NVIDIA RTX wallpaper
594 字
3 分钟
HIT-软件构造 | Java 反射
在 Java 运行时,如果我们拿到一个 Object
,它可能是某个类的实例。如果我们想使用这个类的某个方法,却不知道这个类的名字,即连强制类型转换也做不了,那如何调用我们想要执行的方法呢。解决方案是使用 Java 反射。
Class
类与实例
如果我们有两个类 Type1
和 Type2
的实例,然后将其转换成 Object
实例。表面上我们看不出这两个 Object
实例的区别,因为我们对他们的信息一无所知,但是这只是因为他们的引用是 Object
类型的而已。
Java runtime 提供了一种数据类型,称为 Class
,Java 程序开始运行后,每次首次加载一个 class
,都会用这个 class
的信息创建一个 Class
实例,即这个 Class
实例将会包含这个类的所有信息。Object
类提供了一个接口能让我们拿到任何一个对象的 Class
实例。也就是说,对于上述的 Type1
和 Type2
转换成 Object
后的实例,我们可以拿到它们的 Class
实例,来区分这两个实例哪一个是 Type1
的实例、哪一个是 Type2
。
class Type1 { ... }
class Type2 { ... }
Type1 type1 = new Type1();
Type2 type2 = new Type2();
Object obj1 = (Object)type1;
Object obj2 = (Object)type2;
Class cls1 = obj1.getClass();
Class cls2 = obj2.getClass();
除此之外,还可以已知类的名字,然后直接获得其 Class
实例:
Class cls = Type1.class;
或使用包路径格式的完整类名:
Class cls = Class.forName("com.vonbrank.Type1");
用 Class
实例访问字段
假设有一个类 Person
,定义如下:
class Person {
private String name;
public Person(String name) {
this.name = name;
}
}
在下面的 test
方法中,我们只能拿到它实例的 Object
引用,如果想访问 name
可以这样写:
public class Main {
public static void main(String[] args) {
Person person = new Person("Xiao Ming");
test(person);
}
static void test(Object obj) {
Class cls = obj.getClass();
Field field = cls.getDeclaredField("name");
Object value = field.get(p);
System.out.println(value); // "Xiao Ming"
}
}
调用方法
此处我们以 String
为例展示通过反射调用对象实例的方法:
public class Main {
public static void main(String[] args) throws Exception {
// String对象:
String s = "Hello world";
// 获取String substring(int)方法,参数为int:
Method m = String.class.getMethod("substring", int.class);
// 在s对象上调用该方法并获取结果:
String r = (String) m.invoke(s, 6);
// 打印调用结果:
System.out.println(r);
}
}