Technorati 标记:  , ,

    承接着第一篇  , 这一节将继续谈到如何获取class对象的信息。class对象信息大致可分为两类:(1)class对象的信息;(2)class对象的成员信息。class对象的信息主要修饰修饰符,泛型参数,所实现的接口,继承的路径与及注解信息。class对象的成员信息主要有成员变量field,函数方法与构造器。在进入正文之前,如果对类的信息了解的不多,可以参考.

一、获取class对象信息

    获取class对象信息,主要是使用了一系列对应的函数的方法,在这里先做一个简单的介绍:

方法 描述
getCanonicalName() 获取class的类名
getModifiers() 获取class的修饰符
getTypeParameters() 获取class的泛型参数
getGenericInterfaces() 获取class实现的接口
getSuperclass() 获取class的父类,多次调用即可获得继承的路径
getAnnotations() 获取class的注解

    附:1、以上方法都是class对象的函数方法。方法名后带有“s“的,表示获取一个或多个的意思,都是以数组的形式返回。如”getTypeParameters()可能返回Type[]数组,其他的类似。注意的是”getmodifiers()“返回的是一个int。2、getAnnotations()并不能获取类的所有注解,只有实现了java.lang.reflect.AnnotatedElement的注解才可以被获得。如在预订的三个注解里@Override,@Deprecate,@SuppressWarning,只有@Deprecate可被获得。

    下面给一个Demo,演示如何遍历class对象的信息:

public class ClassDeclarationSpy {	public static void main(String[] args) {		try {			Class
c = Class.forName("java.util.Date"); out.println("类名:" + c.getCanonicalName()); out.println("修饰符:" + Modifier.toString(c.getModifiers())); out.print("泛型参数: "); TypeVariable
[] tv = c.getTypeParameters(); if (tv.length != 0) { for (TypeVariable
t : tv) out.print(t.getName() + " "); out.println(); } else { out.println("无泛型参数"); } out.print("实现的接口:"); Type[] intfs = c.getGenericInterfaces(); if (intfs.length != 0) { for (Type intf : intfs) out.println(" " + intf.toString()); } else { out.println("无实现的接口"); } out.print("继承路径:"); List
> l = new ArrayList<>(); assembleAncestor(c, l); if (l.size() != 0) { for (Class
cl : l) out.println(cl.getCanonicalName()); } else { out.println("无超类"); } out.print("注解:"); Annotation[] ann = c.getAnnotations(); if (ann.length != 0) { for (Annotation a : ann) out.print(a.toString() + " "); out.format("%n"); out.println(); } else { out.println("无注解"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } private static void assembleAncestor(Class
c, List
> l) { Class
ancestor = c.getSuperclass(); if (ancestor != null) { l.add(ancestor); assembleAncestor(ancestor, l); } }}

    其输出如下:

    类似的,可以获取java.util.List的信息,其输出如下:

     尝试去获取一个已经过时的class,如java.io.StringBufferInputStream

二、获取class对象的成员信息

    class对象的成员信息主要有成员变量,函数方法与构造器。与获取class对象信息类似,java提供了各种方法来获取成员信息——这些方法大概可以分两类,一类是直接获取所有的成员(变量,函数或者构造器)的方法,另外一类是搜索指定成员的方法。下面给出这些方法的概览:

1、获得与Class对象对应类的字段

Class API

继承的??

私有的??

no

yes

yes

no

no

yes

yes

no

    解释如下,“继承的?”代表了此方法是否可以获取从超类继承过来的filed值,“私有的”代表了此方法是否可以获取私有的field;如果方法含有“Declared”表示获取class对象自身含有的field值,如果没有,表示可以获取超类的field;如果方法名尾部含有“s”字样,表示此方法获取的是所有可以获取的field值返回一个Field<?>[]数组,反之,则是获取指定的field值,返回Field<T>。如“getDeclaredField()”表示获取当前class对象自身含有的field,此方法可以获取private修饰的field值,”getfields()”表示获取class对象所有public的field(包含从超累继承过来的),不可以获取private修饰的field。

2、获得与Class对象对应类的方法

Class API

继承的方法?

私有方法?

no

yes

yes

no

no

yes

yes

no

3、获得与Class对象对应类的构造方法

 API

继承的?

私有的?

——

yes

——

no

——

yes

——

no

    因为构造器不能从超类继承过来,因此继承对构造器来说没有任何意义,其他的用法与获取field值得方法类似。

   Demo:建立两个类Student,Bachelor,如下

package com.other;public class Student {	private int id;	private String sex;	public String name;		public Student() {	}	public Student(int id, String sex, String name) {		super();		this.id = id;		this.sex = sex;		this.name = name;	}	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}}
 
package com.other;public class Bachelor extends Student{	private String major;		public Bachelor() {	}	public Bachelor(String major) {		super();		this.major = major;	}}

    使用ClassHelp输出class对象的成员信息

public class ClassHelp {		public static void main(String[] args) throws Exception {					Student stu = new Bachelor("computer");			Class
clazz = stu.getClass(); //输出class的类名 System.out.println("class类名:" + clazz.getName()); //输出class所在的包 System.out.println("class包:"+ clazz.getPackage()); //获取指定的field System.out.println(clazz.getField("name"));// printMembers(clazz.getFields(), "Fields");// printMembers(clazz.getDeclaredConstructors(), "Constructors");// printMembers(clazz.getMethods(), "methods"); } public static void printMembers(Member[] mbrs, String s) { //Field,Mehtod,constructor都是Member的实现 out.println(s); for (Member mbr : mbrs) { if (mbr instanceof Field) out.println(((Field) mbr).toGenericString()); else if (mbr instanceof Constructor) out.println( ((Constructor
) mbr).toGenericString()); else if (mbr instanceof Method) out.println( ((Method) mbr).toGenericString()); } if (mbrs.length == 0) out.println("不存在" + s); out.println(); }}

    ClassHelp代码尽管简单,也演示了如何访问class对象成员的信息,其输出如下:

    另外三行注释代码的输出如下:

    对于Field、Constructors的输出应该没有什么问题,可Method的输出就多了很多“意外”的信息,其实这些都继承过来的方法——在java里,任意一个对象都是java,lang.Object的直接或间接的子类,所以getMethods()也相对应的输出里java。lang.Object的九种方法。

   方法toGenericString()返回描述此成员(Filed。Method,Constructor)的泛型描述,如果不存在,则调用toString()返回成员(Filed。Method,Constructor)字符串。