文章目录
一、什么是反射
能够分析类信息的能力叫反射,通过反射能得到一个类对象(存储类的信息)
类信息简单来说就是,类的属性、方法、构造器
类加载器:将类拉到内存里面
二、获取类对象的方法
三种方法获取类对象:
-
Class.forNname()——返回一个类对象,类拿不到,对象也拿不到
-
Class.forName(“类全名”)类全名:包名+类名,多用于配置文件,将类名定义在配置文件中,读取文件,加载类
public class Parent { public int age = 30; public void sleep(){ } }
public class MainTest { public static void main(String[] args) throws ClassNotFoundException{ //通过反射获取Class对象 Class cla = Class.forName("com.test01.Parent"); System.out.println(cla); Field[] fields = cla.getFields(); //拿到类的属性 for(Field field:fields){ System.out.println(field); //打印类的属性 } } }
-
-
类.class——可以拿到类,通过这种方式获取类的信息
-
类.class多用于参数的传递
//通过类名.class Class cla1 = Parent.class;
-
-
对象.getClass()——可以拿到对象
-
对象.getClass()多用于使用对象获取
//通过对象来获取,对象.getClass() Parent parent = new Parent(); Class cla2 = parent.getClass();
-
同一个类在一次程序运行过程中只会被加载一次,通过三种方式获取的类对象是同一个
System.out.println(cla == cla1); //true
System.out.println(cla2 == cla1); //true
三、类对象常用的功能
首先创建一个Parent类作为示例
public class Parent {
public String name;
private int age;
public Parent() {
}
public Parent(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Parent{" +
"name='" + name + '\'' +
", 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;
}
}
3.1 使用构造方法
步骤:
- 通过使用getConstructor()获得构造方法对象(无参),可以根据构造方法参数类型的不同,传入对应类型的类对象,即可获取指定构造方法
- 使用newInstance()创建对象,如果有参构造方法对象,可以传入实际参数值
说明:
-
如果使用无参构造方法,此操作可以简化:类对象.newInstance()来创建对象,例如cla.newInstance();
-
获取所有构造方法对象getConstructors()
-
getDeclaredConstructors() //获取所有构造方法,公共非公共
-
getDeclaredConstructor() //获取构造方法,公共非公共
注意:非公共构造方法有效使用需要使用setAccessible(true),忽略安全访问修饰符的安全检查(暴力反射)
Class cla = Class.forName("com.test01.Parent");
Constructor[] constructorArr = cla.getConstructors();
for(Constructor i:constructorArr){
System.out.println(i);
}
3.1.1 获取无参构造方法对象
//通过反射获取Class对象
Class cla = Class.forName("com.test01.Parent");
//获取构造方法对象
Constructor constructor = cla.getConstructor();
//获取对象
Object object = constructor.newInstance();
System.out.println(object);
3.1.2 获取有参构造方法对象
//获取构造方法对象
Constructor constructor1 = cla.getConstructor(String.class,int.class);
//获取对象
Object object1 = constructor1.newInstance("张三",30);
System.out.println(object1);
输出结果为:
3.2 获取类的成员变量
3.2.1 获取指定公共成员变量
getField()获取指定成员变量对象,可以根据指定成员变量名称
设置值set(Object obj,Object value)
获取值get(Object obj)
//通过反射获取Class对象
Class cla = Class.forName("com.test01.Parent");
//获取指定成员变量name
Object obj2 = cla.newInstance();
Field field = cla.getField("name");
field.set(obj2,"李明");
System.out.println(field.get(obj2));
3.2.2 获取所有公共成员变量
获取所有成员变量对象getFields()
Field[] fields = cla.getFields();
for(Field field1:fields){
System.out.println(field1);
}
//输出只有public java.lang.String com.test01.Parent.name
3.2.3 获取所有成员变量
getDeclaredFields()
Field[] fields = cla.getDeclaredFields();
for(Field field1:fields){
System.out.println(field1);
}
//输出:
//public java.lang.String com.test01.Parent.name
//private int com.test01.Parent.age
3.2.4 获取指定成员变量(公共和非公共)
getDeclaredField()
非公共成员变量有效使用需要使用setAccessible(true),忽略安全访问修饰符的安全检查(暴力反射)
//获取指定成员变量age
Object obj2 = cla.newInstance();
Field field = cla.getDeclaredField("age");
field.setAccessible(true);
field.set(obj2,10);
System.out.println(field.get(obj2));
3.3 获取类的方法
3.3.1 获取指定公共方法对象
获取指定公共方法对象getMethod() 可以根据方法名以及参数类型对应的类对象可以指定获取
调用方法 invoke(Object object,Object args…)
3.3.2 获取所有公共方法对象
获取所有公共方法对象getMethods()
3.3.3 获取所有方法对象
getDeclaredMethods()
3.3.4 获取指定成员变量(公共和非公共)
getDeclaredMethod()
非公共方法有效使用需要使用setAccessible(true),忽略安全访问修饰符的安全检查(暴力反射)
//通过反射获取Class对象
Class cla = Class.forName("com.test01.Parent");
Object obj = cla.newInstance();
//获取所有方法对象
Method[] methods = cla.getDeclaredMethods();
for(Method method:methods){
System.out.println(method);
}
//获取指定方法对象
Method set1 = cla.getDeclaredMethod("setName", String.class);
//调用
set1.invoke(obj,"LiMing");
Method get1 = cla.getDeclaredMethod("getName");
System.out.println(get1.invoke(obj));
四、示例
public class CommonReflect {
//获取类的名称
public static void getClassName(Object object){
String className = object.getClass().getSimpleName();
System.out.println("类的名称是"+className);
}
//获取类的成员变量名称
public static void getField(Object object){
Field[] fields = object.getClass().getDeclaredFields();
for(Field i:fields){
System.out.println("该类成员变量名"+i.getName());
}
}
//获取类的方法
public static void getMethod(Object object){
Method[] methods = object.getClass().getDeclaredMethods();
for(Method i:methods){
System.out.println("该类方法名"+i.getName());
}
}
//调用该类的get方法
public static void getAction(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Field[] fields = object.getClass().getDeclaredFields();
for(int i = 0;i < fields.length;i ++){
String fieldName = fields[i].getName();
String suff = fieldName.substring(0,1).toUpperCase();
String methodName = "get" + suff + fieldName.substring(1);
Method method = object.getClass().getDeclaredMethod(methodName);
System.out.println(methodName+"方法调用结果"+method.invoke(object));
}
}
}
public class MainTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Parent parent = Parent.class.getConstructor(String.class,int.class).newInstance("张三",20);
CommonReflect.getClassName(parent);
CommonReflect.getField(parent);
CommonReflect.getMethod(parent);
CommonReflect.getAction(parent);
}
输出结果