首页 > 代码库 > Java反射技术学习总结

Java反射技术学习总结

  -------<a href=http://www.mamicode.com/"http://www.itheima.com/"">android培训、

 

                      Java反射技术学习总结

 

Java反射技术就是将java中的类的各个组成部分反射出来变为java中相应的数据类型获得。

Java同样将类中的各个组成部分进行封装,变为一个个Java类。

 

Class 字节码类。

其对象对应了Java中的字节码对象。其构造函数私有化。不能直接获得。可以通过以下方式获得。

第一种方式:当该类字节码文件已被加载到内存中时。

 Class    类名.class  或  Class  对象名.getClass().

第二种方式:该类并还没有加载到内存。

Class.forName(String 类的全类名(即包名加类名))。

 

在Java中8个基本数据类型和Void对应了九个预定义的Class对象,用.Class方式获得。

Constructor  构造函数类

对应了Java中的构造函数。

该类同样不能直接new对象。获取该类的对象有两种情形。

一:获取公有的构造函数。

用Class对象的

Construcator   getConstrucator(class<?>.... typs);

二 获取非公有的构造函数

用Class对象的

Construcator   getDeclaredConstrucator(class<?>.... typs);

当我们获取了一个为私有private 修饰的构造函数,如果要使用该构造函数就必须将其设置为可访问状态。用Construcator对象的setAccessible(boolean falg).当参数为true时。该构造函数即为可访问状态。

 

Construcator 中有一个很常用的方法

newInstance(Object...intargs)

利用该构造函数创建一个与之相对的对象。

可以用这个方法创建对象。

 

Filed  成员变量类

该类对应了java中类的成员变量。

该类同样不能直接new对象。获取该类的对象有两种情形。

一:获取公有的用public修饰的Filed。

用Class对象的

Filed   getFiled(String name);

二 获取非公有的Filed

用Class对象的

Filed   getDeclaredFiled(String name);

当我们获取了一个为私有private 修饰的Filed,如果要使用该Filed就必须将其设置为可访问状态。用Filed对象的setAccessible(boolean falg).当参数为true时。该Filed即为可访问状态。

设置成员变量的值

用set(Oject obj,Object vaule)

将该成员变量的所属对象与要设置为的值传入。

Method   方法类

该类对应了Java中的方法,函数。

该类同样不能直接new对象。获取该类的对象有两种情形。

一:获取公有的函数。

用Class对象的

Method   getMethod(String name ,class<?>.... typs);

获取所有的公有方法。

Method[]           getMethods()

 

二 获取非公有的函数

用Class对象的

Method getDeclaredMethod(String name,class<?>.... typs);

当我们获取了一个为私有private 修饰的函数,如果要使用该函数就必须将其设置为可访问状态。用Method对象的setAccessible(boolean falg).当参数为true时。该函数即为可访问状态。

Method 有一个常用方法

 Object

invoke(Object obj, Object... args)
          对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。

 

执行调用该方法

 

暴力反射

何为暴力反射?

当我们用反射技术去获取一些为private修饰的字段,构造函数或方法时,就是暴力反射。

如何暴力反射在上面已讲过了。字段,构造函数,方法都有其获取私有对象的方法。

getDeclaredConstrucator(class<?>.... typs)

getDeclaredMethod(String name,class<?>.... typs)

getDeclaredFiled(String name)

如果要访问,使用私有的字段,构造函数或方法,就将其设为可访问状态。用setAccessible(boolean falg),参数传入true。

 

当我们用反射技术获取一个方法,用invoke(Object obj,Object...args)执行调用该方法时,要注意一种情况,就是该方法的参数是数组这一情形。

 

在JDK1.5之前 Method的invoke 是这样定义的

invoke(Object Object, Object[] obj[]).

现在的定义方法应用了java的新特性——可变参数。但是JDK1.5兼容了老版本。

所以当方法的参数是数组时,如果没有注意到这一点,我们在调用invoke方法时按照新的invoke方法定义的规则传参,将一个数组传入。就会出现参数格式异常。

这是因为JVM看到的参数是数组,就自动调用旧版本的invoke方法(都是兼容惹的祸)。该方法就会将数组拆包,将里面的元素们作为Metod的参数,但Method的参数明明是个数组。

那如何解决这个问题呢?以下代码给出答案

数组的反射

在java中相同维度及数据类型的数组的字节码对象是相等的。看一下下面代码就更清楚了。

int[]arr1=new int[3];

int[]arr2=new int [5];

String[]arr3=new String[]

Int[][]arr4=new int[3][4];

arr1.getClass()==arr2.getClass();true

arr1.getClass()==arr3.getClass();false

arr1.getClass()==arr4.getClass();false

我们都知道Java中所有类的父类都是Object。那么

Object[] obj1=arr3;

Object[] obj2=arr1;

应该是可以的。但实际是Object[] obj2=arr1;

不能通过编译。因为基本数据类型并不是Object类的子类。

这个细节在使用数组工具类Arrays时就有用武之地了。将数组转成集合有一个方法是asList(Object...obj)

当传入的是基本类型数组时,因为基本类型数组不能转换为Object[]。所以JVM不能在调用旧版本的方法asList[Object[] obj].将传入的数组拆包素组里的将元素转为集合里的元素,而是用新版本的方法将整个数组转换为集合里的一个元素。如下面代码

 

解决方法1.将数组的每个元素一个个传入asList方法。

第二种:将基本类型数组转换为其包装类数组。

 

Array 

Array 类提供了动态创建和访问 Java 数组的方法。

Static   Object    get(Object array, int index) 

          返回指定数组对象中索引组件的值。

Static Object newInstance(Class<?> componentType, int length) 

          创建一个具有指定的组件类型和长度的新数组。  

static int getLength(Object array) 

          以 int 形式返回指定数组对象的长度。

 

反射技术多用于框架的编写。我们现在或许没有达到写框架程序的境界,但学好反射有利于我们更好的学习使用一些框架进行编程。

   -------<a href=http://www.mamicode.com/"http://www.itheima.com/"">android培训