java.lang.reflect.Modifier
Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。
修饰符集被表示为整数,用不同的位位置 (bit position) 表示不同的修饰符。表示修饰符的常量值来自于 The JavaTM Virtual Machine Specification, Second edition 的表 4.1、4.4、4.5 和 4.7。
字段 | 说明 | 取值 |
---|---|---|
ABSTRACT | 表示 abstract 修饰符的 int 的值。 | 1024 |
FINAL | 表示 final修饰符的 int 的值。 | 16 |
INTERFACE | 表示 interface修饰符的 int 的值。 | 512 |
NATIVE | 表示 native修饰符的 int 的值。 | 256 |
PRIVATE | 表示 private修饰符的 int 的值。 | 2 |
PROTECTED | 表示 protected修饰符的 int 的值。 | 4 |
PUBLIC | 表示 public修饰符的 int 的值。 | 1 |
STATIC | 表示 static修饰符的 int 的值。 | 8 |
STRICT | 表示 strictfp修饰符的 int 的值。 | 2048 |
SYNCHRONIZED | 表示 synchronized修饰符的 int 的值。 | 32 |
TRANSIENT | 表示 transient修饰符的 int 的值。 | 128 |
VOLATILE | 表示 volatile修饰符的 int 的值。 | 64 |
java.lang.reflect.Member
- 提供类和接口,以获取关于类和对象的反射信息。
- 已知实现该接口的类有Method、Field、Constructor
- Member接口是method、field、constructor对象识别信息
//用于标识【类】或【接口的所有公共成员的集合】,包括继承成员
public static final int PUBLIC = 0;
用于标识【类】或【接口的声明成员集】。不包含继承成员。
public static final int DECLARED = 1;
getDeclaringClass()
//返回表示类或接口的类对象(Class),该类或接口中由Meber声明的成员或构造函数。
public Class<?> getDeclaringClass();
getName()
//返回此成员所表示的基础成员或构造函数的简单名称
public String getName();
getModifiers()
//返回字段、构造函数的Java语言修饰符,返回值为integer; 该修饰符可以使用Mofier类来解码
public int getModifiers();
isSynthetic()
//如果该成员是由编译器引入的,返回true;否则返回false
public boolean isSynthetic();
java.lang.reflect.Type
没有泛型的时候,只有原始类型。此时,所有的原始类型都通过字节码文件类Class类进行抽象。Class类的一个具体对象就代表一个指定的原始类型
泛型出现之后,扩充了数据类型。从只有原始类型扩充了参数化类型、类型变量类型、限定符类型 、泛型数组类型。
- Class(原始/基本类型,也叫raw type):不仅仅包含我们平常所指的类、枚举、数组、注解,还包括基本类型int、float等等
- TypeVariable(类型变量):比如List中的T等
- WildcardType( 泛型表达式类型):例如List< ? extends Number>这种
- ParameterizedType(参数化类型):就是我们平常所用到的泛型List、Map(注意和TypeVariable的区别)
- GenericArrayType(数组类型):并不是我们工作中所使用的数组String[] 、byte[](这种都属于Class),而是带有泛型的数组,即T[] 泛型数组
Type接口本身算是一个标记接口,不提供任何需要复写的方法
Type的直接子类只有一个,也就是Class,代表着类型中的原始类型以及基本类型。
public interface Type {
default String getTypeName() {
return toString();
}
}
GenericArrayType(数组类型)
泛型数组,描述的是形如:A< T>[]或T[]类型变量和原始类型
public interface GenericArrayType extends Type {
//返回泛型数组中元素的Type类型,即List<String>[] 中的 List<String>
Type getGenericComponentType();
}
public class GenericArrayTypeTest<T> {
// 这里面有各种各样的数组:各有不同 方便看测试效果
// 含有泛型数组的才是GenericArrayType
public void testGenericArrayType(List<String>[] pTypeArray, T[] vTypeArray, List<String> list,
List<? extends Number> wildcardList, String[] strings, GenericArrayTypeTest[] test) {
}
public static void main(String[] args) {
Method[] declaredMethods = GenericArrayTypeTest.class.getDeclaredMethods();
for (Method method : declaredMethods) {
// main方法不用处理
if (method.getName().startsWith("main")) {
continue;
}
// 开始处理该方法===打印出此方法签名
System.out.println("declare Method:" + method); //declare Method:public void com.fsx.maintest.GenericArrayTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[],com.fsx.maintest.GenericArrayTypeTest[])
// 该方法能获取到该方法所有的实际的参数化类型,比如本例中有五个参数,那数组长度就是5
Type[] types = method.getGenericParameterTypes();
// 分组打印出来
for (Type type : types) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
System.out.println("ParameterizedType type :" + parameterizedType);
}
else if (type instanceof GenericArrayType) {
// 从结果
GenericArrayType genericArrayType = (GenericArrayType) type;
System.out.println("GenericArrayType type :" + genericArrayType);
Type genericComponentType = genericArrayType.getGenericComponentType();
System.out.println("genericComponentType:" + genericComponentType);
}
else if (type instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) type;
System.out.println("WildcardType type :" + wildcardType);
}
else if (type instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) type;
System.out.println("TypeVariable type :" + typeVariable);
}
else {
Class clazz = (Class) type;
System.out.println("type :" + clazz);
}
}
}
}
}
java.lang.reflect.AnnotatedElement
这个接口(AnnotatedElement)的对象代表了在当前JVM中的一个“被注解元素”(可以是Class,Method,Field,Constructor,Package等)。
在Java语言中,所有实现了这个接口的“元素”都是可以“被注解的元素”。使用这个接口中声明的方法可以读取(通过Java的反射机制)“被注解元素”的注解。这个接口中的所有方法返回的注解都是不可变的、并且都是可序列化的。这个接口中所有方法返回的数组可以被调用者修改,而不会影响其返回给其他调用者的数组。
子接口
- AnnotatedArrayType (被注解的数组类型)
- AnnotatedParameterizedType (被注解的参数化类型)
- AnnotatedType (被注解的类型)
- AnnotatedTypeVariable (被注解的类型变量)
- AnnotatedWildcardType (被注解的通配类型)
- GenericDeclaration (通用声明,用于表示声明型元素,如:类、方法、构造器等)
- TypeVariable (类型变量)
实现类
- AccessibleObject(可访问对象,如:方法、构造器、属性等)
- Class(类,就是你用Java语言编程时每天都要写的那个东西)
- Constructor(构造器,类的构造方法的类型)
- Executable(可执行的,如构造器和方法)
- Field(属性,类中属性的类型)
- Method(方法,类中方法的类型)
- Package(包,你每天都在声明的包的类型)
- Parameter(参数,主要指方法或函数的参数,其实是这些参数的类型)
getAnnotationsByType(Class)和getDeclaredAnnotationsByType(Class)方法在一个元素上支持多个相同类型的注释。
default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
如果指定类型的注解出现在当前元素上,则返回true,否则将返回false。这种方法主要是为了方便地访问一些已知的注解。
T getAnnotation(Class annotationClass)
如果在当前元素上存在参数所指定类型(annotationClass)的注解,则返回对应的注解,否则将返回null。
Annotation[] getAnnotations()
返回在这个元素上的所有注解。如果该元素没有注释,则返回值是长度为0的数组。该方法的调用者可以自由地修改返回的数组;它不会对返回给其他调用者的数组产生影响。
default T[] getAnnotationsByType(Class annotationClass)
返回与该元素相关联的注解。如果没有与此元素相关联的注解,则返回值是长度为0的数组。这个方法与getAnnotation(Class)的区别在于,该方法检测其参数是否为可重复的注解类型(JLS 9.6),如果是,则尝试通过“looking through”容器注解来查找该类型的一个或多个注解。该方法的调用者可以自由地修改返回的数组;它不会对返回给其他调用者的数组产生影响。参考@Repeatable。
* @since 1.8
*/
default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
/*
* Definition of associated: directly or indirectly present OR
* neither directly nor indirectly present AND the element is
* a Class, the annotation type is inheritable, and the
* annotation type is associated with the superclass of the
* element.
*/
T[] result = getDeclaredAnnotationsByType(annotationClass);
if (result.length == 0 && // Neither directly nor indirectly present
this instanceof Class && // the element is a class
AnnotationType.getInstance(annotationClass).isInherited()) { // Inheritable
Class<?> superClass = ((Class<?>) this).getSuperclass();
if (superClass != null) {
// Determine if the annotation is associated with the
// superclass
result = superClass.getAnnotationsByType(annotationClass);
}
}
return result;
}
default T getDeclaredAnnotation(Class annotationClass)
如果参数中所指定类型的注解是直接存在于当前元素上的,则返回对应的注解,否则将返回null。这个方法忽略了继承的注解。(如果没有直接在此元素上显示注释,则返回null。)
default T[] getDeclaredAnnotationsByType(Class annotationClass)
如果参数中所指定类型的注解是直接存在或间接存在于当前元素上的,则返回对应的注解。这种方法忽略了继承的注释。如果没有直接或间接地存在于此元素上的指定注解,则返回值是长度为0的数组。这个方法和getDeclaredAnnotation(Class)的区别在于,这个方法检测它的参数是否为可重复的注释类型(JLS 9.6),如果是,则尝试通过“looking through”容器注解来查找该类型的一个或多个注解。该方法的调用者可以自由地修改返回的数组;它不会对返回给其他调用者的数组产生影响。参考@Repeatable。
Annotation[] getDeclaredAnnotations()
返回直接出现在这个元素上的注解。这种方法忽略了继承的注解。如果在此元素上没有直接存在的注解,则返回值是长度为0的数组。该方法的调用者可以自由地修改返回的数组;它不会对返回给其他调用者的数组产生影响。
Java 注解继承
java.lang.annotation.Inherited
首先这个注解是javaAPI四个元注解之一,用于修饰注解,位于java.lang.annotation包下。
仅用于标识一个注解,背标识过的注解可以被继承使用。
注解@A 使用了@Inherited 。@A使用到了接口B,接口B被C继承实现,在C中可以获取到注解@A的信息,如果 注解@A 没有使用@Inherited C中则不能获取到接口B的@A注解信息
注解的继承
实际上Java注解可以进行继承(也就是把多个注解合并成1个)
比如说SpringMVC的注解
@RestController
@RequestMapping("/person")
可以合并为一个
@PathRestController("/user")