1.Java反射机制的概念
Java反射机制主要就是在程序运行的时候,动态的加载一些类和这些类的详细信息,然后操作这些类或对象的属性和方法。它的本质就是JVM通过类加载器得到一个class对象后,对其进行反编译,这样就能得到对象中的各种信息。
2.反射机制的优缺点
优点:
- 运行期类型的判断,动态加载类,提高代码灵活度。
- 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的 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));
- 【Java的精华——反射机制】通过反射操作运行时类中的指定的方法
@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 = https://www.it610.com/article/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}
推荐阅读
- 反射
- JavaSE|Java的反射技术(Class类,Constructor类,Method类, Field类)
- BGP RR反射器理论实验,BGP联盟详解 纯干货!
- java基础---反射|黑马程序员————Java基础日常笔记---反射与正则表达式
- 实战中反射的应用
- 八股文--反射http学习
- 揭秘反射真的很耗时吗,射 10 万次用时多久