一、注解
元注解
元注解是用来修饰注解的注解,java提供了3种元注解。
@Retention
RetentionPolicy.SOURCE
表明注解仅存在源码之中,不存在.class文件中,更不能运行时可见。常见的注解为@Override, @SuppressWarnings等。
RetentionPolicy.CLASS
这是默认的注解保留策略。这种策略下,注解将存在于.class文件中,但是不能被运行时访问。通常这种注解策略用来处理一些字节码级别的操作。
RetentionPolicy.RUNTIME
这种策略下可以被运行时访问到。通常情况下,我们都会结合反射来做一些事情。
@Target
注解修饰的位置
@Inherited
注解是否可以被子类继承
自定义注解
如下定义了一个MyAnnotation注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD})
@Inherited
public @interface MyAnnotation {
String name();
String value() default “”;
}
二、泛型
Java采用泛型擦除机制来引入泛型。Java中的泛型仅仅是给编译器Javac使用的,确保数据的安全性和免去强制类型转换的麻烦。但是编译一旦完成,所有和泛型有关的类型全部被擦除。类型擦除机制存在的原因正是因为如果在运行时存在泛型,那么将要修改JVM指令集,这是非常致命的。
原始类型会生成字节码文件对象,而泛型类型相关的类型并不会生成与其相对应的字节码文件(因为泛型类型将会被擦除),因此,无法将泛型相关的新类型与class相统一。因此,为了程序的扩展性以及为了开发需要去反射操作这些类型,就引入了Type这个类型,并且新增了ParameterizedType, TypeVariable, GenericArrayType, WildcardType四个表示泛型相关的类型,再加上Class,这样就可以用Type类型的参数来接受以上五种子类的实参或者返回值类型就是Type类型的参数。统一了与泛型有关的类型和原始类型Class。而且这样一来,我们也可以通过反射获取泛型类型参数。
tips:
ParameterizedType:参数化类型,比如List<>。
GenericArrayType:泛型数组类型,比如比如List<>[],T[]这种。
TypeVariable:泛型变量,泛型信息在编译时会被转换为一个特定的类型, 而TypeVariable就是用来反映在编译前该泛型的信息。即我们常用的T,K这种泛型变量。
WildcardType:通配符类型,比如?、? extends Number、? super Integer。
三、反射获取注解,泛型信息
通过反射获取类,方法,参数里面的注解和泛型信息,示例如下。
@MyAnnotation(name = “zhangsan”)
public class User {
private String name;
public void sayHi() {
System.out.println(“hi:i am ” + name);
}
public void sayHi(String age,T t) {
System.out.println(“i am “+ name + “,and i am ” + age + “year old,and t is”+ t);
}
public static void main(String[] args) throws Exception {
Class clazz = User.class;
/**
* 获取类模板信息
*/
// 获取自有属性
Field[] fields = clazz.getDeclaredFields();
// 获取自有方法
Method[] methods = clazz.getDeclaredMethods();
// 获取构造器
Constructor>[] constructors = clazz.getDeclaredConstructors();
/**
* 执行方法,修改属性
*/
// 新建对象
Constructor constructor = clazz.getDeclaredConstructor();
User xiaoming = constructor.newInstance();
// 修改属性
Field field = clazz.getDeclaredField(“name”);// public的属性
field.setAccessible(true);
field.set(xiaoming, “xiaoming”);
field.setAccessible(false);
// 调用方法
Method method = clazz.getDeclaredMethod(“sayHi”, null);
method.invoke(xiaoming, new Class>[] {});
/**
* 获取注解
*/
//获取修饰类的注解
Annotation[] annotations = clazz.getAnnotations();
/**
* 获取泛型信息
*/
//获取方法参数的泛型信息
Method tMethod = clazz.getDeclaredMethod(“sayHi”,new Class[]{String.class,Object.class});
Type[] types = tMethod.getGenericParameterTypes();
for (Type type : types) {
System.out.println(type.getTypeName());
if (type instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) type;
System.out.println(“TypeVariable:”+typeVariable.getName());
}
}
}
}