反射
将类的各个组成部分封装成对象
优点:
- 可以在程序运行中操作这些对象
- 解耦,提高程序扩展性
1类对象的三种获取方式:
- Class.forName():将字节码文件加载进内存,多用于配置文件
- 类名.class 类已经被加载,多用于参数传递
- 对象.getClass: 对象已经创建,多用于对象获取字节码
public class User {
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public User() {
}
}//省略构造方法和setget方法
public class ReflectDemo {
public static void main(String[] args) throws Exception{
Class<?> user = Class.forName("com.leishida.User");
System.out.println(user);
Class<User> userClass = User.class;
System.out.println(userClass);
User u = new User("ljx", 19);
System.out.println(u.getClass());
System.out.println(user == userClass);
System.out.println(userClass == u.getClass());
}
/**
* class com.leishida.User
* class com.leishida.User
* class com.leishida.User
* true
* true
*/
}
2 使用class对象
获取功能
- 获取成员变量
- getFields,获取public修饰的成员变量
- getField,获取指定名称的public修饰的成员变量
- getDeclaredFields,获取所有成员变量,不考虑修饰符
- getDeclaredField,获取指定名称的成员变量,不考虑修饰符
获取后操作:
- 获取操作:get
- 设置操作:set
public class ReflectDemo2 {
public static void main(String[] args) throws Exception{
Class<User> userClass = User.class;
Field[] fields = userClass.getFields();
for (Field field : fields) {
System.out.println(field); //public java.lang.String com.leishida.User.a
}
Field a = userClass.getField("a"); //public java.lang.String com.leishida.User.a
System.out.println(a);
User user = new User();
Object o = a.get(user);
System.out.println(o);//null
a.set(user,"test");
System.out.println(user);//User{name='null', age=0, a='test', b='null', c='null', d='null'}
}
}
public void getDeclaredField(){
Field[] declaredFields = userClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
/**
* private java.lang.String com.leishida.User.name
* private int com.leishida.User.age
* public java.lang.String com.leishida.User.a
* protected java.lang.String com.leishida.User.b
* java.lang.String com.leishida.User.c
* private java.lang.String com.leishida.User.d
*/
}
设置私有成员变量:
在访问或修改私有成员变量时需要设置忽略访问修饰符安全检查
@Test
public void setPrivate() throws Exception{
Field d = userClass.getDeclaredField("d");
//暴力反射
d.setAccessible(true);
Object value = d.get(user);
System.out.println(value); //null
d.set(user,"暴力设置");
System.out.println(user); //User{name='null', age=0, a='null', b='null', c='null', d='暴力设置'}
}
- 获取构造方法
- getConstructors
- getConstructor
- getDeclaredConstructors
- getDeclaredConstructor
@Test
public void getContructors() throws Exception{
Constructor constructor = userClass.getConstructor(String.class, int.class);
System.out.println(constructor); //public com.leishida.User(java.lang.String,int)
//创建对象
Object user1 = constructor.newInstance("反射创建", 18);
System.out.println(user1); //User{name='反射创建', age=18, a='null', b='null', c='null', d='null'}
//如果要使用空参构造器可以直接使用Class下的newInstance的方法
}
访问修饰符部分同上
- 获取成员方法
- getMethods
- gettMethod
- getDeclaredtMethods
- getDeclaredtMethod
@Test
public void getMethods() throws Exception{
// 获取指定参数列表的方法
Method method = userClass.getMethod("say", String.class);
method.invoke(user, "sayHello"); //执行user的eat方法 sayHello
Method[] methods = userClass.getMethods();
for (Method method1 : methods) {
System.out.println(method1); //会默认打印父类的方法
System.out.println(method1.getName()); //打印方法名
}
String className = userClass.getName();
System.out.println(className); //打印类名 com.leishida.User
}
- 获取类名
- getName