2019-03-13 | Java | UNLOCK

Java的反射

Java反射

Java反射机制是运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意属性和方法;这种动态获取信息以动态调用对象方法的功能称为java语言的发反射机制。

一个反射的例子

首先定义一个类Robot:

1
2
3
4
5
6
7
8
9
10
11
public class Robot {
private String name;//私有属性
//一个共有方法
public void sayHi(String helloSentence){
System.out.println(helloSentence + " " + name);
}
//一个私有方法
private String throwHello(String tag){
return "Hello "+tag;
}
}

接着使用反射:

获取类方法

1
2
3
4
5
6
7
8
9
10
11
12
public class ReflactSample {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class rc = Class.forName("com.java.deep.reflact.Robot");
Robot r= (Robot) rc.newInstance();//newInstance()返回的是一个泛型对象,需要强转
System.out.println("Class name is "+ rc.getName());
Method getHello = rc.getDeclaredMethod("throwHello", String.class);//获取到一个声明的方法
getHello.setAccessible(true);//可达性设为true,默认是false
Object str = getHello.invoke(r,"Bob");

System.out.println("getHeloo result is "+str);
}
}

rc.newInstance()返回的是一个泛型对象,因此需要强转,又因为强转可能会失败,因此需要抛出异常。通过rc.getDeclaredMethod(“throwHello”, String.class)方法得到一个声明的方法,这个方法第一个参数是方法的名字,第二个是这个方法所需要的参数。并且这个方法也会抛出异常,就是没有字符串中的这个方法存在的时候触发。接着需要将这个方法的可达性设为true,即setAccessible(true),如果不设true一旦是私有的方法将会报错。最后是调用这个方法,使用Invoke调用,并且它会返回一个String类型的Object对象,还需要转换。

如果是调用非私有方法,还可以使用如下的方式:

1
2
3
Method sayHi = rc.getMethod("sayHi", String.class);//只能获取这个类的public方法,还能获取
//继承类的共有方法,也包括一些实现的接口方法
sayHi.invoke(r,"welcome");

此时输出:Welcome null.因为name还没有被赋值

getDeclaredMethodgetMethod的区别:
getDeclaredMethod能够获取到类中的public,private,protected修饰的方法,但是不能获取被继承的方法,也包括它所实现的接口方法。getMethod只能获取这个类的public方法,还能获取继承类的共有方法,也包括一些实现的接口方法。

获取类属性

使用getDeclareField方法可以获得到任意属性,和获取方法一样,如果这个属性是私有的,还需要设置可达性。

1
2
3
Field name = rc.getDeclaredField("name");
name.setAccessible(true);
name.set(r,"Alice");

评论加载中