Java注解与注释

JDK内置注解

@Override

@Override的作用是标记重写父类的方法,@Override只能用于标记方法。编译器编译时会校验使用@Override标记的方法是否与父类对应方法形式一致。例:

Man.java

public class Man{
    private String name;
    private float height;
    private int weight;
    public void setName(String name){};
    public void setHeight(float height){};
    public void setWeight(int weight){};
}

Woman.java

public class Woman extends Man{
    @Override
    public void setHeight(int height){
        //编译时会报错,因为形参与父类不同
    }
}

@Deprecated

@Deprecated用于提示所修饰的元素(类、方法、变量等)已过时,继续使用可能会发生危险或者存在更好的选择。JDK更新过程中不会删除过时的API,而是为这些API加上@Deprecated标签,使得JDK不建议用户继续使用该API的同时,也保证使用了过时API的旧项目能正常运行。

@SuppressWarnings

@SupressWarnings的作用是抑制编译器警告。可以用于修饰所有成员。例如一个成员定义了却未使用(unused),就可以使用@SupressWarnings("unused")来抑制成员未使用(unused)的警告。再例如使用原类型时抑制警告:

@SupressWarnings({"unused","rawtypes"})
ArrayList list = new ArrayList();   //使用了ArrayList不带类型参数的原类型

元注解

概述

 元注解是用来修饰注解定义的注解。

@Retention

@Retention限定了被修饰注解的生命周期。它的取值有:

//注解在源文件(java文件)中有效(源文件保留),编译时丢弃
@Retention(RetentionPolicy.SOURCE)        
//默认值。注解在class文件中有效(class保留),但不会加载到JVM
@Retention(RetentionPolicy.CLASS)  
//注解在运行时有效(运行时保留),JVM会保留注释,所以程序运行时可以通过反射机制获取到注解信息
@Retention(RetentionPolicy.RUNTIME)       

例:

@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation{
    String[] value();
}

@Target

@Target指定被修饰注解可以用来修饰程序中的哪些元素。取值有:

TYPE:被修饰注解可以修饰class/interface/@interface/enum
FIELD:被修饰注解可以修饰field
METHOD:被修饰注解可以修饰method
PARAMETER:被修饰注解可以修饰parameter
CONSTRUCTOR:被修饰注解可以修饰constructor
LOCAL_VARIABLE:被修饰注解可以修饰local variable(局部变量)
ANNOTATION_TYPE:被修饰注解可以修饰Annotation type
PACKAGE:被修饰注解可以修饰package
TYPE_PARAMETER:被修饰注解可以修饰class parameter(泛型类型参数)
TYPE_USE:被修饰注解可以修饰任何使用的元素。

例:

@Target({TYPE,METHOD,CONSTRUCTOR})   //该注解可以用于修饰 类、方法、构造器
public @interface MyAnnotation{
    String[] value();
}

**注意:**若未指明@Target元注解,则该注解默认可以修饰程序中的所有元素。

@Documented

 被@Documented修饰的注解修饰的成员在API文档中也会显示出相应的注解,而默认API文档中是不显示注解的。

@Inherited

@Inherited修饰的注解将具有继承性,即如果一个类被@Inherited修饰的注解修饰,这个类的子类将自动具有该注解。

自定义注解

使用@interface关键字定义注解:

public @interface MyAnnotation{
    /*
      成员变量以“无参方法”的形式声明,“无参方法”的返回值即成员变量的值
    */
    int value();
    String message();
}

使用方法:

//修饰类
@MyAnnotation(value = 1,message = "type")
public class Person{
    //修饰属性
    @MyAnnotation(value = 2,message = "field")
    private String name;
    //修饰构造器
    @MyAnnotation(value = 3,message = "constructor")
    public Person(String name){
        this.name = name;
    }
    //修饰方法
    @MyAnnotation(value = 4,message = "method")
    public String getName(){
        return name;
    }
    //修饰参数
    public void setName(@MyAnnotation(value = 5,message = "param") String name){
        this.name = name;
    }    
}

使用default关键字指定成员变量默认值:

public @interface MyAnnotation{
    int value() default 0;
    String message() default "";
}

此时再使用时可以不用带参数从而直接使用默认值:

@MyAnnotation
public class Person{
    //也可以仅指定部分参数
    @MyAnnotation(message = "default test")
    public Person(String name){
        this.name = name;
    }
}

如果注解中没有成员,这个注解就是一个标识。例如@Override

通过反射机制获取RUNTIME注解

定义注解

MyAnnotation.java

@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation{
    int value() default 0;
    String message() default "";
}

Person

Person.java

@MyAnnotation(message = "Person")
public class Person{
    @MyAnnotation(value = 1,message = "name")
    private String name;
    @MyAnnotation(value = 2,message = "height")
    private float height;
    @MyAnnotation(value = 3,message = "weight")
    private int weight;
    
    @MyAnnotation(value = 4,message = "Person()")
    public Person(String name,float height,int weight){
        this.name = name;
        this.height = height;
        this.weight = weight;
    }
    
    @MyAnnotation(value = 5,message = "setName()")
    public void setName(@MyAnnotation(value = 6,message = "paramName")String name){
        this.name = name;      
    }
    @MyAnnotation(value = 7,message = "getName()")
    public String getName(){
        return name;
    }
    
    @MyAnnotation(value = 8,message = "setHeight()")
    public void setHeight(@MyAnnotation(value = 9,message = "paramHeight")float height){
        this.height = height;
    }
    @MyAnnotation(value = 10,message = "getHeight()")
    public float getHeight(){
        return height;
    }
    
    @MyAnnotation(value = 11,message = "setWeight()")
    public void setWeight(@MyAnnotation(value = 12,message = "paramWeight")int weight){
        this.weight = weight;
    }
    @MyAnnotation(value = 13,message = "getWeight()")
    public int getWeight(){
        return weight;
    }
    
}

获取注解的方法

//java.lang.annotation.Annotation
public Annotation[] getAnnotations()
//java.lang.annotation.Annotation
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
//java.lang.annotation.Annotation
public Annotation[] getDeclaredAnnotations()
//java.lang.annotation.Annotation
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass)

获取类的注解

Class<Person> clas = Person.class;
//获取注解
MyAnnotation annotation = clas.getDeclaredAnnotation(MyAnnotation.class);
//获取注解成员"value()"值
int value = annotation.value();
//获取注解成员"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

获取属性的注解

Class<Person> clas = Person.class;
//获取属性
Field name = clas.getDeclaredField("name");
//使可访问
name.setAccessible(true);
//获取注解
MyAnnotation annotation = name.getDeclaredAnnotation(MyAnnotation.class);
//获取注解成员"value()"值
int value = annotation.value();
//获取注解成员"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

获取构造器的注解

Class<Person> clas = Person.class;
//获取构造器
Constructor<Person> cons =
    clas.getDeclaredConstructor(String.class,float.class,int.class);
//使可访问
cons.setAccessible(true);
//获取注解
MyAnnotation annotation = cons.getDeclaredAnnotation(MyAnnotation.class);
//获取注解成员"value()"值
int value = annotation.value();
//获取注解成员"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

获取方法的注解

Class<Person> clas = Person.class;
//获取方法
Method method = clas.getDeclaredMethod("setName",String.class);
//使可访问
method.setAccessible(true);
//获取注解
MyAnnotation annotation = method.getDeclaredAnnotation(MyAnnotation.class);
//获取注解成员"value()"值
int value = annotation.value();
//获取注解成员"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

获取参数注解

