Skip to content

[!quote] 反射 反射 允许对成员变量成员方法构造方法的信息进行编程访问

  • 反射会带来一定的性能开销和安全问题
  • 应用例子:idea 里的方法提示,当你输入一个类时,idea 会获取这个类中的方法,然后给你提示

获取

获取的不是 Java 文件,而是 Java 字节码文件 .class

获取 class 对象

  • Class.forname("全类名") ==源代码阶段==使用
  • 类名.class ==加载阶段==使用
  • 对象.getClass(); ==运行阶段==使用

java
public static void main(String[] args) throws ClassNotFoundException {
	Class<?> aClass1 = Class.forName("reflex.Student");
	System.out.println(aClass1);

	Class<Student> aClass2 = Student.class;
	System.out.println(aClass2);

	Student s = new Student();
	Class<? extends Student> aClass3 = s.getClass();
	System.out.println(aClass3);
}

[!hint] Java 中,万物皆对象 构造方法的对象 Constructor 成员变量的对象 field 成员方法的对象 Method

获取构造方法

  • Constructor<?>[] getConstructors() 返回所有公共构造方法【只包括 public】对象的数组
  • Constructor<T> getConstructor(Class<?>... parameterTypes) 返回单个公共构造方法对象
  • Constructor<?>[] getDeclaredConstructors() 返回所有构造方法
  • Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回单个构造方法对象
java
public static void main(String[] args) throws ClassNotFoundException {  
    Class<?> aClass1 = Class.forName("reflex.Student");  
    Constructor<?>[] constructors = aClass1.getConstructors();  
  
    for (Constructor con : constructors) {  
        System.out.println(con);  
    }  

	// getConstructor
    Constructor<?> constructor = aClass1.getConstructor(int.class, String.class);  
    System.out.println(constructor);  
}

---
public reflex.Student()
public reflex.Student(int,java.lang.String)
public reflex.Student(int,java.lang.String)

获取成员变量

  • Field[] getFields() 返回所有公共成员变量对象的数组
  • Field[] getDeclaredFields() 返回所有成员变量对象的数组
  • Field getField(String name) 返回单个公共成员变量对象,name 是变量名字
  • Field getDeclaredField(String name) 返回单个成员变量对象
java
Class<?> aClass1 = Class.forName("reflex.Student");  
Field[] fields = aClass1.getDeclaredFields();  
for (Field f : fields) {  
    System.out.println(f);  
}

---
private int reflex.Student.age
private java.lang.String reflex.Student.name

作用

  • 获取某个对象的成员变量 Field.get(某个对象)
java
Class<?> aClass1 = Class.forName("reflex.Student");  
Field name = aClass1.getDeclaredField("name");  // 获取成员变量对象
  
Student s = new Student(2, "green");  
name.setAccessible(true);  // 修改 private 的临时权限
String ss = (String) name.get(s);  // 获取到 s 对象的 name 变量
System.out.println(ss);

---
green
  • 修改某个对象的成员变量 Field.set(某个对象,要修改成的值)
java
Class<?> aClass1 = Class.forName("reflex.Student");  
Field name = aClass1.getDeclaredField("name");  
  
Student s = new Student(2, "green");  
name.setAccessible(true);  
String ss = (String) name.get(s);  
System.out.println(ss);  

// 修改
name.set(s, "red");  
String sss = (String) name.get(s);  
System.out.println(sss);

---
green
red

获取成员方法

  • Method[] getMethods() 返回所有公共成员方法对象的数组【包括父类的所有公共方法】
  • Method[] getDeclaredMethods() 返回所有成员方法对象的数组【不包括父类的方法】
  • Method getMethod(String name, Class<?>... parameterTypes) 返回单个公共成员方法对象
    • name 方法的名称
    • parameterTypes 方法的参数类型
  • Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回单个成员方法对象
java
Class<?> aClass1 = Class.forName("reflex.Student");  
Method[] methods = aClass1.getMethods();  
for (Method m : methods) {  
    System.out.println(m);  
}

---
public int reflex.Student.getAge()
public void reflex.Student.setAge(int)
public java.lang.String reflex.Student.getName()
public java.lang.String reflex.Student.toString()
public void reflex.Student.setName(java.lang.String)
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

解剖

  • 权限修饰符
java
Class<?> aClass1 = Class.forName("reflex.Student");  
Constructor<?> constructor = aClass1.getConstructor(int.class, String.class);  
int modifiers = constructor.getModifiers();  
System.out.println(modifiers);

---
1

  • 参数
java
Class<?> aClass1 = Class.forName("reflex.Student");  
Constructor<?> constructor = aClass1.getConstructor(int.class, String.class);  
Parameter[] parameters = constructor.getParameters();  
for (Parameter p : parameters) {  
    System.out.println(p);  
}

---
int arg0
java.lang.String arg1

  • 利用获取到的构造方法创建对象
java
Class<?> aClass1 = Class.forName("reflex.Student");  
Constructor<?> constructor = aClass1.getConstructor(int.class, String.class);  
Object green = constructor.newInstance(2, "green");  
System.out.println(green);

---
Student{age=2, name='green'}

  • 获取成员变量的类型 Field.getType();

  • 获取方法的名字
  • 方法的异常
  • 方法的参数

  • 方法的返回值
java
Class<?> aClass1 = Class.forName("reflex.Student");  
Method getName = aClass1.getMethod("getName");  
  
Student s = new Student(2, "李白");  
// 使用 invoke 运行方法才能获取到返回值
String invoke = (String) getName.invoke(s);  
System.out.println(invoke);

---
李白

作用

获取类中的信息:比如获取一个类的信息,写入到某个文件中


结合配置文件,动态的创建对象并调用方法

java
// 创建配置文件对象,properties可以看作一个特殊的集合  
Properties properties = new Properties();  
FileInputStream fileInputStream = new FileInputStream("idea_test//src//prop.properties");  
properties.load(fileInputStream);  
fileInputStream.close();  

String s = (String) properties.get("classname");  
String ss = (String) properties.get("method");  

System.out.println(s);  
System.out.println(ss);  

// 再使用反射……  

---
reflex.Student
getName

强制实例化具有私有构造方法的类

java
// 获取其私有构造器
Constructor<Elvis> constructor = Elvis.class.getDeclaredConstructor();
// 将构造器设置为可访问
constructor.setAccessible(true);

System.out.println(constructor.newInstance());
System.out.println(constructor.newInstance());