目录
海漫浩浩,我亦苦作舟!大家一起学习,一起进步! 本人微信:g2279605572(欢迎大家与我交流)
▐ 反射机制
• 在运行状态中,在仅知道一个类名时,就可以动态获得类中信息,创建对象,调用对象成员的机制称为Java反射机制
• 一旦一个类被加载到内存中,都会为该类创建一个Class类的对象(运行时表现)
▐ 获得类的Class对象
获得类的Class对象有三种方式:
1. 类路径获取:
Class useClass1 = Class.forName("javareflect.User");
2. 类名获取:
Class userClass2 = User.class;
3. 对象获取:
User user = new User();
Class userClass3 = user.getClass();
▐ 获取类的构造方法
1. 获取类的Class对象:
//1.通过类名,获得到类的Class对象
Class useClass1 = Class.forName("javareflect.User");
2. 通过类的Class对象来创建对象:
//2.通过类的Class对象,创建对象
Object object = useClass1.newInstance();
3. 获得类中的构造方法 (还可以通过构造方法API中的方法创建对象)
//3.获得类中的构造方法(只能获得指定的公共构造方法)
//获得无参构造方法
Constructor constructor1 = useClass1.getConstructor();
//获得无参构造方法
Constructor constructor2 = useClass1.getConstructor(String.class,String.class);
//4.还可以通过构造方法API中的方法创建对象
Object object1 = constructor1.newInstance();
Object object2 = constructor2.newInstance("123", "456");
4. 获得类中所有的构造方法,包含私有的:
//只能返回一个特定的构造方法
useClass1.getDeclaredConstructor();
//返回一个包含该类所有声明的构造方法(包括私有、受保护、默认访问和公有构造方法)的数组。
useClass1.getDeclaredConstructors();
//通常不建议操作私有成员
▐ 获取类的属性
1. 获取公共属性:
//1.通过类型,获得到类的Class对象
Class useClass = Class.forName("javareflect.User");
//2.通过类的Class对象,创建对象
Object object = useClass.newInstance();
//3.获得类中的成员变量
Field accountFiled = useClass.getField("account");//获得指定名称的公共的成员变量
2. 获取私有属性:
getDeclaredField( )和getDeclaredFields( )获取私有属性
//获得指定名称的成员变量,包含私有的
Field accountFiled = useClass.getDeclaredField("account");
模拟MyBatis反射:
Class useClass = Class.forName("javareflect.User");
Object object = useClass.newInstance();
//模拟mybatis反射
Map<String,Object> map = new HashMap<>();
map.put("account","666");
map.put("password","666");
//获取所有属性,包括私有
Field[] declaredFields = useClass.getDeclaredFields();
for(Field field:declaredFields){
field.setAccessible(true);
field.set(object,map.get(field.getName()));
}
System.out.println(object);
▐ 获取成员方法
1. 获取类中的公共成员方法:
//1.通过类型,获得到类的Class对象
Class useClass = Class.forName("javareflect.User");
//2.通过类的Class对象,创建对象
Object object = useClass.newInstance();
//3.获得类中成员方法
Method work = useClass.getMethod("work");//无参
//调用访问
work.invoke(object);
2. 获取当前类声明的所有方法(包括私有方法)
Class clazz = MyClass.class;
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("方法名:" + method.getName());
}
3. 调用获取到的方法
可以使用invoke()
方法来调用获取到的方法。需要注意的是,如果方法是私有方法,需要先设置可访问性:
Class clazz = MyClass.class;
Object obj = clazz.newInstance();
try {
Method method = clazz.getDeclaredMethod("privateMethod", int.class);
method.setAccessible(true);
method.invoke(obj, 10);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
e.printStackTrace();
}
在上述代码中,privateMethod
是一个私有方法,接收一个int
类型的参数。通过反射机制获取该方法,并设置可访问性后进行调用。
模拟MyBatis将拿到的数据封装到对象中:
/*
* 模拟MyBatis将拿到的数据封装到对象中
* */
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//1.通过类型,获得到类的Class对象
Class useClass = Class.forName("javareflect.User");
//2.通过类的Class对象,创建对象
Object object = useClass.newInstance();
//通过get和set方法对类中的属性进行赋值操作
Map<String,Object> map = new HashMap<>();
map.put("account","666");
map.put("password","666");
Field[] declaredFields = useClass.getDeclaredFields();
for (Field field:declaredFields){
//根据属性名生成set方法名称
String setmethod = "set"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);
System.out.println(setmethod);
//通过Class对象,获得对应的Set方法对象
Method methodObj = useClass.getMethod(setmethod, field.getType());
methodObj.invoke(object, map.get(field.getName()));
}
System.out.println(object);//User{account='666', password='666'}
}
反射使用的场景:
- 编程开发工具的代码提示,如 IDEA 或 Eclipse 等,在写代码时会有代码(属性或方法名)提示,这就是通过反射实现的。
- 很多知名的框架如 Spring,为了让程序更简洁、更优雅,以及功能更丰富,也会使用到反射,比如 Spring 中的依赖注入就是通过反射实现的。
- 数据库连接框架也会使用反射来实现调用不同类型的数据库(驱动)
- 动态代理也使用了反射机制。
本次的分享就到此为止了,希望我的分享能给您带来帮助,创作不易也欢迎大家三连支持,你们的点赞就是博主更新最大的动力!
如有不同意见,欢迎评论区积极讨论交流,让我们一起学习进步!
有相关问题也可以私信博主,评论区和私信都会认真查看的,我们下次再见