@liayun
2016-06-09T23:58:58.000000Z
字数 7374
阅读 1357
java基础加强
@SuppressWarnings
首先编写一个AnnotationTest类,先通过@SuppressWarnings
的应用让大家认识和了解一下注解,通过System.runFinalizersOnExit(true);
的编译警告引出@SuppressWarnings("deprecation")
。
public class AnnotationTest {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
}
}
@Deprecated
接着直接在刚才的类中增加一个方法,并加上@Deprecated
标注,在另外一个类中调用这个方法。
public class AnnotationTest {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
}
@Deprecated
public static void sayHello() {
System.out.println("hi,李阿昀");
}
}
public boolean equals(Reflect other)
方法与HashSet结合讲解。总结:注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
注解就相当于一个你的源程序中要调用的一个类,要在源程序中应用某个注解,得先准备好了这个注解类,就像你要调用某个类,得先要开发好这个类。
定义一个最简单的注解:
public @interface ItcastAnnotation {
}
把它加在某个类上:
@ItcastAnnotation
public class AnnotationTest {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
}
@Deprecated
public static void sayHello() {
System.out.println("hi,李阿昀");
}
}
用反射进行测试AnnotationTest的定义上是否有@ItcastAnnotation:
@ItcastAnnotation
public class AnnotationTest {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)) { // 类上是否有注解,默认情况下返回false
ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation);
}
}
@Deprecated
public static void sayHello() {
System.out.println("hi,李阿昀");
}
}
发现控制台无任何反应,根据反射测试的问题,引出@Retention
元注解的讲解,其有三种取值:RetetionPolicy.SOURCE
、RetetionPolicy.CLASS
、RetetionPolicy.RUNTIME
,分别对应:java源文件→class文件→内存中的字节码。
对@Retention元注解更加细致的解释:
所以,一个注解的生命周期有3个阶段。
我们定义的简单注解修改为如下:
@Retention(RetentionPolicy.RUNTIME)
public @interface ItcastAnnotation {
}
就能正确打印了。
思考:@Override、@SuppressWarnings和@Deprecated这三个注解的属性值分别是什么?
答:
@Override→RetetionPolicy.SOURCE
@SuppressWarnings→RetetionPolicy.SOURCE
@Deprecated→RetetionPolicy.RUNTIME
@Target元注解
Target的默认值为任何元素,设置Target等于ElementType.METHOD
,原来加在类上的注解就报错了,改为用数组方式设置{ElementType.METHOD,ElementType.TYPE}
就可以了,表示此注解既可以在方法上使用,也可在类上使用。
注意:元注解以及其枚举属性值不用记,只要会看JDK提供那几个基本注解的API帮助文档的定义或其源代码,按图索骥即可查到,或者直接看java.lang.annotation包下面的类。
@ItcastAnnotation(color="red")
定义基本类型的属性和应用属性
在注解类中增加String color()
:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
String color();
}
用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法:
@ItcastAnnotation(color="red")
public class AnnotationTest {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)) { // 类上是否有注解,默认情况下返回false
ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.color()); // red
}
}
@Deprecated
public static void sayHello() {
System.out.println("hi,李阿昀");
}
}
可以认为上面这个@ItcastAnnotation(color="red")是ItcastAnnotation类的一个实例对象。
为属性指定缺省值:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
String color() default "blue";
}
value属性:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
String color() default "blue";
String value();
}
用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法:
@ItcastAnnotation(color="red", value="abc")
public class AnnotationTest {
@SuppressWarnings("deprecation")
@ItcastAnnotation("xyz")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)) { // 类上是否有注解,默认情况下返回false
ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.value()); // abc
}
}
@Deprecated
public static void sayHello() {
System.out.println("hi,李阿昀");
}
}
注意:如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你只有一个value属性),那么可以省略value=
部分,例如:@ItcastAnnotation("lhm")
。
数组类型的属性
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
String color() default "blue";
String value();
int[] arrayAttr() default {3,4,4};
}
用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法:
@ItcastAnnotation(color="red", value="abc", arrayAttr=1)
public class AnnotationTest {
@SuppressWarnings("deprecation")
@ItcastAnnotation("xyz")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)) { // 类上是否有注解,默认情况下返回false
ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.arrayAttr().length); // 1
}
}
@Deprecated
public static void sayHello() {
System.out.println("hi,李阿昀");
}
}
注意:如果数组属性中只有一个元素,这时候属性值部分可以省略大括号。
枚举类型的属性
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
String color() default "blue";
String value();
int[] arrayAttr() default {3,4,4};
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;
}
用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法:
@ItcastAnnotation(color="red", value="abc", arrayAttr=1)
public class AnnotationTest {
@SuppressWarnings("deprecation")
@ItcastAnnotation("xyz")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)) { // 类上是否有注解,默认情况下返回false
ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.lamp().nextLamp().name()); // GREEN
}
}
@Deprecated
public static void sayHello() {
System.out.println("hi,李阿昀");
}
}
注解类型的属性:
我们再定义一个注解MetaAnnotation
:
public @interface MetaAnnotation {
String value();
}
接着再定义一个注解类型的属性:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
String color() default "blue";
String value();
int[] arrayAttr() default {3,4,4};
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;
MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");
}
枚举和注解都是特殊的类,不能用new创建它们的实例对象,创建枚举的实例对象就是在其中增加元素。在程序中如何创建出一个注解的实例对象啊?直接用@放上一个标记即可,例如:@MetaAnnotation("lhm")
。
用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法:
@ItcastAnnotation(annotationAttr=@MetaAnnotation("flx"), color="red", value="abc", arrayAttr=1)
public class AnnotationTest {
@SuppressWarnings("deprecation")
@ItcastAnnotation("xyz")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)) { // 类上是否有注解,默认情况下返回false
ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.annotationAttr().value()); // flx
}
}
@Deprecated
public static void sayHello() {
System.out.println("hi,李阿昀");
}
}
可以认为@ItcastAnnotation是ItcastAnnotation类的一个实例对象,同样的道理,可以认为@MetaAnnotation是MetaAnnotation类的一个实例对象。
注解的详细语法可以通过看java语言规范了解,即看java的language specification,可知道注解的属性类型包括:基本数据类型,String,Class,枚举,其他注解,以及这些类型的数组。