JAVA反射
一、什么是反射
反射就是把java类中的各种成分映射成一个个的Java对象
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
反射的本质是得到class对象后,反向获取对象的各种信息
当我们通过 new User()创建对象的时候,jvm会加载我们的user.class,jvm会到磁盘中找到user.class加载到jvm内存中,一个类只会产生一个class对象
二、反射的应用
2.1 Class类
每个类在Java中都对应着一个Class对象,这个对象保存了该类的结构信息,如类名、字段、方法等。简言之,Class类是一个反射工具,能提供很多方法用于获取类的各种信息,比如获取类名、判断该类是否是一个接口还是普通类等等。
Class的一些常用方法
//获取成员变量
getFields()//获取所有公开(public)的成员变量,包括继承变量
getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量
getField(变量名)//获取指定公共属性的Field对象
getDeclaredField(变量名)//获取指定包括私有,不包括继承的Field对象
//获取成员方法
getMethods()//获取所有可见的方法,包括继承的方法
getMethod(方法名,参数类型列表)//获取指定方法的Method对象
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
getDeclaredMethod(方法名,int.class,String.class)//获取指定包括私有,不包括继承的Method对象
//获取构造方法
getConstructor(参数类型列表)//获取公开的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
getDeclaredConstructor(int.class,String.class)//获取指定包括私有,不包括继承的Constructor对象
//其他方法
getInterfaces()//返回一个包含class对象的数组,存放该类或者接口实现的接口
newInstance()//使用无参构造创建一个类的实例
getName()//返回该类的完整名
User类
package com.ruoyi.system.domain;
public class User {
private String name;
public Integer id;
protected String sex;
}
2.2 获取类的成员变量
package com.ruoyi.system.domain;
import java.lang.reflect.Field;
public class JavaReflect {
public static void main(String[] args) throws NoSuchFieldException {
Class<User> userClass = User.class;
//获取所有公开的成员变量,包括继承变量
Field userFields[] = userClass.getFields();
System.out.println("通过getFields获取User所有公开的成员变量,包括继承变量");
for(Field f: userFields){
System.out.println("属性类型" + f.getType() + "属性名称:" +f.getName());
}
Field userDeclaredFields[] = userClass.getDeclaredFields();
System.out.println("通过getDeclaredFields获取User获取本类定义的成员变量,包括私有,但不包括继承的变量");
for(Field f: userDeclaredFields){
System.out.println("属性类型" + f.getType() + "属性名称:" +f.getName());
}
Field userFieldsByName = userClass.getField("id");
System.out.println("通过getField(变量名)获取User的指定公共属性的Field对象");
System.out.println("属性类型" + userFieldsByName.getType() + "属性名称:" +userFieldsByName.getName());
}
}
运行结果
通过getFields获取User所有公开的成员变量,包括继承变量
属性类型class java.lang.Integer属性名称:id
通过getDeclaredFields获取User获取本类定义的成员变量,包括私有,但不包括继承的变量
属性类型class java.lang.String属性名称:name
属性类型class java.lang.Integer属性名称:id
属性类型class java.lang.String属性名称:sex
通过getField(变量名)获取User的指定公共属性的Field对象
属性类型class java.lang.Integer属性名称:id
2.3 获取成员方法
public static void main(String[] args) throws NoSuchMethodException {
Class<User> userClass = User.class;
System.out.println("通过getMethods()获取所有公开方法");
Method[] methods = userClass.getMethods();
for(Method m : methods){
System.out.print("方法名称 :" + m.getName() +" ");
Class[] plts = m.getParameterTypes();
System.out.println("参数列表为");
for(Class p : plts){
System.out.print(p.getTypeName() + " ");
}
}
System.out.println();
System.out.println("getDeclaredMethods()获取所有方法(包括私有,不包括继承)");
Method[] methods2 = userClass.getDeclaredMethods();
for(Method m : methods2){
System.out.print("方法名称 :" + m.getName() +" ");
Class[] plts = m.getParameterTypes();
System.out.println("参数列表为");
for(Class p : plts){
System.out.print(p.getTypeName() + " ");
}
}
System.out.println();
System.out.println("getMethod(\"getId\",Integer.class)获取setId");
Method methods3 = userClass.getMethod("setId",Integer.class);
System.out.print("方法名称 :" + methods3.getName());
Class[] plts = methods3.getParameterTypes();
System.out.print("参数列表为");
for(Class p : plts){
System.out.print(p.getTypeName() + " ");
}
System.out.println();
System.out.println("getDeclaredMethod(\"getId\",Integer.class)获取setName");
Method methods4 = userClass.getDeclaredMethod("setName",String.class);
System.out.print("方法名称 :" + methods4.getName());
Class[] plts2 = methods4.getParameterTypes();
System.out.print("参数列表为");
for(Class p : plts2){
System.out.print(p.getTypeName() + " ");
}
}
通过getMethods()获取所有公开方法
方法名称 :getId 参数列表为
方法名称 :setId 参数列表为
java.lang.Integer 方法名称 :wait 参数列表为
方法名称 :wait 参数列表为
long int 方法名称 :wait 参数列表为
long 方法名称 :equals 参数列表为
java.lang.Object 方法名称 :toString 参数列表为
方法名称 :hashCode 参数列表为
方法名称 :getClass 参数列表为
方法名称 :notify 参数列表为
方法名称 :notifyAll 参数列表为
getDeclaredMethods()获取所有方法(包括私有,不包括继承)
方法名称 :getName 参数列表为
方法名称 :getId 参数列表为
方法名称 :setName 参数列表为
java.lang.String 方法名称 :setSex 参数列表为
java.lang.String 方法名称 :setId 参数列表为
java.lang.Integer 方法名称 :getSex 参数列表为
getMethod(“getId”,Integer.class)获取setId
方法名称 :setId参数列表为java.lang.Integer
getDeclaredMethod(“getId”,Integer.class)获取setName
方法名称 :setName参数列表为java.lang.String
2.4 获取构造函数
public static void main(String[] args) throws NoSuchMethodException {
Class<User> userClass = User.class;
System.out.println("getConstructor()获取所有公开构造方法");
Constructor[] con1 = userClass.getConstructors();
for(Constructor c : con1){
System.out.print("构造方法名称 :" + c.getName() +" ");
Class[] plts = c.getParameterTypes();
System.out.print("参数列表为:");
for(Class p : plts){
System.out.print(p.getTypeName() + " ");
}
System.out.println();
}
System.out.println("getDeclaredConstructors()获取所有构造方法");
Constructor[] con2 = userClass.getDeclaredConstructors();
for(Constructor c : con2){
System.out.print("构造方法名称 :" + c.getName() +" ");
Class[] plts = c.getParameterTypes();
System.out.print("参数列表为:");
for(Class p : plts){
System.out.print(p.getTypeName() + " ");
}
System.out.println();
}
System.out.println("getDeclaredConstructor()获取构造方法");
//Constructor con3 = userClass.getConstructor(Integer.class,String.class,String.class);
Constructor con3 = userClass.getDeclaredConstructor(Integer.class,String.class,String.class);
System.out.print("构造方法名称 :" + con3.getName() +" ");
Class[] plts = con3.getParameterTypes();
System.out.print("参数列表为:");
for(Class p : plts){
System.out.print(p.getTypeName() + " ");
}
System.out.println();
}
getConstructor()获取所有公开构造方法
构造方法名称 :com.ruoyi.system.domain.User 参数列表为:java.lang.Integer java.lang.String
getDeclaredConstructors()获取所有构造方法
构造方法名称 :com.ruoyi.system.domain.User 参数列表为:java.lang.Integer java.lang.String
构造方法名称 :com.ruoyi.system.domain.User 参数列表为:java.lang.Integer java.lang.String java.lang.String
getDeclaredConstructor()获取构造方法
构造方法名称 :com.ruoyi.system.domain.User 参数列表为:java.lang.Integer java.lang.String java.lang.String
2.5 通过反射创建对象
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<User> userClass = User.class;
Constructor con3 = userClass.getDeclaredConstructor(Integer.class,String.class);
Object obj = con3.newInstance(11,"测试");
System.out.println(obj);
}
User{, id='11’name=‘测试’, sex=‘null’}
2.6 通过反射修改属性(常用)
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<User> userClass = User.class;
Constructor con3 = userClass.getDeclaredConstructor(Integer.class,String.class);
Object obj = con3.newInstance(11,"测试");
//name是私有属性
Field f = userClass.getDeclaredField("name");
f.setAccessible(true);
f.set(obj,"关羽");
System.out.println(obj);
}
User{, id='11’name=‘关羽’, sex=‘null’}
2.7 通过反射调用方法(常用)
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<User> userClass = User.class;
Constructor con3 = userClass.getDeclaredConstructor(Integer.class,String.class);
Object obj = con3.newInstance(11,"张飞");
Method m1 = userClass.getDeclaredMethod("setName", String.class);
m1.setAccessible(true);
m1.invoke(obj,"刘备");
System.out.println(obj);
}
User{, id='11’name=‘刘备’, sex=‘null’}
三、常见面试题
3.1怎么给类中私有属性赋值
标签:反射,JAVA,String,System,Class,获取,class,out From: https://blog.csdn.net/qq_15740137/article/details/140684979(1)属性对象.setAccessible(true);
在程序还没调用属性对象.setAccessible(false);之前,在同一程序内还可以调用私有属性,通过属性值.set(对象, 值)来给对象赋值(例如2.6)
(2)方法.setAccessible(true),使用m1.invoke(obj,属性名);(例如2.7)