1.Java 反射机制的概念
Java 反射机制次要就是在程序运行的时候,动静的加载一些类和这些类的详细信息,而后操作这些类或对象的属性和办法。它的实质就是 JVM 通过类加载器失去一个 class 对象后,对其进行反编译,这样就能失去对象中的各种信息。
2. 反射机制的优缺点
长处 :
- 运行期类型的判断,动静加载类,进步代码灵便度。
毛病 :
- 性能瓶颈:反射相当于一系列解释操作,告诉 JVM 要做的事件,性能比间接的 java 代码要慢很多。
- 平安问题:让咱们能够动静操作扭转类的属性同时也减少了类的安全隐患。
3.Java 反射机制的原理
下图就是类的失常加载过程,以及它们的反射原理和 class 对象:
4. 反射具体应用
-
创立 Class 类的实例有四种办法:
// 提供的简略的 Person 类 public class Person{ private String name; private int id; private static int UID; private String show(String nation){System.out.println("我的国籍是:" + nation); return nation; } } // 形式一:调用运行时类的属性:.class Class clazz1 = Person.class; // 形式二:通过运行时类的对象, 调用 getClass() Person p1 = new Person(); Class clazz2 = p1.getClass();// 通过对象取得 class // 形式三:调用 Class 的静态方法:forName(String classPath) Class clazz3 = Class.forName("com.demo.java.Person"); System.out.println(clazz1 == clazz2);//true System.out.println(clazz1 == clazz3);//true // 形式四:应用类的加载器:ClassLoader (理解) ClassLoader classLoader = ReflectionTest.class.getClassLoader(); Class clazz4 = classLoader.loadClass("com.demo.java.Person");
-
通过反射创立对应的运行时类的对象
// 个别应用 newInstance()创立空参的 Class c = Class.forName("com.demo.java.Person"); Person p = (Person)c.newInstance(); // 调用指定参数构造的结构器,生成 Constructor 的实例 Constructor con = clazz.getConstructor(String.class,Integer.class); // 通过 Constructor 的实例创立对应类的对象,并初始化类属性 Person p2 = (Person) con.newInstance("Peter",20);
-
通过反射操作运行时类中的指定的属性
Class clazz = Person.class; // 创立运行时类的对象 Person p = (Person) clazz.newInstance(); //1. getDeclaredField(String fieldName): 获取运行时类中指定变量名的属性 Field name = clazz.getDeclaredField("name"); //2. 保障以后属性是可拜访的 name.setAccessible(true); //3. 获取、设置指定对象的此属性值 name.set(p,"Tom"); System.out.println(name.get(p)); System.out.println("************** 调用动态属性 **************"); Field uid = clazz.getDeclaredField("UID"); uid.setAccessible(true); uid.set(null,1234);// 动态属性赋值 System.out.println(uid.get(p));
-
通过反射操作运行时类中的指定的办法
@Test public void testMethod() throws Exception { Class clazz = Person.class; // 创立运行时类的对象 Person p = (Person) clazz.newInstance(); /* 1. 获取指定的某个办法 getDeclaredMethod(): 参数 1:指明获取的办法的名称 参数 2:指明获取的办法的形参列表 */ Method show = clazz.getDeclaredMethod("show", String.class); //2. 保障以后办法是可拜访的 show.setAccessible(true); /* 3. 调用办法的 invoke(): 参数 1:办法的调用者 参数 2:给办法形参赋值的实参 invoke() 的返回值即为对应类中调用的办法的返回值。*/ Object returnValue = show.invoke(p,"CHN"); //String nation = p.show("CHN"); System.out.println(returnValue); System.out.println("************* 如何调用静态方法 *****************"); // private static void showDesc() Method showDesc = clazz.getDeclaredMethod("showDesc"); showDesc.setAccessible(true); // 如果调用的运行时类中的办法没有返回值,则此 invoke() 返回 null // Object returnVal = showDesc.invoke(null); Object returnVal = showDesc.invoke(Person.class); System.out.println(returnVal);//null }