Reflection反射机制原理使用场景 及 缺陷
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Reflection反射机制原理使用场景 及 缺陷相关的知识,希望对你有一定的参考价值。
(目录)
反射
一个需求 引出反射
需求如下:
根据配置文件re.properties中的指定信息,创建Cat对象并调用方法hi
代码如下:
public class Cat
private String name;
public int age;
public String sex;
//无参构造器
public Cat()
private Cat(String name)
this.name = name;
public Cat(String name, int age, String sex)
this.name = name;
this.age = age;
this.sex = sex;
public void hi()
System.out.println("hi:" + name);
public void eat(String food)
System.out.println(name+": 吃"+food);
public int sum(int x, int y)
return x+y;
public void dosome(int x,float y, char z, boolean b, String... strs)
System.out.println(name+": "+x+" "+y+" "+z+" "+b);
System.out.println(name+": "+strs);
private void WC()
System.out.println(name + ": 上厕所..");
@Override
public String toString()
return "Cat" +
"name=" + name + \\ +
", age=" + age +
", sex=" + sex + \\ +
;
// 反射问题的引入
//根据 re.properties 配置文件中的信息,创建Cat对象并调用hi方法
public class ReflectionQuestion
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException
//传统方式:new 对象 --》 调用方法 Cat().hi();
// 1. 传统方法: 使用Properties类读写配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src/main/resources/re.properties"));
String classfullpath = properties.get("classfullpath").toString(); //com.panyujie.reflection.Cat
String methodName = properties.get("method").toString(); //hi
System.out.println("classfullpath=" + classfullpath);
System.out.println("methodName=" + methodName);
// 2. 创建对象
// 怎么创建对象???? 你拿到了类的全路径 你怎么 new?
// 只能使用 反射机制
// 2.1 加载类,返回Class类型的对象
Class<?> cls = Class.forName(classfullpath);
// 2.2 通过 cls对象 得到加载的类 com.panyujie.reflection.Cat 的对象
Object o = cls.newInstance();
// 2.3 通过 cls对象 得到加载的类 com.panyujie.reflection.Cat 的 methodName 方法对象 hi
// 即:在反射机制中,可以把方法视为对象(万物皆对象)
Method method1 = cls.getMethod(methodName);
// 2.4通过 method1 调用方法:即-》通过方法对象实现调用方法
// 反射机制:方法.invoke(对象)
method1.invoke(o);
效果: 调用成功,为null是因为我没赋值
此时我们发现,我们只需要将re.properties中的 method=hi 改成 method=eat,就会调用eat()
,不需要修改源码,反射机制非常强大!
反射机制
Java Reflection
反射机制 原理图
反射机制可以完成的功能
反射相关的主要类
- 测试Field和Constructor:
//java.lang.reflect.Field: 代表类的成员变量, Field对象表示某个类的成员变量
//得到name字段
//getField不能得到私有的属性
Field nameField = cls.getField("age"); //
System.out.println(nameField.get(o)); // 传统写法 对象.成员变量 , 反射 : 成员变量对象.get(对象)
//java.lang.reflect.Constructor: 代表类的构造方法, Constructor对象表示构造器
Constructor constructor = cls.getConstructor(); //()中可以指定构造器参数类型, 返回无参构造器
System.out.println(constructor);//Cat()
public class Cat
private String name = "招财猫";
public int age = 10; //public的
public Cat() //无参构造器
public Cat(String name)
this.name = name;
public void hi() //常用方法
//System.out.println("hi " + name);
public void cry() //常用方法
System.out.println(name + " 喵喵叫..");
测试Field和Constructor得到的结果:
- 获得有参数的构造器
//传入 String.class 就是String类的Class对象
Constructor constructor2 = cls.getConstructor(String.class);
System.out.println(constructor2);//Cat(String name)
反射优点 和 缺点
反射调用 性能测试 及 关闭访问检测
测试代码:
/**
* Created with IntelliJ IDEA.
* Description:
* User: Submerge
* Date: 2022-10-23
* Time: 18:10
* 测试反射调用的性能
*/
public class Reflection2
public static void main(String[] args) throws Exception
m1();
m2();
// 普通调用方法
public static void m1()
Cat cat = new Cat();
long l = System.currentTimeMillis();
for(int i=0;i<50000000;i++)
cat.hi();
long r = System.currentTimeMillis();
System.out.println("普通调用耗时: " + (r-l));
// 反射调用方法
public static void m2() throws Exception
Class<?> cls = Class.forName("com.panyujie.reflection.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
long l = System.currentTimeMillis();
for(int i=0;i<50000000;i++)
hi.invoke(o);
long r = System.currentTimeMillis();
System.out.println("反射调用耗时: " + (r-l));
测试结果:反射对速度影响还是挺到的
//反射调用优化:关闭访问检测
public static void m3() throws Exception
Class<?> cls = Class.forName("com.panyujie.reflection.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
//在反射调用方法时,取消访问检查
hi.setAccessible(true);
long start = System.currentTimeMillis();
for (int i = 0; i < 50000000; i++)
hi.invoke(o);
long end = System.currentTimeMillis();
System.out.println("关闭访问检测反射耗时:" + (end - start));
@
以上是关于Reflection反射机制原理使用场景 及 缺陷的主要内容,如果未能解决你的问题,请参考以下文章