1.定义:
反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,都能够调用它的任意一个方法。在java中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
解释:反射就像是一个程序员的万能钥匙,可以让程序员在程序运行时,动态地获取一个类的信息,创建对象,调用方法等操作。反射的核心就是Java中的Class类,它包含了类的信息(包括类名、属性、方法等),可以让程序员在程序运行时,动态地获取这个Class对象,并通过这个Class对象来访问类的信息和操作类的对象。
2.反射的实现方式:
第一步:
获取Class对象,有4种方法:
1)Class.forName(“类的路径”);
该方法可以根据类的全限定名(包名+类名)来获取对应的Class对象,从而实现动态加载类。
例如,我们可以通过以下代码获取String类的Class对象:
Class<?> stringClass = Class.forName("java.lang.String");
2)类名.class
通过类名.class方式可以获取类的Class对象,这种方式比较简单,但是需要明确类的类型。
例如,我们可以通过以下代码获取String类的Class对象:
Class<String> stringClass = String.class;
3)对象名.getClass()
通过实例对象的getClass()方法可以获取其对应的Class对象,从而实现动态获取对象的类型信息。
例如,我们可以通过以下代码获取一个字符串对象的Class对象:
String str = "Hello, world!";
Class<? extends String> strClass = str.getClass();
第二步:
再获取到Class对象之后,就可以通过Class对象来获取类的信息、创建对象、调用方法等操作了。
1)获取类的信息
可以通过Class对象来获取类的各种信息,例如类的名称、包名、父类、接口、字段、方法等等。下面是一些示例代码:
Class<?> personClass = Class.forName("com.example.Person");
// 获取类的名称
String className = personClass.getName();
// 获取类的包名
Package classPackage = personClass.getPackage();
String packageName = classPackage.getName();
// 获取类的父类
Class<?> superClass = personClass.getSuperclass();
// 获取类实现的接口
Class<?>[] interfaces = personClass.getInterfaces();
// 获取类的字段
Field[] fields = personClass.getDeclaredFields();
// 获取类的方法
Method[] methods = personClass.getDeclaredMethods();
2)创建对象
通过Class对象来创建对象,包括使用无参构造函数创建对象、使用有参构造函数创建对象、使用静态工厂方法创建对象等等。下面是一些示例代码:
Class<?> personClass = Class.forName("com.example.Person");
// 使用无参构造函数创建对象
Object person = personClass.newInstance();
// 使用有参构造函数创建对象
Constructor<?> constructor = personClass.getConstructor(String.class, int.class);
Object person = constructor.newInstance("Tom", 20);
// 使用静态工厂方法创建对象
Method factoryMethod = personClass.getMethod("createPerson");
Object person = factoryMethod.invoke(null);
3)调用方法
通过Class对象来调用类的方法,包括调用普通方法、调用静态方法、调用私有方法等等。下面是一些示例代码。
Class<?> personClass = Class.forName("com.example.Person");
Object person = personClass.newInstance();
// 调用普通方法
Method sayHelloMethod = personClass.getMethod("sayHello");
sayHelloMethod.invoke(person);
// 调用静态方法
Method staticMethod = personClass.getMethod("staticMethod");
staticMethod.invoke(null);
// 调用私有方法
Method privateMethod = personClass.getDeclaredMethod("privateMethod");
privateMethod.setAccessible(true);
privateMethod.invoke(person);
3.Java中实现反射机制的类:
1)Class:是Java反射机制的核心类,它代表一个类的类型信息,可以用来获取类的各种信息,包括类的名称、包名、父类、接口、字段、方法等等。
注意: 所有获取对象的信息都需要Class类来实现。
2)Field:提供有关类和接口的属性信息,以及对它的动态访问权限。
它代表一个类的属性,可以用来访问属性。通过Field类可以获取一个类的所有属性,包括公有属性和私有属性。
3)Constructor:Constructor类代表一个类的构造函数,可以用来创建对象。通过Constructor类可以获取一个类的所有构造函数,包括无参构造函数和有参构造函数。
4)Method:代表一个类的方法,可以用来调用方法。通过Method类可以获取一个类的所有方法,包括普通方法、静态方法、私有方法等等。
4.反射机制的优缺点:
优点:
1)能够运行时动态获取类的实例,提高灵活性;
2)与动态编译结合,它是通用的机制,也可以用于各种框架和工具
缺点:
1)使用反射性能较低,需要解析字节码,将内存中的对象进行解析。
解决方案:可以通过setAccessible(true)关闭JDK的安全检查来提升反射速度;
多次创建一个类的实例时,有缓存会快很多;
ReflectASM工具类,通过字节码生成的方式加快反射速度;
2)相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)