-------<a href="http://www.itheima.com/"">android培训</a>、<a href="http://www.itheima.com/"
">java培训</a>期待与您交流!----------
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.itheima.com/"">android培训</a>、<a href="http://www.itheima.com/"
">java培训</a>期待与您交流!----------