注解概述
注解(Annotation):也叫元数据,一种代码级别的说明,它是JDK1.5及以后版本引入的一个特性
它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明
JDK1.5之后的新特性
说明程序的
注解和注释:
注解:用来说明程序,给计算机看的
注释:用来对程序进行说明的文字,给程序员看的
我们先来看看java中常见的几个注解
@Override
@Deprecated
@SuppressWarnings
@FunctionalInterface
@Override:用于指定方法是重写父类的方法,只能修饰方法,不能修饰其他程序元素
单独来看,可能丝毫看不出程序中@Override有何作用,因为它的作用是告诉编译器检查这个方法,保证父类要包含一个被该方法重写的方法
@Deprecated:用于表示某个程序元素(类、方法等)已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告
java9为@Deprecated增加了两个属性
since:该String类型的属性指定该API从那个版本被标记为过时
forRemoval:该boolean类型的属性指定该API在将来是否会被删除
@SuppressWarnings:指示被该注解修饰的程序元素(以及该程序元素中的所有子元素)取消显示指示的编译器警告
使用注解来关闭编译器警告时,一定要在括号内使用name=value的形式为该注解的成员变量设置值
@SuppressWarnings(value = "all")
@FunctionalInterface:Java8新增的,只能用来修饰接口,表示该接口是一个函数式接口
函数式接口:接口中有且仅有一个抽象方法
Lambda表达式的使用前提:接口中有且仅有一个抽象方法
元注解
对注解进行注解的注解。也就是写在注解上面的注解
两个常用元注解:
@Retention
@Target
@Retention:只能用于修饰注解定义,用于指定被修饰的注解可以保留多长时间
只包含了一个RetentionPoclicy类型的value成员变量,所有使用的@Retention时必须要为该value成员变量指定
@Target:只能用于修饰注解定义,用于指定被修饰的注解能用于修饰那些程序单元,包含一个名为value的成员变量
自定义注解
定义格式:
元注解
public @interface 注解名称{
属性列表;
}
注解的本质:
public interface MyAnnotation extends Annotation { }
是一个接口,该接口默认继承Annotation接口
既然是接口,那么内部定义的内容,就是接口中可以定义的内容
注解的属性
属性:接口中的抽象方法
格式:返回值类型 属性名称()[default 默认值]
注解属性类型可以有以下列出的类型:
基本数据类型
String
枚举类型
注解类型
Class类型
以上类型的一维数组类型
package com.aynu5;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String name() default "fqy";
int age();
}
注解的使用和解析
使用注解:
如果注解有多个属性,则可以在注解括号中用 "," 号隔开分别给对于的属性赋值
如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值
如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
数据赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略
package com.aynu5;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
// String name() default "fqy";
//
//
// int age();
// String value();
String[] names();
}
package com.aynu5;
//@MyAnnotation(name = "风清扬", age = 36)
//@MyAnnotation(age = 36)
//@MyAnnotation(value = "好好学习,天天向上")
//@MyAnnotation("好好学习,天天向上")
//@MyAnnotation(names = {"林青霞", "风清扬", "柳岩"})
//@MyAnnotation(names = {"林青霞"})
@MyAnnotation(names = "林青霞")
public class MyAnnotationTest {
}
解析注解:
获取字节码文件对象,获取谁的呢?谁使用了注解,就获取谁的
Class<MyAnnotationTest> c=MyAnnotationTest.class
获取字节码对象上的注解信息
MyAnnotation annotation = c.getAnnotation(MyAnnotation.class);
解析注解
String name = annotation.name();
int age = annotation.age();
package com.aynu5;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String name() default "fqy";
int age();
}
package com.aynu5;
//@MyAnnotation(age = 36)
@MyAnnotation(name = "风清扬", age = 33)
public class MyAnnotationTest {
public static void main(String[] args) {
//通过反射来解析注解
//获取字节码文件对象,获取谁的呢?谁使用了注解,就获取谁的
Class<MyAnnotationTest> c = MyAnnotationTest.class;
//通过字节码文件对象获取注解信息
MyAnnotation myAnnotation = c.getAnnotation(MyAnnotation.class);
//通过注解的属性获取对应的值
String name = myAnnotation.name();
int age = myAnnotation.age();
System.out.println(name + "," + age);
}
}
风清扬,33