反射机制(Reflection)
注:文章截图来自b站up主狂神
若有侵权,联系删除
-
反射式Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并直接操作任意对象的内部属性及方法
-
反射机制的功能:
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
-
优点:可以实现动态创建对象和编译,灵活性很大
-
缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM我们希望做什么并且它满足我们的要求。这类操作总是慢于直接执行相同的操作
-
主要API
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造器
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
// 通过反射获取类的Class对象
Class c1 = Class.forName("com.reflection.User");
Class c2 = Class.forName("com.reflection.User");
System.out.println(c1);
// 一个类在内存中只有一个Class对象
// 一个类被加载后,类的整个结构都回被封装在Class对象中
System.out.println(c1 == c2);
}
}
class User{
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 获得Class对象的四种方法:
- Class clazz = 类名.class;
- Class clazz = 对象名.class
- Class clazz = Class.forName(“类的路径”)
- 基本内置类型的包装类都有一个Type属性
Class c2 = User.class;
User user = new User();
Class c3 = user.getClass();
Class c1 = Class.forName("com.reflection.User");
Class type = Integer.TYPE;
- 所有类型的Class对象
- 类
- 接口
- 数组:只要数组元素类型和维度相同,就是一个Class
- 注解
- 枚举
- void
- Class
(alt键选择多行)
- Java内存分析:
- 类的加载
- 父类静态变量初始化
- 子类静态变量初始化
- 父类非静态变量初始化
- 父类构造函数代码执行
- 子类非静态变量初始化
- 子类构造函数执行
- 类加载完成,即类完成对象实例化
-
Java的类加载器
- 加载器的作用:用来把类装载进内存的
- 分类:
- 引导类加载器:负责Java平台核心代码库
- 扩展类加载器:负责jre/lib/ext目录下的jar包
- 系统类加载器:负责java -classpath所指目录下的类于jar包装入工作(最常用)
-
通反射获得类的信息
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * 获得类的信息 */ public class Test04 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class c1 = Class.forName("com.reflection.User"); // 获得类的名字 System.out.println(c1.getName()); System.out.println(c1.getSimpleName()); System.out.println("========================="); // 获得类的属性 Field[] fields = c1.getFields(); // getFields():只能获得public属性 for (Field field : fields){ System.out.println(field); } fields = c1.getDeclaredFields(); // getDeclaredFields():获得全部属性 for (Field field : fields){ System.out.println(field); } // 获得指定属性的值(public) // Field name = c1.getField("name"); // System.out.println(name); // 获得指定属性的值(所有权限) Field name1 = c1.getDeclaredField("name"); System.out.println(name1); System.out.println("================================"); // 获得类的方法 Method[] methods = c1.getMethods(); // 获得方法(本身和继承的public方法) for (Method method : methods) { System.out.println(method); } System.out.println("-----------------------------"); methods = c1.getDeclaredMethods(); // 获得方法(本身的所有方法) for (Method method : methods) { System.out.println(method); } // 获得指定方法 Method getName = c1.getMethod("getName", null); Method setName = c1.getMethod("setName", String.class); System.out.println("================================="); // 获得类的构造器 Constructor[] constructors = c1.getConstructors(); // 获得public的构造器 for (Constructor constructor : constructors) { System.out.println(constructor); } System.out.println("-------------------------------------"); constructors = c1.getDeclaredConstructors(); // 获得所有的构造器 for (Constructor constructor : constructors) { System.out.println(constructor); } System.out.println("---------------------------"); Constructor constructor = c1.getConstructor(String.class, int.class); // 获得指定构造器 System.out.println(constructor); } }
-
通过反射动态创建对象
package com.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 通过反射动态的创建对象 */ public class Test05 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { Class c1 = Class.forName("com.reflection.User"); // 构造一个对象 User user = (User) c1.newInstance(); // 本质是调用了类的无参构造器 System.out.println(user); // 通过构造器创建对象 try { Constructor constructor = c1.getConstructor(String.class, int.class); Object newInstance = constructor.newInstance("拉拉", 1); System.out.println(newInstance); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } // 通过反射调用普通方法 user = (User) c1.newInstance(); // 通过反射获得方法 Method setName = c1.getDeclaredMethod("setName", String.class); // invoke():激活 setName.invoke(user, "lala1"); System.out.println(user.getName()); System.out.println("============================="); // 通过反射操作属性 User user1 = (User) c1.newInstance(); Field name = c1.getDeclaredField("name"); name.setAccessible(true); name.set(user1, "lala2"); System.out.println(user1); } }
-
性能分析
package com.reflection; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 分析性能 */ public class Test06 { // 普通方式 public static void test1() { long startTime = System.currentTimeMillis(); User user = new User(); for (int i = 0; i < 100000000; i++) { user.getName(); } long endTime = System.currentTimeMillis(); System.out.println("普通方式:" + (endTime - startTime)); } // 反射方式 public static void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { long startTime = System.currentTimeMillis(); User user = new User(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName", null); for (int i = 0; i < 100000000; i++) { getName.invoke(user, null); } long endTime = System.currentTimeMillis(); System.out.println("反射方式:" + (endTime - startTime)); } // 反射方式 关闭检测 public static void test3() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { long startTime = System.currentTimeMillis(); User user = new User(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName", null); getName.setAccessible(true); for (int i = 0; i < 1000000000; i++) { getName.invoke(user, null); } long endTime = System.currentTimeMillis(); System.out.println("反射关闭检测方式:" + (endTime - startTime)); } public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { test1(); test2(); test3(); } }
-
通过反射操作泛型
-
通过反射操作注解