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
封闭。