厚积薄发系列之Java反射
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了厚积薄发系列之Java反射相关的知识,希望对你有一定的参考价值。
小生不才,在对于java反射仅仅停留在简单实用的基础上,下面我们来结合简单案例来了解一下java的反射
1.准备测试 准备两个类 和带有main方法的测试类
- Test1类
package reflection; public class Test1 { public void test() { System.out.println("Test1的方法"); } }
- Test2类
package reflection; public class Test2 { public void test() { System.out.println("Test2的方法"); } }
- 带有main方法的测试类
package reflection; public class Main { public static void main(String[] args) { new Test1().test(); } }
2.需求提出 现在main方法中运行的时候是运行Test1测试类的test()方法 如果我们有需求替换成Test2类中的test()方法 我们有两种方法
- 传统方法 修改代码 重新编译 即可
1 package reflection; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 // new Test1().test(); 7 new Test2().test(); 8 9 } 10 11 }
- 采用反射的方法 优点:不用修改代码 不用重新编译
- 提供一个配置文件 例如 Spring.txt 用来存储 两个类的 全限定名
Class=reflection.Test2
- 重新编写main方法
package reflection; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Properties; public class Main { public static void main(String[] args) throws Exception, IOException { // 传统的更改代码的方法 // new Test1().test(); // new Test2().test(); // 重新编写运用反射动态的加载一个类 // 1加载Spring.txt配置文件 读取你配置的要使用的类 下次如果更改类直接可以在配置文件更改 File file = new File("J:\\ecplisework\\testother\\src\\Spring.txt"); // 创建读取配置文件的对象properties Properties Springtxt = new Properties(); // 使配置文件对象读取Spring.txt的内容 Springtxt.load(new FileInputStream(file)); // 获取Spring.txt中的class的值 也就使类的全限定名 String className = Springtxt.getProperty("class"); // 根据全限定名类创建类对象 Class<?> clazz = Class.forName(className); // 获取方法对象 Method m = clazz.getMethod("test"); // 获取构造器 Constructor<?> c = clazz.getConstructor(); // 根据构造器 实例出一个对象 Object object = c.newInstance(); // 调用指定实例的指定方法 m.invoke(object); } }
- 提供一个配置文件 例如 Spring.txt 用来存储 两个类的 全限定名
- 总结:使用反射的方法不用去更改java代码 也不用去重新编译class文件就可以根据配置文件动态地反射加载一个类并运行其方法,只需要更改配置文件即可
3.为什么要使用反射&反射用在那些应用场景下
- 正常创建一个类 new Object()的过程:当JVM启动,所有编写的类都会编译成.class文件,然后被类加载器加载进jvm的内存中,当需要创建一个类的实例的时候,JVM会先检查这个类是否加载,加载过了就寻找对应的.class对象,并为这个实例分配内存;
- 突然-------我们突然想运行一个没有加载入JVM内存的类怎么办????? JVM里没有这个.class对象怎木办????? 这时反射就能帮助我们
- 常见的应用场景例如在加载数据驱动的时候,可以通过配置文件来选择使用mysql数据库还是oracle数据库
4.如何更好的使用反射?
- 作用:在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法。对于任意一个对象,可以调用它的任意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。
- java的反射机制主要提供了一下功能 关键子:在运行时
- 在运行时判断一个任意对象的所属的类
- 在运行时构造一个任意类的对象
- 在运行时判断任意类所具有的成员变量和方法
- 在运行时调用任意对象的方法
- 常用方法
-
- 获取对象类型
Class<?> clazz = Class.forName("类的权限定名");
Class<? extends Test2> class1 = this.getClass();
Classc2 =Test1.class; - 获取构造器
Constructor<?>[] constructors = clazz.getConstructors(); //获得类的所有公共构造函数
- 获取字段信息的方法
1 String name = clazz.getField("password").getName(); // 获得命名的公共字段 2 Field[] fields = clazz.getFields(); //获得所有公共字段 3 Field declaredField = clazz.getDeclaredField("username"); //获得类声明的命名的字段 4 Field[] declaredFields = clazz.getDeclaredFields(); //获取所有类声明的字段
- 获取方法信息
1 Method method = clazz.getMethod("test"); //使用特定的参数类型,获得命名的公共方法 2 Method[] methods = clazz.getMethods(); // 获得类的所有公共方法 3 Method declaredMethod = clazz.getDeclaredMethod("test"); //使用特写的参数类型,获得类声明的命名的方法 4 Field[] declaredFields2 = clazz.getDeclaredFields(); //获得类声明的所有方法
- 获取对象类型
以上是关于厚积薄发系列之Java反射的主要内容,如果未能解决你的问题,请参考以下文章