在Java中,每个类被加载之后,系统会为该类生成一个对应的class对象,也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。通过该class对象就可以访问到jvm中的这个类。在Java程序中获得class对象通常有如下3种方式:- 使用class类的forName(String clazzName)静态方法,该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名(必须添加完整包名)
- 调用某个类的class属性来获取该类对应的class对象。例如,Person.class将会返回Person类对应的class对象
- 调用某个对象的getClass()方法。该方法是Java.lang.Object类中的一个方法,所以所有的java对象都可以调用该方法,该方法将会返回该对象所属类对应的class对象。
对于第一种方式和第二种方式都是直接根据类来取得该类的class对象,相比之下,第二种方式有如下两种优势: - 代码更安全。程序在编译阶段就可以检查需要访问的class对象是否存在
- 程序性能更好。因为这种方式无需调用方法,故性能更好
也就是说,大部分时间我们都应该使用第二种方式来获取指定类的class对象。但如果我们只有一个字符串,例如“java.lang.String”(譬如在配置文件中取出数据来利用反射机制创建对象的情况),若需要获取该字符串对应的class对象,则只能使用第一种方式,使用class类的forName(String clazzName)静态方法获取class对象时该方法可能会抛出ClassNotFoundException异常 一旦获得了某个类所对应的class对象之后,程序就可以调用class对象的方法来获的该对象和该对象的真实信息。 class类提供了大量的实例方法来获取该class对象所对应类的详细信息: 这里举几个例子 下面4个方法用于获取class对应的类所包含的构造器:(不会返回父类的构造器) - Constructor<T> getConstructor(class<?>...parameterTypes):返回此Class对象对应类的指定public构造器
- Constuctor<?> [ ] getConnstuctor():返回此class对象的所有public构造器
- Constructor<T> getDeclaredConstructor(class<?>...parameterTypes):返回该class对象对应类指定的构造器,与构造器的访问权限无关
- Constuctor<?> [ ] getDeclaredConstructor():返回该class对象的全部构造器,与构造器的访问权限无关
下面4个方法用于获取class对象对应类所包含的方法:(会返回法雷的方法) - Method getMethod(String name,class<?>...parameterTypes):返回此Class对象对应类的指定public方法
- Method [ ] getMethod():返回此class对象的所有public方法
- Method getDeclaredMethod(String name,class<?>...parameterTypes):返回该class对象对应类指定的方法,与方法的访问权限无关
- Method [ ] getDeclaredMethod():返回该class对象的全部方法,与方法的访问权限无关
下面4个方法用于访问class对应类所包含的File - Filed getFiled(String name):返回此Class对象对应类的指定public Filed
- Filed [ ] getFiled():返回此class对象的所有public Filed
- Filed getDeclaredFiled(String name):返回该class对象对应类指定的 Filed,与 Filed的访问权限无关
- Filed [ ] getDeclaredFiled():返回该class对象的全部 Filed,与 Filed的访问权限无关
其他的方法可以查看class 类的api。 上面的多个getMethod()方法和getConstructor()方法中,都需要传入多个类型为Class<?>的参数,用于获取指定的方法或指定的构造器。关于这个参数的作用,假设某个类内包含如下3个info方法签名: - public void info()
- public void info(String str)
- public void info(String str,Integer num)
这3个同名方法属于重载,他们的方法名相同,但参数列表不同。在java语言中需要确定一个方法光有方法名是不行的,如果需要确定一个方法,则应该由方法名和形参列表来确定,但形参名没有实际意义,所以只能由形参类型来确定。例如,我们想要确定第二个info方法,则必须指定方法名为info,形参类表为String.class clazz.getMethod("info",String.class) 想要获取第3个info方法,则可以: clazz.getMethod("info",String.class,Integer.class) 获取构造器是无需传入构造器名,同一个类的所有构造器的名字是相同的,所以要确定一个构造器只要指定形参列表即可。 下面举个例子示范如何通过该class对象来获取对应类的详细信息: - import java.lang.reflect.*;
- import java.lang.annotation.*;
- public class ClassTest
- {
- // 为该类定义一个私有的构造器
- private ClassTest()
- {
- }
- // 定义一个有参数的构造器
- public ClassTest(String name)
- {
- System.out.println("执行有参数的构造器");
- }
- // 定义一个无参数的info方法
- public void info()
- {
- System.out.println("执行无参数的info方法");
- }
- // 定义一个有参数的info方法
- public void info(String str)
- {
- System.out.println("执行有参数的info方法"
- + ",其str参数值:" + str);
- }
- // 定义一个测试用的内部类
- class Inner
- {
- }
- public static void main(String[] args)
- throws Exception
- {
- // 下面代码可以获取ClassTest对应的Class
- Class<ClassTest> clazz = ClassTest.class;
- // 获取该Class对象所对应类的全部构造器
- Constructor[] ctors = clazz.getDeclaredConstructors();
- System.out.println("ClassTest的全部构造器如下:");
- for (Constructor c : ctors)
- {
- System.out.println(c);
- }
- // 获取该Class对象所对应类的全部public构造器
- Constructor[] publicCtors = clazz.getConstructors();
- System.out.println("ClassTest的全部public构造器如下:");
- for (Constructor c : publicCtors)
- {
- System.out.println(c);
- }
- // 获取该Class对象所对应类的全部public方法
- Method[] mtds = clazz.getMethods();
- System.out.println("ClassTest的全部public方法如下:");
- for (Method md : mtds)
- {
- System.out.println(md);
- }
- // 获取该Class对象所对应类的指定方法
- System.out.println("ClassTest里带一个字符串参数的info方法为:"
- + clazz.getMethod("info" , String.class));
- // 获取该Class对象所对应类的上的全部注释
- Annotation[] anns = clazz.getAnnotations();
- System.out.println("ClassTest的全部Annotation如下:");
- for (Annotation an : anns)
- {
- System.out.println(an);
- }
- System.out.println("该Class元素上的@SuppressWarnings注释为:"
- + clazz.getAnnotation(SuppressWarnings.class));
- System.out.println("ClassTest的包为:" + clazz.getPackage());
- System.out.println("ClassTest的父类为:" + clazz.getSuperclass());
- }
- }
复制代码
结果为:
|