JDK1.5之后的新特性
注解:说明程序的,给计算机看。
注释:用文字描述程序的,给程序员看的。
注解也叫元数据,是一种代码级别的说明,与类、接口、枚举在同一层次。
它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、解释。
(1)编写文档:通过代码里标识的注解生成文档。如:生成doc文档。
(2)代码分析:通过代码里标识的注解对代码进行分析。如:通过反射。
(3)编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查。如:@Overrider注解
Java支持三种注释:单行注释、多行注释、说明注释
//单行注释的内容
/*
多行注释的内容
*/
1234567
/**
* 计算两整数之和
* @param a
* @param b
* @return
*/
public int add(int a,int b){
return a+b;
}
123456789
说明注释允许在程序中嵌入关于程序的信息。可以使用javadoc工具软件生成信息,并输出到HTML文件中。
/**
* 注解javadoc的演示
*
* @author jack
* @version 3.0
* @since 1.8
*/
public class AnnotationDemo {
/**
* 计算两整数之和
* @param a
* @param b
* @return
*/
public int add(int a,int b){
return a+b;
}
/**
* 计算两数之差
* @param a
* @param b
* @return
*/
public int sub(int a,int b){
return a-b;
}
}
12345678910111213141516171819202122232425262728
将AnnotationDemo.java文件复制保存到新建的文件夹中,在文件夹中打开命令窗口(shift+鼠标右键,打开PowerShell窗口),输入javadoc -encoding utf-8 AnnotationDemo.java命令
如果不指定字符集格式,无法生成文档
输入正确的命令:
成功后,会在新建的文件夹下生成一些html、css文件
打开index.html
生成的html文档和JDK文档一样,这样我们知道了利用javadoc制作自己的API文档
自定义注解的依法格式:
【修饰符列表】 @interface 注解名称{…}
public @interface FirstAnnotation {
}
12
使用注解:@注解名称 如:@Override
@MyAnnotation
public class Person {
}
123
(1)注解的本质上是一个借口,该借口默认继承Annotation接口
(2)注解的属性就是接口中的抽象方法
(3)注解的属性只能是以下几种:
- 基本数据类型
String类型
枚举类型
注解类型
Class类型
以上类型的一维数组
public @interface MyAnnotation {
int age(); //int类型
String name(); //String类型
Role role(); //枚举类型
String[] address(); //String类型的数组
}
123456
编译(javac)MyAnnotation.java文件,产生MyAnnotation.class文件,再反编译(javap)字节码文件
public interface MyAnnotation extends Annotation{
}
12
可以看到,自定义的注解本质上是一个接口,并且继承java.lang.Annotation接口
(1)在注解中定义了属性,在使用时需要给属性赋值
@MyAnnotation(age=20,name = "张三",role = Role.STUDENT,address = {
"北京市","上海市"})
public class Person {
}
123
(2)数组赋值时,值用大括号{ }包裹,如果数组中只有一个值时,则大括号可以省略。
@MyAnnotation(age=20,name = "张三",role = Role.STUDENT,address = "北京市")
public class Person {
}
123
(3)如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时可以不进行属性赋值
public @interface MyAnnotation {
int age() default 23; //int类型
String name() default ""; //String类型
Role role(); //枚举类型
String[] address(); //String类型的数组
}
123456
@MyAnnotation(role = Role.STUDENT,address = "北京市")
public class Person {
}
123
(4)如果只有一个属性需要赋值,并且属性名称为value,则value可以省略,直接定义值即可
public @interface MyAnnotation {
int age() default 23;
String address() default "";
String value();
}
@MyAnnotation("张三")
public class Person {
}
12345678910
上面的例子中,age属性和address属性已经初始化默认值,只剩下value属性需要赋值,则不用再写成@MyAnnotation(value=“张三”),可以省略为@MyAnnotation(“张三”)。
用于标注在注解上的注解称为元注解
常见的有四个:
- @Target:用来描述“被标注的注解”可以出现在哪些位置上。
@Retention:用来描述“被标注的注解”被保留的阶段。
@Document:用来描述“被标注的注解”是否能被抽取到API文档。
@Inherited:用来描述“被标注的注解”是否被子类继承
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
123456
@Target只有一个属性value,value属性的类型为ElementType类型的数组,ElementType是一个枚举类
public enum ElementType {
TYPE, // 用在类、接口(包括注解类型)、枚举类型上
FIELD, // 属性类型(包括枚举常量上)
METHOD, // 方法类型上
PARAMETER, // 正式参数上
CONSTRUCTOR, // 构造器上
LOCAL_VARIABLE, // 局部变量上
ANNOTATION_TYPE, // 注解类型上
PACKAGE, // 包上
TYPE_PARAMETER, // 输入参数声明,从1.8版本才有
TYPE_USE // 使用一种类型,从1.8版本才有
}
123456789101112
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
123456
@Retention只有一个属性value,value属性的类型为RetentionPolicy,RetentionPolicy是一个枚举类,其源码:
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
12345
@Retention(RetetionPolicy.SOURCE):表示被该注解标注的注解只被保留在java源文件中。编译时直接丢弃这个注解。
@Retention(RetetionPolicy.CLASS):表示被该注解标注的注解会被保留在class文件中。运行Java程序时,JVM不会保留这个注解。
@Retention(RetetionPolicy.CLASS):表示被该注解标注的注解会被保留在class文件中。并且可以被反射机制读取到。
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
12345
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
12345
(1)@Override:检测被该注解标注的内容是否是继承自父类(或实现于父接口)的。
源码:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
1234
通过看源码发现:@Override注解只能用在方法上
(2)@Deprecated:被该注解标注的内容,表示已过时。
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={
CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
12345
在之前学习过的Date类中,大多数方法已过时。
(3)@SuppressWarnings :压制警告
源码:
@Target({
TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
12345
@SuppressWarnings(“all”)可以消除所有警告,一般传递参数all
需求:创建一个自定义注解,在Person类上及Person的方法上使用注解,在测试类中通过反射获取标注在Person类和方法上的注解信息。
注意:自定义注解必须用@Retention(RetentionPolicy.RUNTIME)标注,这样自定义注解才能被反射机制读取到。
@Retention(RetentionPolicy.RUNTIME)
public @interface PersonInfo {
int age();
String name();
}
12345
@PersonInfo(age=20,name="张三")
public class Person {
@PersonInfo(age=30,name="李四")
public void eat(){
System.out.println("run方法执行了.....");
}
}
12345678
测试类:
import java.lang.reflect.Method;
public class ReflectPersonInfo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//获取Person类对象
Class<?> aClass = Class.forName("cn.itcast.annotation.Person");
//获取标注在Person类上的@PersonInfo注解信息
if(aClass.isAnnotationPresent(PersonInfo.class)){
//判断Person类上是否有@PersonInfo注解标注
//获取注解对象
PersonInfo personInfo = aClass.getAnnotation(PersonInfo.class);
//打印标注在Person类上的@PersonInfo注解信息
System.out.println(personInfo.age());
System.out.println(personInfo.name());
}
System.out.println("----------------------------");
//获取标注在Person类的方法上的@Person注解信息
Method eat = aClass.getDeclaredMethod("eat"); //获取Person类的eat方法对象
if(eat.isAnnotationPresent(PersonInfo.class)){
//判断Person类的eat方法上是否有@PersonInfo注解标注
//获取标注在eat方法上的注解对象
PersonInfo personInfo = eat.getAnnotation(PersonInfo.class);
//打印标注在Person类中的eat()方法上的注解信息
System.out.println(personInfo.name());
System.out.println(personInfo.age());
}
}
}
12345678910111213141516171819202122232425262728293031
转自:有讲究的老四–>https://blog.csdn.net/Swingman123/article/details/113264093?utm_medium=distribute.pc_category.none-task-blog-hot-10.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-10.nonecase&request_id=