反射的基本应用
出现的bug:
Class TestReflection can not access a member of class com.atguigu.gmallrealtime.bean.Person with modifiers “private” at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
利用反射可以做的事情有:
第一类:获取属性名,获取属性值,获取方法
第二类:设置属性值
第三类:创建对象
获取对象的四种方式
- 类型名.class 要求编译期间已知类型
- 对象.getClass() 获取对象的运行时类型
- Class.forName(类型全名称) 可以获取编译期间未知的类型
- ClassLoader的类加载器对象.loadClass(类型全名称)
Bean
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String name;
public int age;
private void privateArgShow(String name){
System.out.println("=================== privateArgShow method ==================");
}
private void privateShow(){
System.out.println("=================== private method ==================");
}
public void publicShow(){
System.out.println("=================== public method =========================");
}
public void publicArgShow(int age){
System.out.println("=================== public method =========================");
}
}
main函数
public class TestReflection {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//获取对象的四种方法
/* (1)类型名.class
要求编译期间已知类型
(2)对象.getClass()
获取对象的运行时类型
(3)Class.forName(类型全名称)
可以获取编译期间未知的类型
(4)ClassLoader的类加载器对象.loadClass(类型全名称)*/
//1. 类名.class
// Class<Person> tClass = Person.class;
//2. Class.forName("全类名")
// Class<?> tClass = Class.forName("com.atguigu.gmallrealtime.bean.Person");
//3. 对象.getClass()
/* Person person = new Person();
Class<? extends Person> tClass = person.getClass();*/
//4.ClassLoader的类加载器对象.loadClass(类型全名称)
Class<?> tClass = ClassLoader.getSystemClassLoader().loadClass("com.atguigu.gmallrealtime.bean.Person");
//1.1创建对象
Object obj = tClass.newInstance();
//1.2获取公共的属性名和方法
//1.2.1获取单个Public属性名
System.out.println("=============获取单个Public属性名===============");
Field age = tClass.getField("age");
System.out.println(age.getName());
//设置属性值,一定要有对象
age.set(obj,12);
//获取属性值
System.out.println(age.get(obj));
//输出对象
System.out.println(obj);
//1.2.2获取所有的Public属性名
System.out.println("=============获取所有的Public属性名===============");
Field[] fields = tClass.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
//1.2.3获取单个Public方法(不含参数)
System.out.println("=============获取单个Public方法(不含参数)===============");
Method method = tClass.getMethod("publicShow");
System.out.println(method.getName());
//调用该方法
method.invoke(obj);
//1.2.4获取单个Public方法(含参数)
/* getMethod(String name, Class<?>... parameterTypes)
name:方法名
parameterTypes:参数类型*/
System.out.println("=============获取单个Public方法(含参数)===============");
Method publicArgShow = tClass.getMethod("publicArgShow", int.class);
System.out.println(publicArgShow.getName());
//调用该方法
publicArgShow.invoke(obj,1);
//1.2.5获取所有Public方法(不含参数)
System.out.println("===============获取所有Public方法(不含参数)=====================");
Method[] methods = tClass.getMethods();
for (Method method1 : methods) {
System.out.println(method1.getName());
//调用该方法 不好写,有的方法有参数,有的方法没有参数
// method1.invoke(obj,1);
}
System.out.println("===================获取私有属性和方法===============================");
//获取私有属性和方法
Field name = tClass.getDeclaredField("name");
System.out.println(name.getName());
//设置访问权限
name.setAccessible(true);
//设置属性值
name.set(obj,"tom");
//获取属性值
System.out.println(name.get(obj));
//获取方法
Method method1 = tClass.getDeclaredMethod("privateArgShow", String.class);
method1.setAccessible(true);
method1.invoke(obj,"abc");
}
}
在获取私有属性和方法的时候,会报错:
是因为方法和属性是私有的,没有访问权限,通过设置访问权限可以解决问题
method1.setAccessible(true);
name.setAccessible(true);
因此访问权限在反射面前是透明的