Java反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
Class类
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
继承结构如下图:
可以在Java Api中查看该类的方法摘要,这里只列举本文使用示例的方法:
方法 | 作用 |
---|---|
forName(String className) | 返回与带有给定字符串名的类或接口相关联的 Class 对象 |
getConstructor(Class>... parameterTypes) | 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 |
getDeclaredConstructors() | 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 |
getDeclaredField(String name) | 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 |
getDeclaredFields() | 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。 |
getDeclaredMethod(String name, Class>... parameterTypes) | 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 |
getDeclaredMethods() | 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 |
getField(String name) | 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 |
getFields() | 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 |
getMethod(String name, Class>... parameterTypes) | 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 |
getMethods() | 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 |
getName() | 以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。 |
newInstance() | 创建此 Class 对象所表示的类的一个新实例 |
下面将使用上述方法来使用反射。
使用反射来实例化对象
// Person类
public class Person {
private String name;
private int age;
}
// Test类
public class Test {
public static void main(String args[]) {
try {
System.out.println("1.使用反射实例化对象");
Class> person = Class.forName("Person");
Person o = (Person) person.newInstance();
//相当于 Person o = new Person()
System.out.println(o);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
使用反射访问私有构造方法创建对象
// Person类
public class Person {
private String name;
private int age;
public Person() {
}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
// Test类
public class Test {
public static void main(String args[]) {
try {
System.out.println("1.使用反射实例化对象");
Class> person = Class.forName("Person");
Person o = (Person) person.newInstance();
//相当于 Person o = new Person()
System.out.println(o);
System.out.println("2.通过私有构造方法创建对象");
Constructor> declaredConstructor = person.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);
Person person1 = (Person) declaredConstructor.newInstance("盖伦", 30);
System.out.println(person1.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
查看Person类私有属性
//关键代码
....
System.out.println("3.查看Person类私有属性");
Field[] declaredFields = person.getDeclaredFields();
for (Field f : declaredFields) {
System.out.println(f.getName());
}
运行结果:
修改Person类私有属性
....
System.out.println("4.修改Person类私有属性");
Field nameField = person.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(person1, "压缩");
System.out.println(person1);
调用无参私有方法
在Person中增加无参私有方法
// Person类
....
private void show() {
System.out.println("我是" + name + ", 今年" + age + "岁");
}
....
System.out.println("5.调用Person类无参私有方法");
Method showMethod = person.getDeclaredMethod("show");
showMethod.setAccessible(true);
showMethod.invoke(person1);
运行结果:
调用有参私有方法
Person类中增加有参私有方法
...
private void showAddress(String address) {
System.out.println("我家住在:" + address);
}
System.out.println("6.调用Person类有参私有方法");
Method showAddressMethod = person.getDeclaredMethod("showAddress", String.class);
showAddressMethod.setAccessible(true);
showAddressMethod.invoke(person1, "中国");
运行结果:
完整代码如下:
//Person 类
public class Person {
private String name;
private int age;
public Person() {
}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
private void show() {
System.out.println("我是" + name + ", 今年" + age + "岁");
}
private void showAddress(String address) {
System.out.println("我家住在:" + address);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
// Test类
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String args[]) {
try {
System.out.println("1.使用反射实例化对象");
Class> person = Class.forName("Person");
Person o = (Person) person.newInstance();
//相当于 Person o = new Person()
System.out.println(o);
System.out.println("2.通过私有构造方法创建对象");
Constructor> declaredConstructor = person.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);
Person person1 = (Person) declaredConstructor.newInstance("盖伦", 30);
System.out.println(person1.toString());
System.out.println("3.查看Person类私有属性");
Field[] declaredFields = person.getDeclaredFields();
for (Field f : declaredFields) {
System.out.println(f.getName());
}
System.out.println("4.修改Person类私有属性");
Field nameField = person.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(person1, "压缩");
System.out.println(person1);
System.out.println("5.调用Person类无参私有方法");
Method showMethod = person.getDeclaredMethod("show");
showMethod.setAccessible(true);
showMethod.invoke(person1);
System.out.println("6.调用Person类有参私有方法");
Method showAddressMethod = person.getDeclaredMethod("showAddress", String.class);
showAddressMethod.setAccessible(true);
showAddressMethod.invoke(person1, "中国");
} catch (Exception e) {
e.printStackTrace();
}
}
}