java中的反射 2.2——类:检查一个类的声明信息@译自Oracle官方文档

6 篇文章 0 订阅
5 篇文章 0 订阅

译自:http://docs.oracle.com/javase/tutorial/reflect/class/classModifiers.html

一个类可以在声明时使用一些修饰符,这些修饰符会影响其运行时行为:

  • 访问修饰符:public,protected和private
  • 要求重写(override):abstract
  • 限定为一个实例:static
  • 禁止修改:final
  • 强制精确浮点:strictfp
  • 注解(Annotations)

并不是所有的类都可以用任意修饰符进行修饰,比如接口不能使用final修饰而枚举类型不能用abstract修饰。java.lang.reflect.Modifier包含类所有类型的修饰符。同时它也包含了可以解析由Class.getModifiers()返回的修饰符的方法。

下面这段代码例子展示了如何获取一个类的包括修饰符、泛型类型参数、实现的接口和继承路径在内的声明组件。由于Class类实现了java.lang.reflect.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());
		out.format("%n%n");
	    } 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");
	    }

        // production code should handle this exception more gracefully
	} 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.utiol.concurrent.ConcurrentNavigableMap类在源代码中的声明:

public interface ConcurrentNavigableMap<K,V>
    extends ConcurrentMap<K,V>, NavigableMap<K,V>

注意由于这是一个接口,所以被声明为abstract。编译器会为每一个接口添加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.io.Serializable

Inheritance Path:
  java.lang.Object

Annotations:
  -- No Annotations --


由于数组是运行时对象,所有的类型信息都是由JVM定义的。尤其是数组实现了Cloneable和java.io.Serializable接口而它们的直接父类都是Object。

$ 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

Inheritance Path:
  java.lang.Object

Annotations:
  @java.lang.Deprecated()

这些输出显示java.security.Identity这个被弃用的API使用类注解java.lang.Deprecated。这可以被反射代码用于探测被弃用的API。


注意:并不是所有的注解都可以通过反射获取。只有那些java.lang.annotation.RetentionPolicy字段值为RUNTIME的可以被获取。在java预定义的三个注解@Deprecated,@Override和@SuppressWarnings中只有@Deprecated是符合的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值