java注解
in Java with 0 comment

java注解

in Java with 0 comment

java注解

  1. 注解,或者叫注释,英文单词是:Annotation
  2. 注解是一种引用数据类型。编译之后也是生成xxx.class文件
  3. 怎么自定义一个注解呢?语法格式?
    [修饰符列表] @interface 注解类型名 {
    }
  4. 注解怎么用,用在什么地方?
    1. 注解使用时的语法格式
      @注解类型名
    2. 注解可以出现在类上、属性上、方法上、变量上等...
      注解还可以出现在注解类型上。

JDK内置注解

注解的注解叫做元注解

元注解

Override

@Override 只能出现在方法上.@Override这个注解是给编译器参考的,也运行阶段没有关系。凡是java中的方法带有这个注解的,编译器都会进行检查,如果这个方法不是重写父类的方法,编译器报错。但这不是必须的。

源码

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override { }

Deprecated

表示被标注的元素已过时,这个注解主要是向其他程序员传达一个信息,告知已过时,有更好的解决方案存在。

@Deprecated
public @interface MyAnnotation {}

已过时的方法或类在不同的编译器可能有不同的展示效果,例如vscode:
vscode

idea

idea

自动定义Annotation

语法

[修饰符列表] @interface 注解类型名 {...}

定义

public @interface MyAnnotation {}

我们通常在注解当中可以定义属性,以下这个是MyAnnotation的name属性。一个注解如果有定义了一个不能为空的属性,那么使用该注解的时候必须给属性赋值

String name();

给指定的属性名赋值

@MyAnnotation(name = "UpYou")
public static void sun(){
  return;
}

让它使用自己的默认值

在Annotation中这样定义一个属性,这个属性有个默认值18

int age() default 18;

在有默认值的情况下,我们可以设置它的属性值,也可以使用默认

@MyAnnotation(name = "UpYou")
public static void sun(){}

不使用默认值

@MyAnnotation(name = "UpYou", age = 18)
public static void sun(){}

如果一个注解的属性名字是value,并且只有一个属性的话,在使用的时候,该属性名可以省略。


注解当中的属性可以是哪一种类型?

以及以上每一种类型的数组形式

数组属性

定一个数组类型的属性

public @interface MyAnnotation {
    int[] age();
}

如果只有一个值的情况下,可以这样用name = value,如果你有多个值时需要使用大括号{}而不是中括号[]包裹,例如:

@MyAnnotation(age = 18)
public static void sun(){}

@MyAnnotation(age = {17, 18, 19, 20})
public static void doT(){}

反射注解

被反射的类

@MyAnnotation(age = {14, 15, 16, 17, 18})
public class AnnotationTest {
  public void doT() {}
}

获取一个类

Class clazz = Class.forName("annotation.AnnotationTest");

判断类上面是否有注解某个注解

boolean isMyAnnotationPresent = clazz.isAnnotationPresent(MyAnnotation.class);

-- true

获取到这个注解对象

if (isMyAnnotationPresent) {
  MyAnnotation clazzMyAnotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
}

指定获取这个注解的属性

int[] clazzMyAnotationAge = clazzMyAnotation.age();
for (int i = 0; i < clazzMyAnotationAge.length; i++) {
  System.out.println(clazzMyAnotationAge[i]);
}

-- 14
-- 15
-- 16
-- 17
-- 18

获取注解对象的属性值

获取doT方法上的注解信息

// 读取do方法是否带有MethodAnnotation
Method clazzMethods = clazz.getDeclaredMethod("doT");
boolean clazzMethodsIsAnnotationPresent = clazzMethods.isAnnotationPresent(MethodAnnotation.class);
if (clazzMethodsIsAnnotationPresent) {
  MethodAnnotation methodAnnotation = clazzMethods.getAnnotation(MethodAnnotation.class);
  System.out.println(methodAnnotation.name());
  System.out.println(methodAnnotation.pass());
}

-- admin
-- 123

注解在开发中有什么用

假设有这样一个注解,叫做:@Id

这个注解只能出现在类上面,当这个类上有这个注解的时候,要求这个类中必须有一个int类型的id属性。如果没有这个属性就报异常。如果有这个属性则正常执行。

@Id(fiel = "id", type = int.class)
public class User {}

Id注解的定义

这个注解@Id用来标注类,被标注的类中必须有一个对应类型的属性属性,没有就报异常。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
  // 必须出现的字段
  String fiel();
  // 字段类型
  Class type();
}

反射

拿到User类

Class userClass = Class.forName("User");

判断这个类是否存在这个注解

boolean userClassIsAnnotationPresent = userClass.isAnnotationPresent(Id.class);
// 存在这个注解时执行对应操作
if (userClassIsAnnotationPresent) {
  ...在这里执行操作...
}

获取到这个类上的@Id注解

Annotation idAnnotation = userClass.getAnnotation(Id.class)

拿到指定的属性跟属性类型

String idFieldName = idAnnotation.fiel();
Class idFieldType = idAnnotation.type();

判断这个属性是否存在

try {
  Field idField = userClass.getDeclaredField(idFieldName);
} catch (NoSuchFieldException | SecurityException e) {
  System.out.println("错误,不存在属性: " + idFieldName);
}

判断这个属性类型是否对应

if (idField.getType() != idFieldType) {
  System.out.println("期望的属性类型为" + idFieldType.getSimpleName() + "; 可得到的类型为" + idField.getType().getSimpleName());
}

测试

User.java文件内容如下时

@Id(fiel = "id", type = int.class)
public class User {}

-- 错误,不存在属性: id

@Id(fiel = "id", type = int.class)
public class User {
  public String id;
}

-- 期望的属性类型为int; 可得到的类型为String

@Id(fiel = "id", type = int.class)
public class User {
  public int id;
}

没有错误


注解在程序当中等同于一种标记,如果这个元素上有这个注解怎么办,没有这个注解怎么办。

注解+反射练习