Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
所有反射操作的入口点是 java.lang.Class。除 java.lang.reflect.ReflectPermission 外,java.lang.reflect 中的类都没有公共构造函数。要获得这些类,必须在 Class 上调用适当的方法。有几种方法可以获取 Class,具体取决于代码是否可以访问对象,类名,类型或现有 Class。
如果对象的实例可用,那么获取 Class 的最简单方法是调用 Object.getClass()。当然,这仅适用于所有都继承自 Object 的引用类型。一些例子如下。
Class c = "foo".getClass();
Class c = System.console().getClass();
有一个与虚拟机关联的唯一控制台,由 static 方法 System.console() 返回。getClass() 返回的值是对应于 java.io.Console 的 Class。
enum E { A, B }
Class c = A.getClass();
A 是枚举 E 的实例;因此 getClass() 返回与枚举类型 E 对应的 Class。
byte[] bytes = new byte[1024]; Class c = bytes.getClass();
由于数组是 Objects,因此也可以在数组实例上调用 getClass()。返回的 Class 对应于组件类型 byte 的数组。
import java.util.HashSet; import java.util.Set; Set<String> s = new HashSet<String>(); Class c = s.getClass();
在这种情况下,java.util.Set 是 java.util.HashSet 类型的对象的接口。getClass() 返回的值是与 java.util.HashSet 对应的类。
如果类型可用但没有实例可用,那么可以通过将 ".class" 追加到类型名称后来获得 Class。这也是获取基本类型的 Class 的最简单方法。
boolean b; Class c = b.getClass(); // compile-time error Class c = boolean.class; // correct
请注意,语句 boolean.getClass() 会产生编译时错误,因为 boolean 是基本类型,无法解除引用。.class 语法返回与 boolean 类型对应的 Class。
Class c = java.io.PrintStream.class;
变量 c 将是 Class 对应于类型 java.io.PrintStream。
Class c = int[][][].class;
.class 语法可用于获取对应于给定类型的多维数组的 Class。
如果类的完全限定名称可用,则可以使用静态方法 Class.forName() 获取相应的 Class。这不能用于基本类型。数组类名称的语法由 Class.getName() 描述。此语法适用于引用数组和基本类型数组。
Class c = Class.forName("com.duke.MyLocaleServiceProvider");
此语句将根据给定的完全限定名称创建一个类。
Class cDoubleArray = Class.forName("[D");
Class cStringArray = Class.forName("[[Ljava.lang.String;");
变量 cDoubleArray 将包含对应于基本类型 double 数组的 Class(即与 double[].class 相同)。cStringArray 变量将包含对应于 String 的二维数组的 Class(即与 String[][].class相同)。
.class 语法是获取基本类型的 Class 的更方便和首选的方法;然而,有另一种方法来获得 Class。每个基本类型和 void 在 java.lang 中都有一个包装类,用于将基元类型装箱到引用类型。每个包装类包含一个名为 TYPE 的字段,它等于被包装的基本类型的 Class。
Class c = Double.TYPE;
有一个类 java.lang.Double,用于在需要 Object 时包装基本类型 double。Double.TYPE 的值与 double.class 的值相同。
Class c = Void.TYPE;
Void.TYPE与 void.class 相同。
有几个反射 API 可以返回类,但只有在已经直接或间接获得 Class 的情况下才能访问这些类。
Class.getSuperclass()Class c = javax.swing.JButton.class.getSuperclass();
javax.swing.JButton 的超类是 javax.swing.AbstractButton。Class.getClasses()Class<?>[] c = Character.class.getClasses();
Character包含两个成员类 Character.Subset 和 Character.UnicodeBlock。Class.getDeclaredClasses()Class<?>[] c = Character.class.getDeclaredClasses();
Character包含两个公共成员类 Character.Subset 和 Character.UnicodeBlock 和一个私有类 Character.CharacterCache。Class.getDeclaringClass()java.lang.reflect.Field.getDeclaringClass()java.lang.reflect.Method.getDeclaringClass()java.lang.reflect.Constructor.getDeclaringClass()Class。Anonymous Class Declarations 不会有声明类,但会有一个封闭类。
import java.lang.reflect.Field;
Field f = System.class.getField("out");
Class c = f.getDeclaringClass();
out 在 System 中声明。
public class MyClass {
static Object o = new Object() {
public void m() {}
};
static Class<c> = o.getClass().getEnclosingClass();
}
o 定义的匿名类的声明类是 null。Class.getEnclosingClass()Class c = Thread.State.class().getEnclosingClass();
Thread.State 的封闭类是 Thread。
public class MyClass {
static Object o = new Object() {
public void m() {}
};
static Class<c> = o.getClass().getEnclosingClass();
}
o 定义的匿名类由 MyClass 封闭。