一个类可能被声明为包含该一个或者多个影响它运行时行为的修饰符。
- 访问权限修饰符:public,protected和private
- 需要重写修饰符:abstract
- 限制一个实例修饰符:static
- 禁止值修改:final
- 强制浮点型行为:strictfp
- 注解
不是所有的修饰符可以使用到所有的类上面,比如,一个接口不能被修饰为final,一个枚举不能被修饰为abstract。java.lang.reflect.Modifier包含所有存在修饰符的声明,它同样包含用来解析Class.getModifiers()返回的修饰符集合。
例子ClassDeclaration展示了怎么获取一个类的描述信息,包括修饰符、泛型类型、实现接口和继承路径,由于Class实现AnnotatedElement接口,它也可以查询运行时注解。
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class ClassDeclarationSpy{
public static void main(String... args){
try{
Class<?> c = Class.forName(args[0]);
out.format("Class:%n %s%n%n",c.getCanonicalName());
out.format("Modifiers:%n %s%n%n", Modifier.toString(c.getModifiers()));
out.format(Type Parameters:%n);
TypeVariable[] tv = c.getTypeParameters();
if(tv.length !=0){
out.format(" ");
for(TypeVariable t:tv){
out.format("%s ", t.getName());
}
}else{
out.format(" -- No Type Parameters --%n%n");
}
out.format("Implemented Interfaces:%n");
Type[] intfs = c.getGenericInterfaces();
if(intfs.length != 0){
for(Type intf : intfs){
out.format(" %s%n", intf.toString());
}
out.format("%n");
}else{
out.format(" -- No Implemented Interfaces --%n%n");
}
out.format("Inheritance Path:%n");
List<Class> l = new ArrayList<Class>();
printAncestor(c, l);
if (l.size() != 0) {
for (Class<?> cl : l)
out.format(" %s%n", cl.getCanonicalName());
out.format("%n");
} else {
out.format(" -- No Super Classes --%n%n");
}
out.format("Annotations:%n");
Annotation[] ann = c.getAnnotations();
if (ann.length != 0) {
for (Annotation a : ann)
out.format(" %s%n", a.toString());
out.format("%n");
} else {
out.format(" -- No Annotations --%n%n");
}
}catch(ClassNotFoundException x){
x.printStackTrace();
}
}
private static void printAncestor(Class<?> c,List<Class> l){
Class<?> ancestor = c.getSuperClass();
if(ancestor != null){
l.add(ancestor);
printAncestor(ancestor,l);
}
}
}
举一些输出例子,斜体字为输入参数。
$ *java ClassDeclarationSpy java.util.concurrent.ConcurrentNavigableMap*
Class:
java util.concurrent.ConcurrentNavigableMap
Modifiers:
public abstract interface
Type Parameters:
K V
Implemented Interfaces:
java.util.concurrent.ConcurrentMap<K,V>
java.util.NavigableMap<K,V>
Inheritance Path:
--No Super Classes --
Annotations:
--No Annotations --
这是给java.util.concurrent.ConcurrentNavigableMap实际的声明,在这个代码中:
public interface ConcurrentNavigableMap<K,V> extends ConcurrentMap<K,V>,NavigableMap<K,V>
注意,由于这个是一个接口,隐藏包含abstract,编译器会给每个接口添加这个修饰符,同时,这个声明包含了两个泛型参数,K和V,样例代码简单的打印这些参数,但是获取额外的关于在java.lang.reflect.TypeVariable中方法的信息。接口同样可以实现其它接口,如:
$ java ClassDeclarationSpy "[Ljava.lang.String;"
Class:
java.lang.String[]
Modifiers:
public abstract final
Type Parameters:
-- No Type Parameters --
Implemented Interfaces:
interface java.lang.Cloneable
interface java.lang.Serializable
Interitance Path:
java.lang.Object
Annotations:
-- No Annotations --
由于数组是运行时对象,他们所有的类型信息由java虚拟机定义,尤其,数组实现Cloneable和java.io.Serializable和其它直接父类。
$ java ClassDeclarationSpy java.io.InterruptedIOException
Class:
java.io.InterruptedIOException
Modifiers:
public
Type Parameters:
-- No Type Parameters --
Implemented Interfaces:
-- No Implemented Interfaces --
Inheritance Path:
java.io.IOException
java.lang.Exception
java.lang.Throwable
java.lang.Object
Annotations:
-- No Annotations --
从继承路径,可以推断出java.io.InterruptedIOException是一个受检异常类型,因为RuntimeException是它的父类。
$ java ClassDeclarationSpy java.security.Identity
Class:
java.security.Identity
Modifiers:
public abstract
Type Parameters:
-- No Type Parameters --
Implemented Interfaces:
interface java.security.Principal
interface java.io.Serializable
Interitance Path:
java.lang.Object
Annotations:
@java.lang.Deprecated()
这个输出展示了java.security.Identity是一个废弃api,含有java.lang.Deprecated注解,这个可能用于反射代码来检查废弃apis