JAVA基础知识之JVM-——通过反射查看类信息
Class实例
当类被加载之后,JVM中就会生成一个Class实例,通过这个实例就可以访问JVM中的这个类。有三种方式可以获取Class对象
- 使用Class的静态方法forName(完整包名)
- 调用类自身的class属性
- 调用类对象的getClass方法。 该方法继承自java.lang.Object,任何对象都有这个方法。
通常情况下,推荐用第二种方式。因为第二种方式既不需要重建对象,也不需要调用方法,而是直接读取类的属性。
从Class实例中获取类的信息
Class类提供了大量方法来获取Class实例所对应的类的信息,下面是一些常用的方法,
Constructor<T> getConstructor(Class<T>...parameterTypes), 返回类中带参数的构造函数
Method getMethod(String name, Class<?>...parameterTypes), 返回带参数的指定方法
Filed getFiled(String name), 返回类中的属性变量
关于不定形参Class<T>...parameterTypes的解释,
例如类中有两个同名方法,
public void info(String name),
public void info(String name, int age)
如果用反射的方法,仅仅通过方法名是无法区分开的,因此需要指明形参
这里的形参用的是Class<T> 类型的,即 java.lang.String 这种,而不是字符串的String类型,
正如上面第一节所说,使用 类名.class 可以获取这个类在JVM中的Class实例, 所以要使用反射来获取上面两个类的info方法的方式为,
1 Class<T> clazz = T.class 2 3 clazz.getMethod("info", String.class) 4 5 clazz.getMethod("info", String.class, Integer.class)
下面例子演示了Class 的大部分方法,如何从Class实例中获取对应类的信息,
1 package jvmTest; 2 3 import java.lang.annotation.Annotation; 4 import java.lang.annotation.Retention; 5 import java.lang.reflect.Constructor; 6 import java.lang.reflect.Method; 7 import java.util.Arrays; 8 9 /* 10 //定义可重复注解 11 @Repeatable(Annos.class) 12 @interface Anno {} 13 @Retention(Value=RetentionPolicy.RUNTIME) 14 @interface Annos { 15 Anno[] value(); 16 } 17 //使用4个注解修饰该类 18 @SuppressWarnings(value="unchecked") 19 @Deprecated 20 //使用重复注解修饰该类 21 @Anno 22 @Anno 23 */ 24 public class ClassTest { 25 26 private ClassTest() {} 27 public ClassTest(String name) { 28 System.out.println("执行有参数构造器"); 29 } 30 public void info() { 31 System.out.println("执行无参info"); 32 } 33 public void info(String str) { 34 System.out.println("执行有参数info"); 35 } 36 37 class Inner {} 38 39 public static void main(String[] args) throws Exception{ 40 //获取ClassTest在JVM中对应的Class实例 41 Class<ClassTest> clazz = ClassTest.class; 42 //获取clazz对应类的全部构造器 43 Constructor[] ctors = clazz.getDeclaredConstructors(); 44 System.out.println("ClassTest的全部构造器如下:"); 45 for (Constructor c: ctors) { 46 System.out.println(c); 47 } 48 //获取所有public构造器 49 Constructor[] publicCtors = clazz.getConstructors(); 50 System.out.println("ClassTest的全部public构造器如下:"); 51 for (Constructor c: publicCtors) { 52 System.out.println(c); 53 } 54 //获取所有public方法 55 Method[] mtds = clazz.getMethods(); 56 System.out.println("ClassTest所有public方法如下:"); 57 for (Method md : mtds) { 58 System.out.println(md); 59 } 60 //获取指定方法 61 System.out.println("ClassTest中带一个字符串参数的info方法: " + clazz.getMethod("info", String.class)); 62 //获取全部注解 63 Annotation[] anns = clazz.getAnnotations(); 64 System.out.println("ClassTest全部注解如下: "); 65 for (Annotation an : anns) { 66 System.out.println(an); 67 } 68 // System.out.println("ClassTest类的@SuppressWarning注解为: " + Arrays.toString(clazz.getAnno)) 69 //获取全部内部类 70 Class<?>[] inners = clazz.getDeclaredClasses(); 71 System.out.println("ClassTest所有内部类: "); 72 for (Class<?> c : inners) { 73 System.out.println(c); 74 } 75 //使用forName()加载内部类 76 //Class inClazz = Class.forName("ClassTest$Inner"); 77 //通过getDeclaringClass()访问该类所在的外部类 78 //System.out.println("inClazz对应的外部类: " + inClazz.getDeclaringClass()); 79 System.out.println("ClassTest的包为: " + clazz.getPackage()); 80 System.out.println("ClassTest的父类为: " + clazz.getSuperclass()); 81 } 82 }