时间:2021-05-19
Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据。
1)获取某个类型的所有子类;比如,有一个父类是TestInterface,可以获取到TestInterface的所有子类。
2)获取某个注解的所有类型/字段变量,支持注解参数匹配。
3)使用正则表达式获取所有匹配的资源文件
4)获取特定签名方法。
通常的用法有:
具体也可以参见官方文档
补充:Java中的反射:框架设计的灵魂
框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
反射:将类的各个组成部分封装为其他对象,这就是反射机制
好处:
1.可以在程序运行过程中,操作这些对象。
2.可以解耦,提高程序的可扩展性。
1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
多用于配置文件,将类名定义在配置文件中。读取文件,加载类
2.类名.class:通过类名的属性class获取
多用于参数的传递
3.对象.getClass():getClass()方法在Object类中定义着。
多用于对象的获取字节码的方式
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
例如我们有一个Person类
public class Person { private String name; private int age; public Person(){ } public Person(String name, int age) { this.name = name; this.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; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}我们写一个Demo用三种方式来获取Class对象
public class Demo1 { public static void main(String [] args) throws Exception { //1、Class.forName("类名") Class cls1 = Class.forName("man.Person"); System.out.println(cls1); //2、类名。class Class cls2= Person.class; System.out.println(cls2); //3、对象.getClass() Person p = new Person(); Class cls3=p.getClass(); System.out.println(cls3); }}获取功能:
Field[] getFields() :获取所有public修饰的成员变量
Field getField(String name) 获取指定名称的 public修饰的成员变量
Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name)String getName() * Field:成员变量
操作:
setAccessible(true):暴力反射
Constructor:构造方法
创建对象:
T newInstance(Object… initargs)如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法* Method:方法对象
执行方法:
Object invoke(Object obj, Object… args)获取方法名称:
String getName:获取方法名
同样对于上面的Person类我们对其新增带参数和不带参数的sleep方法并且写一个Demo来获取这些成员变量,构造方法以及成员方法
Person.java
public class Person { private String name; private int age; public String a; protected String b; String c; private String d; public Person(){ } 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; } public Person(String name, int age) { this.name = name; this.age = age; } public void eat(){ System.out.println("eat..."); } public void eat(String food){ System.out.println("eat..."+food); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + ", d='" + d + '\'' + '}'; }}Demo2.java代码如下:
public class Demo2 { public static void main(String [] args) throws Exception { Class<Person> personClass = Person.class; //获取成员变量 Field[] fields = personClass.getFields(); for(Field field:fields) { System.out.println(field); } System.out.println("--------------"); Field a = personClass.getField("a");//获取a的值 Person p = new Person(); Object value=a.get(p); System.out.println(value); a.set(p, "zhangsan");//设置a的值 System.out.println(p); System.out.println("============="); //获取所有成员变量 Field[] declaredFields = personClass.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } Field d = personClass.getDeclaredField("d"); d.setAccessible(true);//暴力反射 Object value2 = d.get(p); System.out.println(value2); //获取构造方法 Constructor<Person> constructor = personClass.getConstructor(String.class, int.class); System.out.println(constructor); Object person = constructor.newInstance("张三", 23); System.out.println(person); System.out.println("======="); Constructor<Person> constructor1 = personClass.getConstructor(); System.out.println(constructor1); Object person1 = constructor1.newInstance(); System.out.println(person1); //获取成员方法 Method eat_method = personClass.getMethod("eat"); Person p1 = new Person(); eat_method.invoke(p1); Method eat_method1 = personClass.getMethod("eat",String.class); eat_method1.invoke(p1,"饭"); System.out.println("---------"); Method[] methods = personClass.getMethods(); for (Method method : methods) { System.out.println(method); } }}运行结果如下:
public java.lang.String man.Person.a-------------- null Person{name=‘null', age=0, a=‘zhangsan', b=‘null', c=‘null', d=‘null'}============= private java.lang.String man.Person.name private int man.Person.age public java.lang.String man.Person.a protectedjava.lang.String man.Person.b java.lang.String man.Person.c privatejava.lang.String man.Person.d null publicman.Person(java.lang.String,int) Person{name=‘张三', age=23, a=‘null',b=‘null', c=‘null', d=‘null'}======= public man.Person() Person{name=‘null', age=0, a=‘null', b=‘null', c=‘null', d=‘null'} eat… eat…饭--------- public java.lang.String man.Person.toString() public java.lang.String man.Person.getName() public voidman.Person.setName(java.lang.String) public voidman.Person.eat(java.lang.String) public void man.Person.eat() publicvoid man.Person.setAge(int) public int man.Person.getAge() publicfinal void java.lang.Object.wait() throwsjava.lang.InterruptedException public final voidjava.lang.Object.wait(long,int) throws java.lang.InterruptedExceptionpublic final native void java.lang.Object.wait(long) throwsjava.lang.InterruptedException public booleanjava.lang.Object.equals(java.lang.Object) public native intjava.lang.Object.hashCode() public final native java.lang.Classjava.lang.Object.getClass() public final native voidjava.lang.Object.notify() public final native voidjava.lang.Object.notifyAll()需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
1. 配置文件
2. 反射
1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
2. 在程序中加载读取配置文件
3. 使用反射技术来加载类文件进内存
4. 创建对象
5. 执行方法
为了实现创建任意类的对象,并且执行其中任意方法,我们再原有Person.java文件基础上新增Student.java,代码如下:
public class Student { public void sleep(){ System.out.println("sleep..."); }}那么我们需要在src目录下添加pro.properties文件并写入以下配置信息
className=man.StudentmethodName=sleep接着我们来写这个案例ReflectTest.java,代码如下
public class ReflectTest { public static void main(String [] args) throws Exception { //加载配置文件 Properties pro = new Properties(); ClassLoader classLoader = ReflectTest.class.getClassLoader(); InputStream is = classLoader.getResourceAsStream("pro.properties"); pro.load(is); //获取配置文件中定义的数据 String className = pro.getProperty("className"); String methodName = pro.getProperty("methodName"); //加载该类进内存 Class cls = Class.forName(className); Object obj = cls.newInstance(); Method method = cls.getMethod(methodName); method.invoke(obj); }}这样我们只需改变配置文件中的信息而不需要去改变任何代码就可以实现类以及类中的方法,整个目录结构如下
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
Java类反射应用得非常广泛几乎是所有框架的最核心部分,PHP程序员似乎从不关心反射。尝试着用java的思想去理解php的反射,跟java基本上基本一致。参考了
java反射java从很早的版本开始就引入了反射机制,java如今的框架底层大部分也都是使用反射实现的。这篇博客就去探索下java反射使用的方便之处。要说jav
方案一:采用reflections框架(此框架依赖com.google.guava)1、reflections框架地址:https://github.com/r
很多主流框架都使用了反射技术.像ssh框架都采用两种技术xml做配置文件+反射技术.与反射有关的类包.java.lang.reflect.*;和java.lan
jquery非常好用,只要你是网站前端设计师,你肯定会喜欢,一张图片大小的框架文件,却有如此强大的功能,令人非常佩服,当然这也要感谢jquery框架的开发团队,