java中的反射,是指在运行时,对于任意一个类,都可以知道这个类的所有属性和方法,对于任意一个对象,都能调用该对象的所有属性和方法。
反射机制主要提供了如下功能,
在运行时:
- 判断一个对象所属的类
- 构造一个类的对象
- 判定一个类的成员变量和方法
- 调用一个对象的方法
- 生成动态代理
判断一个对象所属的类
根据对象获取该类,或者根据类名获得该类的Class对象。
A t = new B();
Class c1 = t.getClass();
Class c2 = B.class;
Class c3 = null;
try {
c3 = Class.forName("B");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c1 == c2); //true
System.out.println(c1 == c3); //true
System.out.println(c1); //class B
class A{}
class B extends A{}
判断该对象的父类和接口方法如下:
A t = new B();
Class c1 = t.getClass();
System.out.println(c1.getSuperclass());
System.out.println(c1.getInterfaces()[0]);
构造一个类的对象
首先需要获得该类的Class实例,然后通过newInstance()方法或者getConstructors()方法进行实例化。
//使用newInstance()赋值
try {
Class classB = B.class;
B b = (B)classB.newInstance();
System.out.println(b.i); //2
} catch(InstantiationException e){
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
class A{}
class B extends A implements I{
public int i = 2;
}
//使用getConstructors()赋值
Class classB = B.class;
Constructor<?> cons[] = classB.getConstructors();
for (int i = 0; i < cons.length; i++) {
Class<?> clazzs[] = cons[i].getParameterTypes();
System.out.print("cons[" + i + "] (");
for (int j = 0; j < clazzs.length; j++) {
System.out.print(clazzs[j].getName()+" ");
}
System.out.println(")");
}
//上述的输出结果如下:
//constructor [0]:(int )
//constructor [1]:(int int )
try {
B b = (B) cons[2].newInstance(3, 5);
System.out.println(b.i); //3
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
class A{}
class B extends A implements I{
public int i = 2;
public B(int i){
this.i = i;
}
public B(int i, int j){
this.i = i;
}
}
两者的不同在于,前者是使用Class的newInstance()方法进行初始化,不带参数;后者使用Constructor的newInstance()方法进行初始化,可以带参数。
其中,第二个方法的代码使用了Constructor的getConstructors方法,该方法返回的是参数的类型。注意,参数的类型也是类,因此返回的参数类型是Class<T>
。
判定类的成员变量和方法
Class classA = A.class;
//输出属性
Field[] fields = classA.getFields();
for (Field field:fields ){
Class type = field.getType();
String prive = Modifier.toString(field.getModifiers());
System.out.println(prive+" "+type.getName()+" "+field.getName());
}
//public java.lang.String i4
//public double i5
//输出方法
Method method[] = classA.getDeclaredMethods();
for (int i = 0; i < method.length; ++i) {
Class<?> returnType = method[i].getReturnType();
Class<?> para[] = method[i].getParameterTypes();
int temp = method[i].getModifiers();
System.out.print(Modifier.toString(temp) + " ");
System.out.print(returnType.getName() + " ");
System.out.print(method[i].getName() + " ");
System.out.print("(");
for (int j = 0; j < para.length; ++j) {
System.out.print(para[j].getName() + " " + "arg" + j);
if (j < para.length - 1) {
System.out.print(",");
}
}
System.out.println(")");
}
//public java.lang.String toString (java.lang.String arg0)
//public int size ()
// void eat (java.lang.String arg0)
class A{
private int i1;
protected Integer i2;
int i3;
public String i4;
public double i5;
public A(){}
public int size(){return 0;}
void eat(String s){
System.out.println("eats");
}
public String toString(String name){
System.out.println(name+":A");
return name+"A";
}
}
调用一个对象的方法
调用对象的方法和修改属性。即使属性是私有的,也可以修改。
Class classA = A.class;
Method m1 = classA.getDeclaredMethod("eat",String.class);
m1.invoke(classA.newInstance(), "rice");//eats rice
A a = (A) classA.newInstance();
Field i = classA.getDeclaredField("i1");
i.setAccessible(true);
i.set(a, 4);
System.out.println(i.get(a)); //4
class A{
private int i1;
public A(){}
void eat(String s){
System.out.println("eats "+s);
}
}