JAVA反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
获取构造方法
getConstructors
getDeclaredConstructors
创建对象
newInstance()
con.newInstance(“zhangsan", 20);
获取所有成员
getFields,getDeclaredFields
获取单个成员
getField,getDeclaredField
修改成员的值
set(Object obj,Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
获取所有方法
getMethods
getDeclaredMethods
获取单个方法
getMethod
getDeclaredMethod
暴力访问
method.setAccessible(true);
常用方法
下面我们通过具体实例来看看如何实现
先创建个student类
public class student {
private String name;//学生姓名
private int age;//学习年龄
public student(String name, int age) {
this.name = name;
this.age = age;
}
public void study(String school){
System.out.println(name+"在"+school+"读书");
}
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 student() {
}
public student(String name){
this.name=name;
}
}
//java如何加载一个类
Class clazz = Class.forName("com.student.study.student");//该类的字节码表示
创建Test类
一个类包括属性,方法还有构造方法
1.获得所有的构造方法
public class Test {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("com.student.study.student");
//1.获得所有构造方法
Constructor[] cs = clazz.getConstructors();
for (Constructor c:cs
) {
System.out.println(c);
}
测试结果
public com.student.study.student()
public com.student.study.student(java.lang.String)
public com.student.study.student(java.lang.String,int)
Process finished with exit code 0
获得单个构造方法
//获得单个构造方法
// Constructor c = clazz.getConstructor(String.class);
Constructor c = clazz.getConstructor();//无参数表示获得无参的构造方法
System.out.println(c);
测试结果
public com.student.study.student()
Process finished with exit code 0
创造对象
Object obj = c.newInstance();
获得属性
//获得属性
Field[] fs = clazz.getDeclaredFields();
for (Field f:fs
) {
System.out.println(f);
}
测试结果
private java.lang.String com.student.study.student.name
private int com.student.study.student.age
Process finished with exit code 0
获得单个属性
Field f = clazz.getDeclaredField("name");
System.out.println(f);
测试结果
private java.lang.String com.student.study.student.name
设置属性值
当需要给private修饰符修饰的属性赋值时,必须要通过setAccessible方法打破封装性
f.setAccessible(true);//突破私有化限制
f.set(obj,"小明");
3.获得方法
Method[] ms = clazz.getDeclaredMethods();
for (Method m:ms
) {
System.out.println(m);
}
测试结果
private java.lang.String com.student.study.student.name
public java.lang.String com.student.study.student.getName()
public void com.student.study.student.setName(java.lang.String)
public void com.student.study.student.study(java.lang.String)
public void com.student.study.student.setAge(int)
public int com.student.study.student.getAge()
获得单个方法
Method m =clazz.getDeclaredMethod("study", String.class);
// //对象.方法(实参)
m.invoke(obj,"华科");
测试结果
private java.lang.String com.student.study.student.name
小明在华科读书