所有反射操作的入口是java.lang.Class.包括异常类java.lang.reflect.ReflectPermission,java.lang.reflect包中的所有类都没有公有构造函数。为了获得这些类,需要调用Class类中合适的方法。有几种方式可以获取一个Class,取决于代码是否有相应实例对象、类名称、类型或者一个存在的Class。
Object.getClass()
如果一个对象的实例是可用的,那么获取它的类类型最简单的方法是调用Object.getClass().当然,这种方法仅适用于继承Object类的引用类型。例如:
Class = "foo".getClass();
返回的类类型是String
Class c = System.console().getCLass();
这是一个由静态方法System.console()返回的和虚拟机关联的唯一控制台,getClass()方法返回的值和java.io.Console类型是一致的
enum E{ A,B}
Class c = A.getClass();
A是枚举E的一个实例,那么getClass()方法返回的类型和枚举类型E是一致的。
byte[] bytes = new byte[1024];
Class c = bytes.getClass();
由于数组都是对象,同样可以调用数组实例的getClass()方法,它返回的类类型和数组元素类型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类型是一致的。
The .class Syntax
如果类型是可以获得的,但是没有这类型的实例,那么是可以通过这类型名称后加”.class”方式来获得这个类型。这也是获取基本数据类型的类类型的最简单方法。
boolean b ;
Class c = b.getClass();//error
Class c = boolean.class;
注意,语句boolean.getClass()会产生一个编译时的错误,因为boolean是一个基本数据类型并且不能够被引用。这个.class语句返回类类型和类型boolean是一致的。
Class c = java.io.PrintStream.class;
变量c将会和java.io.PrintStream类型一致的。
Class c = int[][].class;
这个.class语句可能被用于获取一个和多维数据元素类型一致的类类型。
Class.forName()
如果一个类的全称是可以获得的,那么可以使用静态方法Class.forName()来获取相应的类类型,这个不能用于基本数据类型。这用法对于数据类型的名称被描述成Class.getName(),这个则适用于引用和基本数据类型。
Class c = Class.forName("com.duke.MyLocaleServiceProvider");
这个语句会用已给定的全名创建一个Class对象。
Class cDoubleArray = Class.forName("[D");
Class cStringArray = Class.forName("[[Ljava.lang.String;");
变量cDoubleArray将会是和数组元素类型double一样的类型(和double[].class相似);变量cStringArray将会是和二维数组元素类型String一致(类似String[][].class)
TYPE Field for Primitive Type Wrappers
对于基本数据类型,.class方法获取Class对象是一个更加方便和首选的方式,然而,还有另外一种方法可以获取类类型,每个基本数据类型和void都有一个相应的封装类型,存在于包java.lang,封装类型被用于将基本类型封装成引用类型。每个封装类包含一个字段,名称为TYPE,这个相当于Class,对于被封装的基本数据类型。
Class c = Double.TYPE;
类java.lang.Double被用于封装基本数据类型double,无论什么时候需要一个对象,Double.TYPE和double.class的值是一样的。
Class c = Void.TYPE;
Void.TYPE相当于void.class
Methods that Return Classes
有一些反射APIs但仅当已经直接或者间接的获取到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()
返回这些被声明的成员类型,匿名类将没有声明类型但是包含一个封装类型。
import java.lang.reflect.Field;
Field f = System.class.getField("out");
Class c = f.getDeclaringClass();
字段在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封闭类。