最近开发中要用到Java反射技术,整理下帮助自己回忆。
1.Java反射技术
Java反射:是指动态的获取指定的类,以及动态的调用类中的内容。
2.Java反射技术的意义
提高了程序的可扩展性。
3.举例释义
3.1 字节码文件对象
Java中万物皆对象,一个java类经过编译后会生成对应的.class文件即二进制的字节码文件,JVM加载进内存解析的就是这个.class文件,为了更好的描述和管理字节码文件就需要将其抽象为某种类型即Class类,Class类中包含有如下内容:
1)Field field :描述类成员变量的对象
2)Constructor constructor :描述类构造器的对象
3)Method method :描述类成员方法的对象
4)一系列获取上述各个字段的方法,如: getField()、getConstructor()、getMethod()。
3.2 定义Person类
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
this.name = name;
this.age = 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 String showInfo(String name,int age){
return "name="+name+";age="+age;
}
public static void staticShow(){
System.out.println("static method invock");
}
}
3.3 获取字节码文件对象的三种方式:
方式一:通过类对象获取
Person person = new Person();
Class<Person> clazz = (Class<Person>) person.getClass();
方式二:通过类本身获取
Person person = new Person();
//Class<Person> clazz = (Class<Person>) person.getClass();
Class<Person> clazz = Person.class;
方式三:通过类的全限定名获取
Person person = new Person();
//Class<Person> clazz = (Class<Person>) person.getClass();
//Class<Person> clazz = Person.class;
Class<Person> clazz = (Class<Person>) Class.forName("com.cn21.model.Person");
4.通过字节码文件对象创建其所表示的类对象
方式一:如果类中有无参构造函数,可用如下方式:
Class<?> clazz = Class.forName("com.cn21.model.Person");
Person person = (Person) clazz.newInstance();
System.out.println(person);
打印结果:
方式二:如果类中没有无参构造函数,可用如下方式:
Class<?> clazz = Class.forName("com.cn21.model.Person");
//Person person = (Person) clazz.newInstance();
Constructor<?> constructor = clazz.getConstructor(String.class,int.class);
Person p = (Person) constructor.newInstance("小明",21);
System.out.println("name="+p.getName()+";age="+p.getAge());
打印结果:
4.1 反射技术获取类的成员变量
Class<?> clazz = Class.forName("com.cn21.model.Person");
//1.getField()方法只能获取公有的成员变量,否则会报NoSuchFieldException异常
//2.获取私有的成员变量需要使用getDeclaredField()方法
Field field = clazz.getDeclaredField("name");
//给私有成员变量设置值时,需要取消java语言访问控制检查
//设置为true取消访问控制检查,false表示进行访问控制检查
field.setAccessible(true);
Person p = (Person) clazz.newInstance();
field.set(p, "小明");
//打印name设置的值
System.out.println(field.get(p));
打印结果:
1.实例方法调用:
Class<?> clazz = Class.forName("com.cn21.model.Person");
//通过方法名获取特定的成员方法
Method method = clazz.getMethod("showInfo",String.class,int.class);
Object obj= clazz.newInstance();
Object result = method.invoke(obj,"小明",21);
System.out.println(result);
打印结果:
2.静态成员方法调用:
Class<?> clazz = Class.forName("com.cn21.model.Person");
//通过方法名获取特定的成员方法
Method method = clazz.getMethod("staticShow",null);
//Object obj= clazz.newInstance();
method.invoke(null,null);
打印结果:
总结:水平有限,有错误之处望批评指正,欢迎交流。