目录
什么是注解:
注释:给人解释的
注解:给 程序/编译器… 解释的
内置注解:
@Override:定义在java.langOverride中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。
@Deprecated:定义在java.langDeprecated中,此注释可以用于修辞方法、属性、类,表示此元素已经废弃,不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择。
@SuppressWarnings:定义在java.langSuppressWarnings中,用来抑制编译时的警告信息。SuppressWarnings与前两个注释有所不同你需要添加一个参数才能正确使用,这些参数都是已经定义好了的
- all(抑制所有警告)
- boxing(抑制装箱、拆箱操作时候的警告)
- cast(抑制映射相关的警告)
- dep-ann(抑制启用注释的警告)
- deprecation(抑制过期方法警告)
- fallthrough(抑制确在switch中缺失breaks的警告)
- finally(抑制finally模块没有返回的警告)
- hiding(抑制相对于隐藏变量的局部变量的警告)
- incomplete-switch (忽略没有完整的switch语句)
- nls (忽略非nls格式的字符)
- null (忽略对null的操作)
- rawtypes (使用generics时忽略没有指定相应的类型)
- restriction(抑制与不鼓励或禁止引用的使用相关的警告)
- serial(忽略在serializable类中没有声明serialVersionUID变量)
- static-access(抑制不正确的静态访问方式警告)
- synthetic-access(抑制子类没有按最优方法访问内部类的警告)
- unchecked(抑制没有进行类型检查操作的警告)
- unqualified-field-access(抑制没有权限访问的域的警告)
- unused(抑制没被使用过的代码的警告)
定义注解的属性:
1、返回值类型:基本数据类型、String、枚举、注解、以上类型的数组。(不能定义为void、或其他引用数据类型)
2、注解内的方法必须为抽象方法。(其实不能被重写或调用,跟普通变量一样用于接收赋值,所以称为属性)
3、定义了属性,在使用该注解时就要给属性赋值。可以使用default来给属性赋默认值。
public @interface MyAnno{ // 使用@interface来定义注解
int age();
String name() default "张三" ;
}
@MyAnno(age = 19)
public class test{
}
4、如果只有一个属性需要赋值,并且属性的名称是value,则可以直接在括号内写上所要赋的值即可。如:@MyAnno=(19) 。
5、如果给数组属性赋值:str = {"abc"、"xyz"} 时,只有一个元素,那么大括号可以省略:str = "xyz" 。
元注解:
元注解的作用就是负责注解其他的注解。Java定义了四个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明。
这些类型和他们所支持的类在java.lang.annotation包中可以找到,他们分别是@Target、@Retention、@Documented、@Inherited。
@Target | 用于描述注解的使用范围/使用场所 |
@Retention | 表示需要在什么级别保存该注解信息,用于描述注解的生命周期 |
@Documented | 用于说明该注解能被抽取到api文档中 |
@Inherited | 用于说明子类可以继承父类中的该注解 |
@Target:
用于描述注解的使用范围/使用场所。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
它的取值范围定义在ElementType 枚举类中。
public enum ElementType {
TYPE, // 类、接口、枚举类
FIELD, // 成员变量(包括:枚举常量)
METHOD, // 方法
PARAMETER, // 方法参数
CONSTRUCTOR, // 构造方法
LOCAL_VARIABLE, // 局部变量
ANNOTATION_TYPE, // 注解类
PACKAGE, // 可用于修饰:包
TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
}
不写@Target默认修饰什么都可以(类、静态方法、实例方法、构造方法、属性、形参、注解、枚举)。
@Retention:
表示需要在什么级别保存该注解信息,用于描述注解的生命周期。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
它的取值范围定义在RetentionPolicy枚举类中。
public enum RetentionPolicy {
SOURCE, // 源代码时期,表示该注解只被保留在java源文件中。
CLASS, // 类时期,表示该注解被保存在class文件中。
RUNTIME // 运行时期,表示该注解被保存在class文件中,并且可以被反射机制所读取。
}
(SOURCE<CLASS<RUNTIME)
@Documented:
用于说明该注解能被抽取到api文档中。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
被@Documented注解的注解都会被javadoc命令提取到帮助文档中。
@Inherited:
用于说明子类可以继承父类中的该注解。
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有被@Inherited修饰。
注解在开发中的作用:
现有一个需求:
假设有这样一个注解,叫做:@MustHasIdPropertyAnnotation。这个注解只能出现在类上面,当这个类上有这个注解的时候,要求这个类中必须有一个int类型的id属性。如果没有这个属性就报异常。如果有这个属性则正常执行!
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 表示这个注解只能出现在类上面
@Target(ElementType.TYPE)
// 该注解可以被反射机制读取到
@Retention(RetentionPolicy.RUNTIME)
public @interface MustHasIdPropertyAnnotation {
}
// 这个注解@Id用来标注类,被标注的类中必须有一个int类型的id属性,没有就报异常。
/*
自定义异常
*/
public class HasNotIdPropertyException extends RuntimeException {
public HasNotIdPropertyException(){
}
public HasNotIdPropertyException(String s){
super(s);
}
}
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception{
// 获取类
Class userClass = Class.forName("com.bjpowernode.java.annotation7.User");
// 判断类上是否存在Id注解
if(userClass.isAnnotationPresent(MustHasIdPropertyAnnotation.class)){
// 当一个类上面有@MustHasIdPropertyAnnotation注解的时候,要求类中必须存在int类型的id属性
// 如果没有int类型的id属性则报异常。
// 获取类的属性
Field[] fields = userClass.getDeclaredFields();
boolean isOk = false; // 给一个默认的标记
for(Field field : fields){
if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){
// 表示这个类是合法的类。有@Id注解,则这个类中必须有int类型的id
isOk = true; // 表示合法
break;
}
}
// 判断是否合法
if(!isOk){
throw new HasNotIdPropertyException("被@MustHasIdPropertyAnnotation注解标注的类中必须要有一个int类型的id属性!");
}
}
}
}
@MustHasIdPropertyAnnotation
public class User {
int id;
String name;
String password;
}
正常运行:
异常运行: