一:简介
使用注释,可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充的信息。Annotation可以用来修饰类、属性、方法,而且Annotation不影响程序运行,无论是否使用Annotation,代码都可以正常执行。
二:各个Annotation使用
1、@Override
表示这个方法是覆写父类中的方法:
范例1:
package haizhu.com;
class Person{
public String getInfo(){
return "这是一个Person类";
}
}
class Student extends Person{
@Override
public String getInfo(){
return "这是一个Student类";
}
}
public class AnnotationDemo01 {
public static void main(String[] args) {
Person per = new Student();
System.out.println(per.getInfo());
}
}
如果声明了@Override,则使用IDE进行编辑的时候,如果继承的这个类中没有这个歌方法,就会进行出错提醒,如果使用记事本编辑,则会在编译的时候进行出错提醒。
表示这个方法不建议使用:
范例2:
package haizhu.com;
class Person{
@Deprecated
public String getInfo(){
return "这是一个Person类";
}
}
public class AnnotationDemo02 {
public static void main(String[] args) {
Person per = new Person();
System.out.println(per.getInfo());
}
}
在使用Person的实例调用getInfo()方法的时候,如果使用IDE,则调用的时候就会出现一个中间的横线提醒这个方法不建议使用,如果使用记事本,会在编译的时候使用。除了在方法中可以声明为@Deprecated,在类中也可以声明:
范例3:
package haizhu.com;
@Deprecated
class Person{
public String getInfo(){
return "这是一个Person类";
}
}
public class AnnotationDemo03 {
public static void main(String[] args) {
Person per = new Person();
System.out.println(per.getInfo());
}
}
同样,在IDE和编译的时候都会出现警告信息,因为Person类不建议使用。
3、@SuppressWarnings
用来压制警告:
范例4:
package haizhu.com;
class Demo<T>{
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}
public class AnnotationDemo04 {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
Demo d = new Demo();
d.setVar("海竹");
System.out.println("内容:"+d.getVar());
}
}
上面是用来压制一个泛型的警告信息。可以同时压制多条警告信息,如下所示:
范例5:
package haizhu.com;
@Deprecated
class Demo<T>{
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}
public class AnnotationDemo05 {
@SuppressWarnings({"unchecked","deprecation"})
public static void main(String[] args) {
Demo d = new Demo();
d.setVar("海竹");
System.out.println("内容:"+d.getVar());
}
}
另外一种写法:
范例6:
package haizhu.com;
@Deprecated
class Demo<T>{
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}
public class AnnotationDemo06 {
@SuppressWarnings(value = {"unchecked","deprecation"}) // 将这个内容赋给 value
public static void main(String[] args) {
Demo d = new Demo();
d.setVar("海竹");
System.out.println("内容:"+d.getVar());
}
}
三:自定义Annotation
1、定义简单的Annotation
范例7:
package haizhu.com;
public @interface MyAnnotation { // @interface 就表示这个 annotation 继承了 java.lang.annotation.Annotation 接口
public String value(); // 接收设置的内容
}
@MyAnnotation(value = "海竹") // 使用自定义的 Annotation
class Demo{
}
2、向Annotation传递多个值:传递多个属性和一个属性接收多个值
也可以在Annotation中设置多个属性:范例8:
package haizhu.com;
public @interface MyAnnotation {
public String key();
public String value(); // 接收设置的内容
}
@MyAnnotation(key = "haizhu",value = "海竹") // 多个属性
class Demo{
}
一个属性接收多个值:
范例9:
package haizhu.com;
public @interface MyAnnotation {
public String[] value(); // 用数组接收内容
}
@MyAnnotation(value = {"海竹","向北西行"}) // 传递一个数组
class Demo{
}
3、默认值
如果在一个定义好的Annotation中已经定义好了若干个属性,但是在使用Annotation时没有指定具体的内容,则在编译的时候也会出现错误,所以,在定义Annotation的时候,最好定义好默认值:
范例10:
package haizhu.com;
public @interface MyAnnotation {
public String value() default "海竹"; // 设置默认值
}
@MyAnnotation // 可以不用传递
class Demo{
}
4、使用枚举限制设置的内容:
范例11:
package haizhu.com;
public enum MyEnumName {
海竹,向北西行,程序员;
}
package haizhu.com;
public @interface MyAnnotation {
public MyEnumName value() default MyEnumName.海竹; // 使用枚举数据
}
@MyAnnotation(value = MyEnumName.向北西行)
class Demo{
}
5、@Retention 、RetentionPolicy 、@Documented 、@Inherited 、@Target
范例12:
package haizhu.com;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Documented
@Inherited
@Retention(value=RetentionPolicy.RUNTIME)
@Target(value=ElementType.TYPE)
public @interface Retention{
RetentionPolicy value();
}
@Retention:表示注释作用的范围,变量RetentionPolicy 有三个可选项:SOURCE、CLASS、RUNTIME
@Documented:
@Target:表示注释作用的类型,是作用在普通方法、构造方法还是作用在类上,变量ElementType
@Inherited:用来标注一个父类的注释是否可以被子类继承,如果需要被继承,加上@Inherited 即可
四:Annotation 结合反射的应用
1、取得注释
通过反射,取得一个方法中所有的注释:
范例13:
package haizhu.com;
public class ManyAnnotation{
@SuppressWarnings(value = { "unchecked" })
@Deprecated
@Override
public String toString(){ //在这个方法上,有三个注释
return "我有很多注释。。。。";
}
}
package haizhu.com;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class GetAnnotationByReflect {
public static void main(String[] args) throws Exception{
Class<?> c = Class.forName("haizhu.com.ManyAnnotation"); //取得class类实例
Method m = c.getMethod("toString"); //取得"toString"方法
Annotation an[] = m.getAnnotations(); //取得这个方法的所有注释
for(Annotation a : an){
System.out.println(a); //遍历,打印
}
}
}
结果:
@java.lang.Deprecated()
为什么有三个注释,结果只取到了一个呢?因为只有一个注释默认的是“RUNTIME”类型,能够取得到,另外两个取不到。
2、取得注释的内容
范例14:
package haizhu.com;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(value=RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public String key() default "haizhu";
public String value() default "海竹";
}
package haizhu.com;
public class ManyAnnotation{
@SuppressWarnings(value = { "unchecked" })
@Deprecated
@Override
@MyAnnotation(key="hello",value="world")
public String toString(){
return "我有很多注释。。。。";
}
}
package haizhu.com;
import java.lang.reflect.Method;
public class GetAnnotationContentByReflect {
public static void main(String[] args) throws Exception{
Class<?> c = Class.forName("haizhu.com.ManyAnnotation");
Method m = c.getMethod("toString");
if(m.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation ma = m.getAnnotation(MyAnnotation.class);
String key = ma.key();
String value = ma.value();
System.out.println("key值:"+key+"\tvalue值:"+value);
}
}
}
结果:
key值:hello value值:world
使用isAnnotationPresent 判断一个类是否是注释类,然后取得这个注释的key值和value值。