Java-注解基础
admin
2024-04-12 03:27:10
0

注解

文章目录

  • 注解
    • 1. 注解语法
      • 1.1 注解接口
      • 1.2 常用方法
      • 1.3 注解(打上注解)
      • 1.4 注解的声明
      • 1.5 注解类型的用法
    • 2. 标准注解
      • 2.1 一些常见的注解
    • 3. 自定义注解
    • 4. 使用反射操作注解

1. 注解语法

1.1 注解接口

modifiers @interface AnnotationName{elementDeclaration1;elementDeclaration2;...
}

每个元素声明都有如下形式:

type elementName();

或者:

type elementName() default value;

所有注解接口都隐式地扩展自 java.lang.annotation.Annotation接口。这是个常规接口,不是一个注解接口。

注解元素的类型为下列之一:

  • 基本类型(int, short, long, byte, char, double, float 或者 double)
  • String
  • Class (具有一个可选的类型参数,例如 Class
  • enum枚举类型
  • 注解类型
  • 上述所述类型组成的数组

合法例子:

public @interface Example{enum Status {A, B, C, D};boolean isOK() default false;String assignedTo() default "[none]";Class test() default Void.class;Status status() default Status.A;Reference ref() default @Reference();//这是一个注解类型String[] report();
}

1.2 常用方法

  • Class annotationType();
    

    返回Class对象,用于描述该注解对象的注解接口。注意:调用注解对象上的getClass()方法可以返回真正的类,而不是返回接口。

  • boolean equals(Object other);
    

    判断other是否实现了同样的注解接口,并且该对象与other的所有元素都彼此相等。

  • int hashCode()
    
  • String toString()
    

    返回一个包含注解接口名以及元素值的字符串表示。例如 @Example(assignedTo=[none],isOk=false)

1.3 注解(打上注解)

每个注解都具有下面这种格式:

@AnnotationName(elementName1 = value1, elementName2 = value2, ...)

元素的顺序无关紧要。如果某个元素没有指定,将会使用声明的默认值。

简化注解:

  • 标记注解:没有指定元素,不需要圆括号:

    @AnnotationName
    
  • 单值注解:只有唯一元素,且该元素具有特定的名字 value,则可以忽略元素名以及等号:

    @AnnotationName("someValue")
    
  • 所有注解都是由编译器计算而来的,因此所有元素值必须是编译器常量。

  • 一个项可以有多个注解

  • 注解可以重复声明

  • 注解元素不能设置为 null

  • 不允许循环依赖,例如:在注解A中有一个注解类型为B的注解元素,则B中不能再拥有一个类型为A的注解元素。

1.4 注解的声明

注解可以出现的声明处:

  • 类(包括enum)
  • 接口(包括注解接口)
  • 方法
  • 构造器
  • 实例域(包括enum常量)
  • 局部变量
  • 参数变量
  • 类型参数

对于类和接口,声明如下:

@Entity
public class User{...}

对于变量,声明如下:

@SuppressWarnings("unchecked")
List users = ...;public User getUser(@Param("id") String userId)

泛化类或者方法中的类型参数,声明可以如下:

public class Cache<@Immutable V>{...}

1.5 注解类型的用法

类型用法注解可以出现在下面的位置:

@NonNull注解可以通过静态分析工具检查参数不为空的断言是否有效

  • 与泛型类型引元一起使用:

    List<@NonNull String>,
    Comparator.<@NonNull String>reverseOrder() //这是静态泛型方法的调用方式
    
  • 在数组中的任何位置:

    @NonNull String[][] words,//表示words[i][j]不为null
    String @NonNull[][] words,//表示words不为null
    String[] @NonNull[] words //表示words[i]不为null
    
  • 与超类和实现接口一起使用:

    class Warning extends @Localized Message
    
  • 与构造器一起使用:

    new @Localized String(...)
    
  • 与强制转型和instanceof检查一起使用:

    (@Localized String)text,
    if(text instanceof @Localized String)
    

    这些注解只提供给外部工具使用,对代码实际逻辑没有任何影响

  • 与异常规约一起使用:

    public String read() throws @Localized IOException;
    
  • 与通配符和类型边界一起使用:

    List<@Localized ? extends Message>,
    List
    

2. 标准注解

2.1 一些常见的注解

  • @Override

    应用场合:方法

    目的:检查该方法是否覆盖了某一个父类方法

  • @Resource

    应用场合:类、接口、方法、域

    目的:在类或者接口上时,标记为在其他地方要用到的资源;在方法或域上时,为“注入”而标记。

  • @Target

    应用场合:注解

    目的:限制该注解可以应用到哪些项。

    例子:

    @Target({ElementType.TYPE, ElementType.METHOD})
    public @interface AnnotationName
    
  • @Retention

    应用场合:注解

    目的:指明这个注解可以保留多久,或者说指明这个注解的生命周期

    例子:

    @Retention(RetentionPolicy.RUNTIME)
    public @interface ActionListener
    
  • @Inherited

    应用场合:类的注解

    目的:指明当这个注解应用于一个类的时候,能够自动被它的子类继承。

3. 自定义注解

使用@interface自定义注解时候,自动继承了 java.lang.annotation.Annotation接口

  • @interface用来声明一个注解,格式:public @interface AnnotationName{...}

  • 其中的每一个方法实际上是声明了一个配置参数,如下的value虽然看着像是方法,其实是一个叫做value的配置参数

    @interface Example{String value() default "[none]"
    }
    
  • 方法的名称就是参数的名称

  • 返回值类型就是参数的类型(只能是基本类型,Class,String,enum)

  • 可以通过default声明参数的默认值。如果没有默认值,使用时必须要赋值。

  • 如果只有一个参数成员,一般设置参数名为value,成为单值注解

  • 注解元素必须要有值,不允许为null,可以使用0、空字符串。

  • 注解元素之间没有顺序性。

自定义一个简单注解,例子:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{String name() default "";int id() default -1;int age() default 0;String[] studentIds() default {"U1101","U1102"};
}

4. 使用反射操作注解

核心方法:

//返回类,方法或者域上的具体某个注解
field.getAnnotation(Class annotationType);
method.getAnnotation(Class annotationType);
cl.getAnnotation(Class annotationType);obj.getAnnotations();//返回类,方法或者域上的所有注解

场景:类与数据库的关联。

首先看一下学生类:

class Student{privateint id;private int age;private String name;public Student(){  }public Student(int id,int age, String name){this.id = id;this.age= age;this.name = name;}//getter setter...//toString
}

创建一个类名的注解:

@Target({ElementType.TYPE})//要作用在类上
@Retention(RetentionPolicy.RUNTIME)//运行时
@interface Table{String value();
}

将Table注解作用在Student类上:

@Table("db_name")
public Student{...}

创建一个属性的注解:

@Target({ElementType.FIELD})//要作用在域上
@Retention(RetentionPolicy.RUNTIME)//运行时
@interface FieldAnnotation{String columnName();//数据库中的列名String type();//数据库中的类型int length();//长度
}

作用在学生类中的各个要与数据库关联的域上:

public class Student{@FieldAnnotation(columnName = "db_id", type = "int", length = 10)private int id;@FieldAnnotation(columnName = "db_age", type = "int", length = 10)private int age;@FieldAnnotation(columnName = "db_name", type = "varchar", length = 3)private String name;
}

最后,通过反射来进行关联:

public static void main(String[] args) throws Exceptions{Class cl = Class.forName("com.example.Student");//通过反射获取注解Annotation[] annotations = cl.getAnnotations();//获取所有注解//获取注解的value的值//首先获取该类中为Table.class的注解Table tableAnnotation = (Table) cl.getAnnotation(Table.class);//然后获取该注解中的值String value = tableAnnotation.value();//获取域的注解//首先通过反射获取域Field f = cl.getDeclaredField("name");//在通过域,获取加在域上的注解FieldAnnotation fieldAnnotation = (FieldAnnotation)f.getAnnotation(FieldAnnotation.class);//获取name域上打上的注解的值String columnName = fieldAnnotation.columnName();String type = fieldAnnotation.type();int length = fieldAnnotation.length();}

我们获取到所有注解上的参数后,就可以拼接出数据库需要的语句,完成我们的目的。

相关内容

热门资讯

安卓系统音乐软件推荐,五大热门... 你有没有发现,手机里音乐软件那么多,挑一款适合自己的真心不容易啊!安卓系统上的音乐软件更是五花八门,...
安卓系统刷三星系统,轻松刷入最... 你有没有想过,你的安卓手机其实可以变身成三星的旗舰机呢?没错,就是那种屏幕大、性能强、系统流畅的旗舰...
塞班系统可以转为安卓,跨越时代... 你知道吗?现在科技的发展真是让人眼花缭乱,连我们曾经熟悉的塞班系统也能华丽转身,变成安卓系统呢!是不...
安卓系统如何录像剪辑,录像剪辑... 亲爱的手机控们,你是否有过这样的经历:在某个瞬间,你捕捉到了一段令人难忘的画面,却因为没来得及记录而...
安卓系统强行提高配置,配置提升... 最近你的安卓手机是不是感觉有点儿“发烧”了?没错,就是那种配置突然“升级”的感觉。你是不是也觉得,手...
安卓系统能做设计吗,探索安卓系... 你有没有想过,安卓系统竟然也能做设计?是的,你没听错,这个我们日常使用的手机操作系统,竟然也能成为设...
安卓系统几年后使用,探索多年使... 你有没有想过,那些陪伴我们多年的安卓手机,它们现在过得怎么样了呢?安卓系统,这个曾经让我们爱恨交加的...
平板安卓苹果双系统,安卓与苹果... 你有没有想过,拥有一台既能运行安卓系统,又能使用苹果系统的平板电脑,那该是多么酷炫的事情啊!想象一边...
嘉和病历系统安卓,便捷医疗信息... 你有没有听说过嘉和病历系统安卓版?这可是医疗行业的一大神器呢!想象医生们拿着手机就能轻松管理病历,患...
安卓10更改系统号,揭秘系统编... 你知道吗?最近安卓系统又来了一次大更新,安卓10正式上线了!这次更新可是带来了不少新功能,其中最引人...
小米墨水屏 安卓系统,融合科技... 你知道吗?在科技日新月异的今天,电子阅读器市场也迎来了新的活力。而小米,这个我们熟悉的品牌,最近推出...
系统软件最少的安卓系统,基于最... 你有没有想过,手机系统就像是我们生活的操作系统,有时候太复杂了,让人感觉头都大了。今天,我要给你介绍...
安卓系统关闭应用推荐,安卓系统... 你有没有发现,手机里的安卓系统最近有点儿“小情绪”,总是给你推荐一些你根本不感兴趣的应用?别急,今天...
车载安卓系统如何用,智能驾驶体... 你有没有想过,你的车载安卓系统其实是个隐藏的宝库呢?没错,就是那个你每天开车时几乎不离手的那个屏幕,...
安卓系统更新如何取消,```p... 你有没有遇到过这种情况:安卓手机的系统更新推送得让人有点头疼,有时候更新后的系统还各种不适应。别急,...
安卓系统源码修改练习,从零开始... 亲爱的技术爱好者,你是否曾梦想过深入安卓系统的内核,亲手修改源码,让手机变得更加个性化?那就让我们一...
安卓考勤系统论文,基于安卓平台... 你有没有想过,每天打卡上班,是不是也能变得有趣起来呢?没错,就是那个我们每天都要面对的安卓考勤系统。...
安卓系统哪家流畅度,安卓系统流... 手机里的安卓系统,就像是每个人的小世界,各有各的风采。但说到流畅度,这可是大家最关心的问题了。今天,...
安卓开不了定位系统,安卓设备定... 最近是不是发现你的安卓手机定位系统突然罢工了?别急,别慌,今天就来给你详细解析一下这个问题,让你轻松...
安卓系统怎么设置airpod,... 你有没有发现,自从AirPods问世以来,它就成为了科技界的宠儿?这款无线耳机不仅音质出众,而且连接...