原文连接:http://tutorials.jenkov.com/java-reflection/classes.html
通过使用 Java 反射,我们可以在程序运行时来观察 Java classes 。通常我们使用 Java 反射最先会观察 classes ,通过 classes 我们可以获取到的信息有:
还有 Java classes 相关的更多信息。我们可以参考 JavaDoc for java.lang.Class 来获取更全面的信息。本文将对上面提到的所有的知识点作一个简单的涉及。上面列出的一些主题将会在单独的部分做一个更详细的介绍。比如,本文将会向大家展示怎样获取所有的 method 或者是一个特定的 method ,但会在专门的一篇文章中来介绍怎样调用那个特定的 method ,如果有多个同名的 method 怎样根据 method 名称和给定的 method 参数来匹配找到我们想要找的那个特定的 method ,调用 Java 反射的方法会抛出什么异常,怎样发现一个get、set方法等。本文的主要目的就是基本的介绍一下 Class 对象以及我们可以从该对象中获取到哪些信息。
要想使用某一个 class 的 Java 反射我们首先得获得该 class 的 java.lang.Class 对象。在 Java 中所有的类型包括原生类型(int、long、float等)、数组都有一个与之相关联的 Class 对象。在编译期如果我们能知道一个 Java class ,我们就可以通过下面的方法来获取到一个 Class 对象:
Class aClass = User.class;
如果在编译期我们不知道 Class 名,但我们在程序运行时能获得 class 的字符串全名,我们可以通过下面的代码来得到一个 Class 对象:
String className = "test.User"; Class aClass = Class.forName(className);
当我们通过使用 Class.forName() 方法来获取一个 Class 对象时,我们传递的这个 className 必须是一个 class 的全名(包括所有的包名)。比如, User 位于包 test 下,那么全名就是 test.User ,如果 User 位于 com.model.test 包下,那么 class 的全名就是 com.model.test.User 。
Class.forName() 这个方法在程序运行时如果在 classpath 路径下找不到那个 class ,会抛出一个 ClassNotFoundException 异常。
从一个 Class 对象中我们可以获取到它的两种名称。我们可以通过 getName() 方法来获取到一个 class 的全名(包括包名):
String className = "test.User"; Class aClass = Class.forName(className); String fullName = aClass.getName();
如果我们只想获得一个 class 的名称而不需要获取包名我们可以通过调用 getSimpleName() 方法来达到目的:
String className = "test.User"; Class aClass = Class.forName(className); String simpleName = aClass.getSimpleName();
我们可以通过 Class 对象来获取到一个 class 的访问修饰符(private、public、static等),我们可以通过下面的方式来获取访问修饰符:
int modifiers = aClass.getModifiers();
modifiers是所有访问修饰符标识位的一个整型表示的集合(学过linux的同学都会知道,linux中有权限这一说,有三种权限读、写、执行即r、w、x,可以分别用4、2、1来代表,如果给定一个整数是7,7=4+2+1,那么代表的权限就是读、写、执行,如果给定的整数是1,那么代表的权限一定是执行,如果给定的整数是6,6=4+2,那么代表的权限一定是读、写等等)。我们可以通过java.lang.reflect.Modifier的以下方法来检查一个class的访问修饰符:
Modifier.isAbstract( modifiers); Modifier.isFinal( modifiers); Modifier.isInterface( modifiers); Modifier.isNative( modifiers); Modifier.isPrivate( modifiers); Modifier.isProtected( modifiers); Modifier.isPublic( modifiers); Modifier.isStatic( modifiers); Modifier.isStrict( modifiers); Modifier.isSynchronized( modifiers); Modifier.isTransient( modifiers); Modifier.isVolatile( modifiers)
我们可以通过以下的代码来获取一个 Class 对象的包信息:
String className = "test.User"; Class aClass = Class.forName(className); Package aPackage = aClass.getPackage();
通过 Package 对象我们可以获取到包的信息,比如可以获取到包名。我们也可以获取到位于 classpath 下的 JAR 包中专门用于具体说明这个包的的 Manifest 文件。 java.lang.Package 的详细信息
通过Class对象我们可以获取到class对象的父类,下面是代码实现:
String className = "test.User"; Class aClass = Class.forName(className); Class superClass = aClass.getSuperclass();
superclass 对象就像其他的 Class 对象一样,我们也可以在 superclass 对象上继续对其进行反射。
通过下面的代码我们可以获取到一个给定的class实现的的所有接口:
String className = "test.User"; Class aClass = Class.forName(className); Class[] interfaces = aClass.getInterfaces();
在 Java 反射中 Class 对象也可以代表接口,一个 class 可以实现多个接口,因此调用 aClass.getInterfaces() 方法会返回来一个类型为Class的数组。
注意:只有被给定的一个 class 所声明实现的那些特定接口才会被返回。如果被给定的那个 class 所继承的父类实现的接口,但所给定的那个 class 并没有再特殊声明实现了接口,在返回的数组中是不包含这一类的接口的。尽管事实上被给定的那个 class 实现了那些接口,因为通过调用父类的getInterfaces() 方法会返回这些接口,所以在子类中调用 getInterfaces() 方法就不会返回那些接口了。
为了完整的获取到一个给定的 class 的所有接口,我们可以通过调用给定的 class 的 getInterfaces()和 递归的调用它的父类getInterfaces()。
我们可以通过下面的方式来获取到一个 class 的所有构造方法:
Constructor[] constructors = aClass.getConstructors();
在后面我们会写一篇介绍 Constructors 的文章来详细的介绍构造方法。
我们可以通过下面的方式来获取到一个 class 的所有方法:
Method[] method = aClass.getMethods();
在后面我们会写一篇介绍 Methods 的文章来详细的介绍它。
我们可以通过下面的方式来获取到一个 class 的所有字段:
Field[] method = aClass.getFields();
在后面我们会写一篇介绍 Fields 的文章来详细的介绍它。
Annotation[] annotations = aClass.getAnnotations();
我们可以在后面我们会写一篇介绍 Annotations 的文章来详细的介绍它。