运行时类型信息可以让你在程序运行时发现和使用类型信息。

在Java中运行时识别对象和类的信息有两种方式:传统的RTTI,以及反射。下面就来说说反射。

重点说说通过反射获取方法以及调用方法,即类方法提取器

1、反射:

  如果你不知道一个对象的确定类型,RTTI可以告诉你。但是有个限制:这个类型在编译期间必须已知,才能使用RTTI来识别它。例如,在磁盘上或者网络中的一段字符串,被告知代表一个类,但是编译器在编译代码的时候,并不知道,怎么才能使用这个类呢?这时候就需要使用反射。

  通过反射与未知类型的对象打交道时,JVM只是简单地检查这个对象,看它属于哪个特定的类(与RTTI一样)。但在这之后,在做其它事情之前,必须加载那个类的 Class 对象。因此,那个类的.class 文件对于 JVM 来说必须是可获取的,要么在本地机器上,要么可以通过网络取得。

RTTI:编译器在编译期间打开和检查.class文件

反射:编译器在运行期间打开和检查.class文件

1.1类方法提取器

 1.1.1获取方法

步骤:

  1. 先找到方法所在类的字节码 
  2. 找到需要被获取的方法

Class类中获取方法:

  1. public Method[] getMethods();//获取包括自身和继承(实现)过来的所有的public方法——Method不支持泛型<>,即后面不接<>
  2.  
  3. public Method[] getDeclaredMethods();//获取自身所有的方法(private、public、protected,和访问权限无关),不包括继承的
  4.  
  5. public Method[] getMethod(String methodName, Class<T>...parameterTypes);//表示获取指定的一个公共的方法,包括继承的
  6.  
  7. public Method[] getDeclaredMethod(String methodName, Class<T>...parameterTypes);//表示获取本类中的一个指定的方法(private、protected、public,与访问权限无关),不包括继承的方法

其中参数: methodName:表示获取的方法的名字

parameterTypes:表示获取的方法的参数的Class类型

1.1.2调用方法

步骤:

  1. 先找到方法所在类的字节码

  2. 找到需要被获取的方法

  3. 调用该方法
  1. class User{
  2.  
  3.   public void sayHello(){...}
  4.  
  5.   public void sayHi(String naem){...}
  6.  
  7.   private void sayGoodBye(String name, int age){...}
  8.  
  9. }

如何使用反射调用一个方法?

在Method类中有一个方法:

  1. public Object invoke(Object obj, Object... args);//表示调用当前Method所表示的方法

参数:  obj: 表示被调用方法底层所属对象

args: 表示调用方法时传递的实际参数

返回:方法调用后,底层方法的返回结果

  1. Class<User> clz=User.class;
  2.  
  3. Method mt=clz.getMethod(“sayHi”, String.class);
  4.  
  5. Object obj=clz.newInstance();
  6.  
  7. Object ret=mt.invoke(obj, wili”);//要调用实例方法,必须有一个对象,方法的底层对象就是指当前Method所在的类的实例对象,sayHi方法具有返回值,调用该方法后的返回结果使用Object接收

如何调用私有方法?

  1. Method mt=clz.getDeclaredMethod(“sayGoodBye”, String.class, int.class);
  2.  
  3. //在调用私有方法之前,需设置该方法为可访问的权限:——否则会报错
  4.  
  5. mt.setAccessible(true);
  6.  
  7. mt.invoke(clz.newInstance(), limi”, 17);

如何调用静态方法?

  1. class User{
  2.  
  3. public static void staticMethod(){
  4.  
  5. System.out.println(“static mthod invoke.”);
  6.  
  7. }
  8.  
  9. }
  1. Class<User> clz=User.class;
  2.  
  3. Method staticMethod=clz.getMethod(“staticMthod”);
  4.  
  5. //两种方式调用静态方法:
  6.  
  7. //1. 因为静态方法属于所有实例对象公共的,可以创建该类的一个任意对象,通过该对象调用
  8.  
  9. staticMethod.invoke(clz.newInstance());//staticMethod无参,故参数列表类型不填
  10.  
  11. //2. 如果底层方法是静态的,那么可以忽略指定的obj参数,将obj参数设置为null即可
  12.  
  13. staticMethod.invoke(null);

如何调用可变参数的方法?

  1. class User{
  2.  
  3. public static int sum(int[] ages){
  4. System.out.println(args);//打印结果可看出:可变参数底层就是一个数组
  5. int sum=0;
  6.   for(int i : args){
  7. sum+=i;
  8. }
  9. return sum;
  10. }
  11.  
  12. public static void show(String[] args){...}
  13.  
  14. }
  1. Class<User> clz=User.class;
  2.  
  3. Method m=clz.getMethod(“sum”, int[].class);//可变参数底层就是一个数组
  4.  
  5. M.invoke(null, new int[]{1,2,3});
  6.  
  7. Method m=clz.getMethod(“show”, String[].class);
  8.  
  9. //M.invoke(null, new String[]{“A”,”B”,”C”});//会报错,可变参数是引用类型时,底层会自动解包,上述调用被解包后变成M.invoke(null,“A”,”B”,”C”);——为了解决该问题,我们再使用一层数组把实际参数包装起来
  10.  
  11. M.invoke(null, new Object[]{new String[]{“A”,”B”,”C”}});//正确

通用方法:

以后在使用反射调用invoke方法时,在传递实际参数的时候,无论是基本数据类型,还是引用类型,或者是可变参数类型,把实际参数都包装在一维数组中。

