“反射”听这个名字有点高级的样子,它实际的作用是什么呢,就是可以在程序运行时去加载某个类,或去调用某个类里面的方法(这是我的理解)
先上代码,有个初步认识:
//这是最简单的Bean
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//反射,最常用的大概就是这些。
public class ReflectTest {
public static void main(String[] args){
try {
/*获取class的几种方法*/
Class c1 = Class.forName("com.smc.test.User");
Class c2 = User.class;
User user3 = new User();
Class c3 = user3.getClass();
System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c3.getName());
/*遍历class里面的所有方法*/
Field[] fs = c1.getDeclaredFields();
StringBuffer sb = new StringBuffer();
for(Field field : fs){
sb.append(Modifier.toString(field.getModifiers())+" ");
sb.append(field.getType().getName() + " " );
sb.append(field.getName() + ";\n");
}
System.out.println(sb.toString());
/*根据name来获取class里面的某个field*/
Field fieldName = c1.getDeclaredField("name");
Object user = c1.newInstance();
fieldName.setAccessible(true);
fieldName.set(user, "xiaoming");
System.out.println(((User)user).getName());
/*根据name来获取class里面的某个method*/
Method methodSetName = c1.getDeclaredMethod("setName", String.class);
Method methodGetName = c1.getDeclaredMethod("getName", null);
methodSetName.invoke(user, "honghong");
String name = (String) methodGetName.invoke(user, null);
System.out.println("name = " + name);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
反射获取Class
反射的操作,基本都是基于java.lang.Class类来进行的,那么如何来获取Class对象呢。一般来说,就这三种方法。
//第一种,调用Class的静态方法(forName)来获取,传入需要反射类的完整路径。
Class c1 = Class.forName("com.smc.test.User");
//第二种,直接使用目标类.class来获取
Class c2 = User.class;
//第三种,调用目标类实例的getClass()方法,(这里我不明白,都获取到实例了,为什么还要反射呢。)
User user3 = new User();
Class c3 = user3.getClass();
使用反射来获取里面的某个Field
Field应该知道的吧,就是类里面的参数,变量,属性。
//通过之前获取到的Class实例,调用getDeclaredField()方法,传入需要反射Field的名称,这里是“name”,这样就获取对应的Field了。
Field fieldName = c1.getDeclaredField("name");
//然后给Class,实例一个目标类出来,毕竟要操作里面的属性了。
Object user = c1.newInstance();
//先要调用Field的setAccessible(true)方法,这样就可以给里面的私有属性赋值了。
fieldName.setAccessible(true);
//最后一步,调用Field方法的set()方法,传入目标类实例对象,和需要设置属性的值。最后看一下属性有没有被设置进去。
fieldName.set(user, "xiaoming");
System.out.println(((User)user).getName());
使用反射来调用方法
//这里通过Class实例调用getDeclaredMethod()传入method的名字和参数(这里必须要传正确,因为有方法重载的可能性),就得到了Method实例。
Method methodSetName = c1.getDeclaredMethod("setName", String.class);
//没有参数就传null
Method methodGetName = c1.getDeclaredMethod("getName", null);
//然后调用invoke()方法,将操作对象和变量值传入,方法就调用成功了,
methodSetName.invoke(user, "honghong");
String name = (String) methodGetName.invoke(user, null);
//最后再试一下,成功了没有
System.out.println("name = " + name);
灵活使用反射,会使开发变得更加灵活,但是不要依赖反射,毕竟反射不是主流开发,效率上来讲,没有直接使用高。