一提到反射,那么就要想到是运行时的事,而不是编译时的事.
在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制
Java 反射机制主要提供了以下功能:(注意都是运行时的)
•在运行时判断任意一个对象所属的类。
•在运行时构造任意一个类的对象。
•在运行时判断任意一个类所具有的成员变量和方法。
•在运行时调用任意一个对象的方法
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
–Class类:代表一个类。
–Field 类:代表类的成员变量(成员变量也称为类的属性)。
–Method类:代表类的方法。
–Constructor 类:代表类的构造方法。
–Array类:提供了动态创建数组,以及访问数组的元素的静态方法
Java中,无论生成某个类的多少个对象,这些对象都会对应于同一个Class对象,如Integer生成很多个对象,那这些对象都会对应于Integer这个类所对应的Class对象
Class是Reflection起源。针对任何您想探勘的class,唯有先为它产生一个Class object,接下来才能经由后者唤起为数十多个的Reflection APIs
获取某个类或某个对象所对应的Class对象的常用的3种方式:
a) 使用Class类的静态方法forName:Class.forName(“java.lang.String”);
b) 使用类的.class语法:String.class;
c) 使用对象的getClass()方法:String s = “aa”; Class<?> clazz = s.getClass();
若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
a) 先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可:
Class<?> classType = String.class;
Object obj = classType.newInstance();
b) 先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{String.class, int.class});
Object obj = cons.newInstance(new Object[]{“hello”, 3});
对于Method:
得到它的方法:那么就要得到它的那个方法所对应的Method对象.getMethod(,)这个方法可以唯一的确定你是调用那个方法,由它后面的那个参数决定.前面那个是方法名,后面那个是方法的参数类型的class,代码如下:
Class<?> classType = InvokeTester.class;
Object invokeTester = classType.newInstance();
// System.out.println(invokeTester instanceof InvokeTester);
Method addMethod = classType.getMethod("add", new Class[] { int.class, int.class });
Object result = addMethod.invoke(invokeTester, new Object[]{1, 2});
注意反射总是返回Object类型及其子类型,原生数据类型则是它的包装类.
通过反射可以在类的外边调用类的私有方法.
method.setAccess...方法,这个方法是它的父类的方法.它压制JAVA对访问修饰符的检查.
getDeclaredMethod与getMethod方法的区别是前者连private的成员都可以得到,而后者只得到public的.
Field的使用跟Method的是大同小异的
注意的是:Integer.TYPE返回的是它的原生数据类型的Class对象,Integer.class才是真正返回的是Integer的Class对象.
数组本身也是对象,Array.newInstance()可以生成一个数组对象.
public class ArrayTester2
{
public static void main(String[] args)
{
int[] dims = new int[] { 5, 10, 15 };//这个数组是代表是维度.
Object array = Array.newInstance(Integer.TYPE, dims);//创建了一个三维数组,长,宽,高分别为5,10,15.
System.out.println(array instanceof int[][][]);
Object arrayObj = Array.get(array, 3);
arrayObj = Array.get(arrayObj, 5);
Array.setInt(arrayObj, 10, 37);
int[][][] arrayCast = (int[][][]) array;
System.out.println(arrayCast[3][5][10]);//打印出37来
// System.out.println(Integer.TYPE);
// System.out.println(Integer.class);
}
}