m.invoke(方法的底层对象,new Object[]{实际参数});

  1. m.invoke(null new Object[]{17});//方法参数为基本类型,且只有一个参数,解包后变成m.invoke(null,17});
  2.  
  3. m.invoke(null new Object[]{“xxx”});//方法参数为String类型,且只有一个参数
  4.  
  5. m.invoke(null new Object[]{new int[]{1,2}});//方法参数为int类型,且为可变参数或者数组类型
  6.  
  7. m.invoke(null new Object[]{new String[]{“A”,”B”}});//方法参数为String类型,且为可变参数或者数组类型,new String[]{“A”,”B”}为传递的实际参数

类型信息(RTTI和反射)——反射的更多相关文章

  1. Java基础 -- 深入理解Java类型信息(Class对象)与反射机制

    一 RTTI概念 认识Claa对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RT ...

  2. Java编程思想——第14章 类型信息(二)反射

    六.反射:运行时的类信息 我们已经知道了,在编译时,编译器必须知道所有要通过RTTI来处理的类.而反射提供了一种机制——用来检查可用的方法,并返回方法名.区别就在于RTTI是处理已知类的,而反射用于处 ...

  3. Java 类型信息详解和反射机制

    本文部分摘自 On Java 8 RTTI RTTI(RunTime Type Information)运行时类型信息,能够在程序运行时发现和使用类型信息,把我们从只能在编译期知晓类型信息并操作的局限 ...

  4. Thinking in Java -- 类型信息RTTI

    Thinking in Java – 类型信息 个人感觉 java 中的比較难的部分了,在看了些netty源代码发现事实上这块很实用. 这章重点是RTTI和反射.先说下自己的理解 RTTI是执行时识别 ...

  5. 了解运行时类型信息(RTTI)

    RTTI需要引用单元TypeInfo GetPropInfo 函数用于获得属性的 RTTI 指针 PPropInfo.它有四种重载形式,后面三种重载的实现都是调用第一种形式.AKinds 参数用于限制 ...

  6. Java类型信息(RTTI和反射)

    要想在IT领域站得住脚,必须得不断地学习来强化自己,但是学过的技术不实践很容易便被遗忘,所以一直都打算开个博客,来记录自己学的知识,另外也可以分享给有需要的人! 最近在学习反射,为了更好地理解反射,就 ...

  7. JAVA类型信息——Class对象

    JAVA类型信息——Class对象 一.RTTI概要 1.类型信息RTTI :即对象和类的信息,例如类的名字.继承的基类.实现的接口等. 2.类型信息的作用:程序员可以在程序运行时发现和使用类型信息. ...

  8. JAVA类型信息——Class对象(转载)

    JAVA类型信息--Class对象 一.RTTI概要 1.类型信息RTTI :即对象和类的信息,例如类的名字.继承的基类.实现的接口等. 2.类型信息的作用:程序员可以在程序运行时发现和使用类型信息. ...

  9. 20190908 On Java8 第十九章 类型信息

    第十九章 类型信息 RTTI(RunTime Type Information,运行时类型信息)能够在程序运行时发现和使用类型信息. Java 主要有两种方式在运行时识别对象和类信息: "传 ...

随机推荐

  1. ubuntu 搭建django 环境

    ubuntu 默认安装了 python2.7 . 安装django apt install python-django: 安装mysql apt install mysql-server*  *代表版 ...

  2. java程序员的从0到1:@Resource与@Autowired的比较

    目录: 1.@Resource与@Autowired的源码分析 2.@Resource与@Autowired的相同点 3.@Resource与@Autowired的不同点 正文: 1.@Resourc ...

  3. sharepoint_study_8

    描述:如何删除webPart无效文件? 图示: 有时候webpart的部署包虽然删除了,但是它的文件依然会留在这个类别中,怎样删除这些无效的文件呢? 解决: 在网站设置中打开web部件,里面列出了网站 ...

  4. windows_study_2

    描述:如何确定像%ProgramFiles%这样格式的目录的具体位置? 解决:运行——cmd——echo %ProgramFiles%——回车——界面就显示出目录位置了.

  5. vs如何在Windows身份验证下调试Web项目

    vs做的Web项目发布到IIS站点后,通常我们还希望利用vs来调试代码.如果Web在IIS中设置成了Windows身份验证,那么我们如何在vs调试的时候,也同样采用Windows身份认证进行调试呢? ...

  6. Gym - 101572G Galactic Collegiate Programming Contest 小根堆(set)

    题目传送门 题目大意: n个人,m次提交,每次提交都代表某支队伍做出一题,并且给出罚时,让你输出每次提交后,编号为1的队伍的排名. 思路: 首先处理ac和罚时,由于罚时最大1000,最多有1e5次,要 ...

  7. Java字符容量capacity()方法

    Java字符容量计算:比如StringBuffer sb=new StringBuffer("Good");输出 .

  8. java——利用生产者消费者模式思想实现简易版handler机制

    参考教程:http://www.sohu.com/a/237792762_659256 首先说一下这里面涉及到的线程: 1.mainLooper: 这个线程可以理解为消费者线程,里面运行了一个死循环, ...

  9. vue 中使用driver.js来进行页面分步引导

    Driver.js 推荐15款最佳的 jQuery 分步引导插件 11 个超棒的 jQuery 分步指引插件

  10. 使用PyCharm实现远程编写并调试代码

    使用PyCharm实现远程编写并调试代码 版权声明:本文为博主原创文章,转载请注明出https://www.cnblogs.com/wenqiangit/p/9771947.html 因为工作中使用的 ...