前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅析Java RTTI 和 反射的概念

浅析Java RTTI 和 反射的概念

作者头像
JMCui
发布2018-03-15 16:57:31
1.7K0
发布2018-03-15 16:57:31
举报
文章被收录于专栏:JMCuiJMCui

一、概念: RTTI(Run-Time Type Identification,运行时类型识别)的含义就是在运行时识别一个对象的类型,其对应的类是Class对象,怎么理解这个Class对象呢?如果说类是所有对象方法、属性的集合,那就可以把这个Class对象理解成是所有class的集合,然后利用这个Class对象动态的解析出相关类,并可以获得其构造器和方法等,甚至实例化这个类的对象。开始文章前,先提重要的一点:无论是RTTI还是反射,其本质都是一样的,都是去动态的获取类的信息,他们唯一的区别仅是:

  • RTTI 在编译期知道要解析的类型。
  • 反射 在运行期知道要解析的类型。

二、RTTI

有以下两种方式可以获取到Class对象:

代码语言:javascript
复制
    public static void main(String[] args)
    {
        try {
            //第一种方式
            Class rtti = Class.forName("com.jomoo.test.rtti.RTTI");
            //第二种方式
            Class type=RTTI.class;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

 可以看到,采用RTTI的方式必须在写程序的时候就知道了类的名字,才能获取到Class对象对这个类的引用,并利用这个引用,得到大量关于这个类的信息,包括接口,父类,方法,静态成员,甚至是像newInstance()方法这样的一个实现“虚拟构造器”的一种方式。

代码语言:javascript
复制
RTTI r =(RTTI)rtti.newInstance();//newInstance的类必须要有一个缺省构造器

         另外需要提一个经常用到 instanceof 该关键字的调用其实就是使用了Class对象,并且返回一个布尔值。

代码语言:javascript
复制
            Object o = rtti.newInstance();
            if (o instanceof RTTI){
                System.out.println(true);//这里需要注意的是,如果 o 是 RTTI的子类的话,返回的也会true;
            }

三、反射

Java中有时候在编译器为程序生成代码很久之后才会出现要处理的那个类,那么这个时候怎么才能处理这个类呢,即在编译的时候根本无法获知这个对象所属的类。答案就是利用Java的反射机制。废话不多说,看完下面这个代码你就很清楚的明白 RTTI 和 反射的区别在哪里了。

代码语言:javascript
复制
public class RTTI
{
    private  static final String usage="usage";
    private static Pattern pattern=Pattern.compile("\\w+\\.");

    public static void main(String[] args)
    {
        if (args.length<1){
            System.out.println(usage);
            System.exit(0);
        }
        int lines=0;
        try {
            Class c = Class.forName(args[0]);//看这里类的名字在编译的时候是无法得知的,只有在运行的时候动态传进去
            Method[] method = c.getMethods();
            Constructor[] constructors = c.getConstructors();
            if (args.length==1){
                for (int i=0;i<method.length;i++){
                    System.out.println(pattern.matcher(method[i].toString()).replaceAll(""));
                }
                for (int i=0;i<constructors.length;i++){
                    System.out.println(pattern.matcher(constructors[i].toString()).replaceAll(""));
                }
                lines=method.length+constructors.length;
            }else {
                for (int i=0;i<method.length;i++){
                    if (method[i].toString().indexOf(args[1])!=-1){
                        System.out.println(pattern.matcher(method[i].toString()).replaceAll(""));
                    }
                    lines++;
                }
                for (int i=0;i<constructors.length;i++){
                    if (constructors[i].toString().indexOf(args[1])!=-1){
                        System.out.println(pattern.matcher(constructors[i].toString()).replaceAll(""));
                    }
                    lines++;
                }
            }
        } catch (ClassNotFoundException e) {
            System.out.println("NO!!!!");
        }
    }
}

 如何在main方法中带入参数可以参考这篇博客,我用原生的 javac -encoding UTF-8 RTTI.java 和 java RTTI com.jomoo.test.seven.ActionCharacter来运行 竟然报错了:Error: Could not find or load main class RTTI,我的JDK有毒!无奈借助了强大的IDE工具:

四、总结

其实RTTI的概念是在《Thinking in Java》中提到的,才引来这么多人的讨论,原生的Java中并没有这个概念的说法。所以勒,我们根本不必纠结是RTTI还是反射,他们无论用法还是本质都是一样的,都是为了实现一样的目的——动态的获取类的信息,我们应该把重点放在使用上,而不要过多在纠结在差异上。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档