——java中的反射

来源:互联网 发布:js 数组slice方法 编辑:程序博客网 时间:2024/06/05 22:34

---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------

什么是反射?

一,反射就是把java类中的各个成员,提取成其对应的java类对象。

例如:一个java类中用一个Class类的对象来表示,一个类中的组成部分都有对应的类:

Field —— 成员变量;

Method —— 成员方法;

Constructor —— 构造函数;

Package ——包

二,一个类中的每个成员可以用相对应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些

实例对象,就可以执行相应的操作了。


反射的基石 -- Class类

1,java中的各个java类属于同一类事物,描述这类事物的java类名就是Class。

注:对比:众多人用一个Person类表示,众多的java类就用Class表示

a,一个人  -->Person

b,java类  -->Class

2,Class类代表java类,它的实例对象分别对应什么呢?

1,对应各个类在内存中字节码,例如,String类的字节码,Person类的字节码等。。。

2,一个类被类加载器加载到内存中,占用一片存储空间,这个空间的内容就是类的字节码,不同的类的字节码是不同的,

所以它们在内存中的内容是不同的,这一个个空间分别用一个个的对象来表示,这些对象具有相同的类型即Class类型。

3,如何得到各个字节码对应的实例对象(Class类型)

有3中方式:

1:类名.class;例如:System.class

2:对象名.getClass();例如:new Date().getClass()

3:Class.forName(类的全名称(包名+类名)字符串);例如:Class.forName("java.util.Date");

4,九个预定义Class实例对象:

1,boolean.class = Boolean.TYPE,
2,char.class = Character.TYPE, 
3,byte.class = Byte.TYPE, 
4,short.class = Short.TYPE, 
5,int.class = Integer.TYPE, 
6,long.class = Long.TYPE, 
7,float.class = Float.TYPE, 
8,double.class = Double.TYPE,
9,void.class = Void.TYPE

5,数组类型的Class对象实例对象

1,Class.isArray()

2,总之,只要好似在源程序中出现的类型,都有各自的Class实例对象,例如,int[]

构造函数的反射应用

一,Constructor类代表某个类中的一个构造方法

二,得到某个类所有的构造方法:

示例:Constructor[]  constructors = Class.forName("java.lang.String").getConstructors();

三,得到某一个构造方法://获取时要用到参数类型

示例:Constructor  constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);

四,创建示例对象:

示例:

1,普通方式:String str = new String(new StringBuffer("abc"));

2,反射方式:

Constructor  constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);

String str = (String)constructor.newInstance(new StringBuffer("abc"));

五,Class.newInstance()方法:

1,示例:String obj = (String)Class.forName("java.lang.String").newInstance();

2,该方法内部先得到默认的构造方法,然后用该构造方法来创建实例对象。

3,该方法内部的具体事项代码,用到了缓存机制来保存默认构造方法的示例对象。

构造函数反射的示例代码:



成员变量的反射

Field类表示某个类中的一个成员变量。

语法:

  类名 对象名 = new 类();

  Field field = 对象名.getClass().getField(属性名字符串);

  此时field对象并不代表具体的值,只代表该类下的成员变量的一个对象,

  要获取到指定对象里的成员变量的值,语法如下:

  field.get(对象名);指明要取的成员变量的值属于哪个对象里的。
  
注:一,getField()和getDeclareField()方法的区别:

    getField()方法只能获取到访问级别为可见的属性,不能获取到不可见的属性,若调用该方法

      获取不可见的属性,会报出:notFoundFieldException的异常。

    getDeclareField()方法可以获取该类中声明的所有属性,包括private所修饰的。

    二,使用Field 对象下的get(对象名)来获取该对象下的属性时,如果属性的访问修饰符为不可见时,

     则会报出IllegaAccessException()异常。若要获得不可见的属性的话,可以用以下的方式来强行

     获得,Field对象名.setAccessible(true);设置访问级别为可见。(称为暴力反射)

  例子:将一个类中的所有String类型中的"b"全部换成"a";

注:字节码比较时,要用"=="来比较,因为是同一份字节码。

成员变量反射的实例代码:



成员方法的反射
Method代表某一个类中的一个成员方法

  语法:

Class cls = TestUtil1.class;

TestUtil1 tu1 = (TestUtil1)cls.newInstance();
Method method = cls.getDeclaredMethod("show", null);//指定获取方法名为“show”,并且没有参数的方法

method.invoke(tu1, null);//在对象tu1中执行无参的方法

Method method2 = cls.getDeclaredMethod("show2", null);

method2.invoke(null, null);//当对象参数为null时,表示这是一个静态方法

调用方法的方式:

  一,使用对象名.方法名。调用;

  二,使用反射来获得对应的方法对象,来调用invoke(Object obj,Object...args)执行方法;

其中obj是指那一个对象上的方法,args是表示该方法的参数列表


注:专家模式:哪个类拥有该方法需要的私有数据,那这个方法就属于哪个类。


用反射调用某个类的main方法

  语法:

String className = args[0];//获取第一个参数,首先要设置RunConfigurations中的Arguments为要执行的类的完整类名。

Class cls2 = Class.forName(className);//通过活动到的完整类名,获得该类的字节码

Method main = cls2.getMethod("main", new String[]{}.getClass());//通过字节码,获得该类的main方法

/*

* 因为为了兼容JDK1.4以下的版本,在传入参数的时候,会对参数进行装包;执行时,会对参数进行拆包,如果

* 单纯的传入一个数组的话,则在拆包的时候将每一个元素都拆成一个参数,此时会报出:IllegalArgumentException异常

* 解决方式有以下2种。

*/

//使用一个Object数组,再把传入的数组参数当成Object数组的一个元素在传入。

//main.invoke(null, new Object[]{new String[]{"abc","东方","123"}});

//将传入的参数强转成Object对象,

main.invoke(null, (Object)new String[]{"abc","东方","123"});

成员方法反射的示例代码:



数组的反射,及数组与Object

数组的反射

  1,具有相同位数(例如:一维对一维)和元素类型的数组属于同一个类型,即具有相同的Class实例对象

  2,代表数字的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class

  3,基本类型的一维数组可以被当做Object类型使用,不能当作Object[]类型使用;

     非基本类型的一维数组,既可以当作Object类型使用,又可以当作Object[]类型使用。

  4,Arrays.asList()方法处理int[]和String[]的差异

当处理的是一维的基本数据类型的数组时,其保存的是一维数组的完整名称,即内存中的地址如:[I @a6d7f3。但二维的基本数据类型数组是可以遍历的。

当处理的是引用类型的数组,则会将每一个元素都保存到集合中。

  5,Array工具类用于完成对数组的反射操作。

  6,通过反射获取元素的步骤:

1,获取数组的字节码:对象.getClass()

2,判断是否是数组:字节码对象.isArray()
3,获取数组的长度:getlength(Object obj)

      4,遍历数组元素

      5,通过元素.getClass().getName()方法获取元素对应的类型


数组反射的示例代码:



---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------







































 
0 0
原创粉丝点击