Class<Person> clas = Person.class;
//获取方法(或构造器)
Method method = clas.getDeclaredMethod("setHeight",float.class);
//使可访问
method.setAccessible(true);
//获取参数
Parameter param = (method.getParameters())[0];
//获取注解
MyAnnotation annotation = param.getDeclaredAnnotation(MyAnnotation.class);
//获取注解成员"value()"值
int value = annotation.value();
//获取注解成员"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

注意:

只有包含@Retention(RetentionPolicy.RUNTIME)修饰的注解才能使用反射机制获取。

说明注释

概述

 Java中有三种注释形式:1.以//开头的单行注释;2.以/*开头*/结尾的多行注释;3.以/**开头*/结尾的说明注释

说明注释允许在程序中嵌入对程序的说明信息,生成API文档作为API调用时的指导。

说明注释中可以包含以@开头标签,用于对特定信息的描述,例如作者、版本、方法参数和方法返回值等。

常用的说明注释标签

1.@author:用于注释。说明类的作者。例:

/**
*@author Lishaoyin
*/
public class Person{}

2.@version:用于注释。说明类的版本。例:

/**
*@version 1.0
*/
public class Person{}

3.@since:用于类和任意类成员注释。说明API是在JDK的哪个版本添加的。例:

/**
*@since 1.8
*/
public void setName(String name){}   //API在JDK1.8添加

4.@deprecated:用于类和任意类成员注释。说明该类成员已过期,不建议使用。例:

/**
*@deprecated this field is deprecated,you can use better choice
*/
private String name;

5.@throws:用于方法和构造器注释。说明方法或构造器可能会抛出的异常。例:

/**
*@throws java.io.IOException this method maybe throws IOException
*/
public void setHeight(float height) throws IOException {}

6.@exception:作用与@throws相同。

7.@see:用于类和任意类成员注释。在生成的文档中指定一个API文档超链接,用户点击后可跳转至指定内容的API文档。例:

/**
*@see java.lang.annotation.Annotation
*/
public class Person{}

8.@param:用于方法和构造器注释。说明方法或构造器的参数。例:

/**
*@param name String,person's name
*@param height float,person's height
*@param weight int,person's weight
*/
public Person(String name,float height,int weight){}

9.@return:用于方法注释。说明方法的返回值。

/**
*@return String,person's name
*/
public String getName(){}

TODO

TODO是一种用法简单的计划标记工具,其作用是将计划指示信息嵌入到注释中(可嵌入到三种注释中的任意一种)。编译后可使用快速定位跳转到指定计划位置,继续完成计划中未完成的工作。例:

public class Person{
    
    public String getName(){
       //TODO function to get person's name 
    }
    
    public void setHeight(float height){
       /*TODO function to set person's height*/
    }
    
    /**
    *@param weight int,set person's weight
    *TODO function to set person's weight
    */
    public String setWeight(int weight){}
    
}

示例

Person.java

/**
*@author Lishaoyin
*version 1.0
*@since 1.8
*/
public class Person{
    
    private String name;
    private float height;
    private int weight;
    
    /**
    *@param name String,init person's name
    *@param height float,init person's height
    *@param weight int,init person's weight
    */
    public Person(String name,float height,int weight){
        this.name = name;
        this.height = height;
        this.weight = weight;
    }
    
    /**
    *@param name String,set person's name
    */
    public void setName(String name){
        this.name = name;
    } 
    /**
    *@return String,get person's name
    */
    public String getName(){
        return name;
    }
    
    /**
    *@param height float,set person's height
    */
    public void setHeight(float height){
        this.height = height;
    } 
    /**
    *@return float,get person's height
    */
    public float getHeight(){
        return height;
    }
    
    /**
    *@throws java.io.IOException this method maybe throws IOException
    *@see java.io.IOException
    *@param weight int,set person's weight
    */
    public void setWeight(int weight) throws java.io.IOException {
        this.weight = weight;
    }
    /**
    *@return int,get person's weight
    */
    public int getWeight(){
        return weight;
    }
    
    //TODO function to set person's sex
    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章