一,Class类.
了解反射必须先了解CLass类.
Class类表示java中所有的类.java类是用来描述同一类事物的,而众多的java类也属于同一类事物,这就是Class类.
打个不恰当的比方:造船图纸描述船,造车图纸描述车,造飞机图纸描述飞机.而Class类则描述这些图纸.
1.Class类对应的实例对象.
l一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这就是Class的实例.
2.得到Class实例对象的方法
获得某个类的Class对象的方法有三种
A 类名.class 例如: Person.class
B 对象.getClass() 例如 new Person().getClass();
C CLass.forName("类名") 例如: Class.forName("java.util.Date");
3.九种预定义的
Class
对象也就是八大基本类型(byte,short,int,long,char,float,double,boolean)和void
这些类对象由 Java 虚拟机创建,与其表示的基本类型同名.
int.class==Integer.TYPE 结果为true. Integer.TYPE.isPrimitive()结果为true.
isPrimitive()方法 判定指定的
Class
对象是否表示一个基本类型4.数组类型的Class实例对象.
跟一般的Class实例获取方法一样.
总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void
注意:
静态代码块不是在类加载时被调用的,而是第一个实例对象被创建时才执行的。
二,反射
反射就是把Java类中的各种成分映射成相应的java类。
一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来描述,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。
1.Constructor类表示某个类的构造方法
A.得到某个类所有的构造方法:
例子:Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
B.得到某一个构造方法:
例子:Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
StringBuffer,class是使用该构造方法时需要传入的参数类型
C.创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式: String str = (String)constructor.newInstance(new StringBuffer("abc"));
调用获得的方法时要用到上面相同类型的实例对象
2.Field类表示某个类中的成员变量.
例如 ,一个类ReflectPoint 有x和y两个public的成员变量 构造方法是ReflectPoint(x,y);
ReflectPoint point = new ReflectPoint(1,7);
Field y = point.getClass().getField("y");//这里得到的是y这个成员变量而不是具体的y的值
System.out.println(y.get(point));//调用Field的get方法去获取具体的Field对象的y的值.
如果y是私有的需要用y.getDeclaredField()方法.同时还需要用 y.setAccesible(true);.这就是暴力反射.
3.Method类表示某个类中的成员方法.
3.Method类表示某个类中的成员方法.
A.得到类中的某一个方法:
例子:Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
//charAt是调用的方法名,int.class是要传入的参数的类型.
注意:如果要调用的method需要传入的是多个参数,可以用1.5的可变参数,也可以用1.4的传入数组.
但是如果要把一个数组作为参数传入 则需要将该数组强转为Object.否则会被拆分成若干参数.....
B,调用方法:
通常方式:str.charAt(1);
反射方式: charAt.invoke(str, 1);
•如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!