目录
为什么要学习反射?
经常听到的答案:
为了可以操作私有变量,操作私有方法
大伙可以思考,这有什么意义?
其实,我更认为这是反射机制带来一个副作用而已,而不是目的
思考题
目标:实现一个导弹发射平台,输入具体的导弹类型,就发送不同的导弹
要求:可以修改配置文件,但不允许修改代码
即编译期无法确定要执行的类和对象,只有到运行期才能确定
1.什么是反射
Java的反射机制让Java语言具有动态性
Java的反射机制实现程序运行期间,动态获取类的信息以及动态调用对象方法的功能;
2.反射技术的核心
Student student = new Student();
当执行上面这段程序时,JVM会在方法区创建Student类对应的Class对象,这个对象包含了完整的类结构
信息;
Class类就是反射的核心,是一个特殊的类,用来描述所有类的结构信息,我们来查看Class的类结构,
加深理解
类结构 ,包名、类名、成员变量、成员方法、构造方法、接口
3.获取Class对象的三种方式
1,通过getClass()方法
Student student = new Student();
Class studentClass = student.getClass();
2,通过.class静态属性
Class studentClass = Student.class;
3,通过Class.forName()方法
//性能较比前两种较差
//优点是灵活性高
Class studentClass = Class.forName("com.pojo.Student");
//Class.forName(xxx.xx.xx)返回的是一个类。
//Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段。
4.获取构造方法
1,获取类定义的构造方法
package reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @author XiaoAI
* @date 2023/7/20 16:06
*/
public class ConstructorTest {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<Book> bookClass = Book.class;
//1.获取public修饰的构造方法
java.lang.reflect.Constructor<?>[] constructors = bookClass.getConstructors();
for (java.lang.reflect.Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("-------------------------------------------");
//2.获取所有的构造方法
Constructor<?>[] declaredConstructors = bookClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
Constructor<Book> constructor = bookClass.getConstructor(String.class, double.class);
Book book = constructor.newInstance("Java编程思想", 9999);
System.out.println(book.toString());
}
}
2,通过构造方法创建对象
//1.获取到构造器对象
Constructor<Book> constructor = bookClass.getConstructor(String.class, double.class);
//2.通过构造器对象的newInstance()方法创建对象
Book book = constructor.newInstance("Java编程思想", 9999);
System.out.println(book.toString());
5.获取类方法
1,获取方法
package reflection;
import java.lang.reflect.Method;
/**
* @author XiaoAI
* @date 2023/7/20 16:30
* 通过反射技术获取方法
*/
public class MethodTest {
public static void main(String[] args) {
Class<Book> bookClass = Book.class;
//1.获取所有public修饰的方法
Method[] methods = bookClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("------------------------------------");
//2.获取所有方法
Method[] declaredMethods = bookClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
}
}
2,调用方法
package reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author XiaoAI
* @date 2023/7/20 16:33
* 通过反射技术调用方法
*/
public class MethodTest2 {
public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//1.获取类对应的Class对象
Class<Book> bookClass = Book.class;
//2.通过Class对象,获取到其内部具体定义的方法
Method test = bookClass.getDeclaredMethod("test", null);
//3.通过Class对象构造具体类的实例
Book book = bookClass.newInstance();
//4.通过反射执行方法调用
//私用方法需要开放访问权限
test.setAccessible(true);
test.invoke(book, null);
}
}
6.获取类的成员变量
1,获取成员变量
package reflection;
import java.lang.reflect.Field;
/**
* @author XiaoAI
* @date 2023/7/21 15:24
* 通过反射技术获取类属性
*/
public class FieldTest {
public static void main(String[] args) {
//1.获取某个类的Class对象
Class<Book> bookClass = Book.class;
//2.通过Class对象获取属性
Field[] fields = bookClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("------------------------------------");
Field[] declaredFields = bookClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
}
}
2,操作成员变量
package reflection;
import java.lang.reflect.Field;
/**
* @author XiaoAI
* @date 2023/7/21 15:24
* 通过反射技术来动态给某个属性赋值
*/
public class FieldTest2 {
public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
//1.获取某个类的Class对象
Class<Book> bookClass = Book.class;
//2.通过Class对象获取属性
Field otherField = bookClass.getField("other");
//3.通过Class的对象来创建类的实例
Book book = bookClass.newInstance();
//4.调用成员变量对象的set方法实现赋值
otherField.set(book, "反射技术演练");
System.out.println(book.other);
}
}
7.获取类的其他信息
//1.获取包名
clazz.getPackage();
//2.获取类名
clazz.getName();
//3.获取父类
clazz.getSuperclass();
//4.获取该类实现的接口信息
clazz.getInterfaces();
//5.获取注解信息
clazz.getAnnotations();
8.反射的效率
1,反射性能测试
2,提高反射性能,关闭安全检查
//设置为true,表示关闭安全检查
//设置为false,表示执行Java语言的访问检查
setAccessible(true);
//但是整体的性能表现依然不如直接调用
//但是要注意,反射解决的是实现动态功能的问题
package reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author XiaoAI
* @date 2023/7/21 16:14
* 反射性能测试
*/
public class Reflection {
public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
long start = System.currentTimeMillis();
Book book = new Book();
// //14
// for (int i = 0; i < 100000000; i++) {
// book.test1();
// }
Class<Book> bookClass = Book.class;
Method test1 = bookClass.getMethod("test1", null);
Book book1 = bookClass.newInstance();
//239 124
test1.setAccessible(true);
for (int i = 0; i < 100000000; i++) {
test1.invoke(book1, null);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}