反射中的5大类:
Class,Constructor,Method,Field,Annotation.
Class:用来描述一个类
|_______Constructor:用来描述一个类的构造函数
|_______Method:用来描述一个类的方法
|_______Field:用来描述一个类的成员变量
|_______Annotation:用来描述一个类用到的注解
最常见的三个注解:
@Override:准确覆写,用于检查需要覆写的方法是否正确覆写
@Deprecated:过期声明,声明方法变量或者类是一个不应该被使用的,一旦声明一个类或者方法为过期的,那么就应该写另一个类或者方法来替代它。
@SuppressWarning:压制警告,用于屏蔽所用作用域下指定类型的警告。@SuppressWarnings("unused")用于屏蔽未使用的引用变量。
通过反射取得类用到的注解:
@SuppressWarnings("serial") @Deprecated public class Test { public static void main(String[] args) { Class<?> cls = Test.class; Annotation[] ans = cls.getAnnotations(); for(Annotation annotation : ans) { System.out.println(annotation); } } }
运行结果:
此处SuppressWarnings注解没有出现的原因可以查看SuppressWarnings的实现:
@Retention可以设置注解的级别
他的参数RetentionPolicy是一个枚举类,规定这个注解的保留的时间。
有以下三个选项:
SOURCE:表示只出现在源码中。
CLASS:表示出现在源码和.class文件中。
RUNTIME:表示出现在源码中,.class文件中,运行时。
由于SuppressWarnings只保留在SOURCE中,所以在运行时查看不到这个注解。
@Target用于规定作用的对象:
他的参数ElementType是一个枚举类,有以下几个对象
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, // 类,接口,注解 /** Field declaration (includes enum constants) */ FIELD, //属性域 /** Method declaration */ METHOD, // 方法 /** Formal parameter declaration */ PARAMETER, // 参数 /** Constructor declaration */ CONSTRUCTOR, // 构造方法 /** Local variable declaration */ LOCAL_VARIABLE, // 局部变量 /** Annotation type declaration */ ANNOTATION_TYPE, // 注解类型 /** Package declaration */ PACKAGE, // 包类型 /** * Type parameter declaration * * @since 1.8 */ TYPE_PARAMETER, // 参数类型 /** * Use of a type * * @since 1.8 */ TYPE_USE }
取得用在方法上的注解:
public class Test { @Deprecated @Override public String toString() { return "重写toString"; } public static void main(String[] args) throws NoSuchMethodException, SecurityException { Class<?> cls = Test.class; Method method = cls.getDeclaredMethod("toString");// 取得toString方法 Annotation[] ans = method.getAnnotations(); // 取得方法上的注解 for(Annotation annotation : ans) { System.out.println(annotation); } } }
运行结果:
可见@Override也是只保留在源码中的。
自定义注解:
自定义注解的使用:
使用@interface来定义一个注解
使用@Retention(RetentionPolicy.RUNTIME)来声明他的保留到运行时
使用@Target(ElementType.TYPE)让这个注解只能用于类,接口和注解上
代码如下:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation{ // 带参的注解 String name(); int age(); } @MyAnnotation(name="Tom", age = 20) public class Test { public static void main(String[] args){ showAnnotation(); } public static void showAnnotation() { MyAnnotation annotation = Test.class.getAnnotation(MyAnnotation.class); // 取得参数 System.out.println(annotation.age()); System.out.println(annotation.name()); } }
运行结果: