Java注解(Annotation)

0.0 Hello World

先上代码,再加以说明。这样不至于让初学者懵。

例1

public class Dog extends Animal(){

@Override

public void call(){

System.out.println("汪汪...");

}

}

0.1 Java自带注解 - @Override

方法call()上声明的@Override是Java自带的注解,它的作用是标记这个方法是重写的。当类继承的类或接口没有这个方法,编译时就会报错,因为你声明了这个注解的意图是希望重写某个方法。另外一个作用是在生成javadoc上这个方法也会显示@Override表示这个方法是重写的。

0.2 注解只是为代码提供描述

显然@Override并没有影响你的代码执行。你删注解,代码还是正常运行。这样我们就得出一个结论:Java注解只是为代码的元素(类,方法,方法参数等)提供描述。

0.3 注解处理

看到这里你可能觉得注解不没什么作用,但是想想看,上面讲到的编译时会报错,这是什么在起作用。虽然将注解本身并没有逻辑,但是你标注了注解这有助于其他程序执行。在这里,你标注了@Override,编译期发现你在这个方法标注了注解就会进行判断。

到这里你已经大概了解注解是用来干嘛的了。下面是正文部分,内容包括:

自定义注解

Java自带注解

注解处理器

1.0 自定义注解

1.1元注解

我们打开@Override源码看看:

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.SOURCE)

public @interface Override {

}

注解源码非常简单,和接口的定义类似。它使用@interface修饰声明这是一个注解。另外面多了两个注解@Target和@Retention,我们将这些注解叫做元注解,它只用于自定义注解。

@Target

@Target表示你定义的这个注解能用在哪里。包括:

类型

描述

ElementType.ANNOTATION_TYPE

可以给一个注解进行注解

ElementType.CONSTRUCTOR

构造方法

ElementType.FIELD

类属性

ElementType.LOCAL_VARIABLE

局部变量

ElementType.METHOD

方法

ElementType.PACKAGE

ElementType.PARAMETER

方法参数

ElementType.TYPE

类、接口、枚举等

可填多个,使用数组格式{}括起,并用,隔开。

@Retention

@Retention表示自定义的注解的作用范围。可选

类型

描述

RetentionPolicy.SOURCE

只在源码时作用

RetentionPolicy.CLASS

源码及编译期作用

RetentionPolicy.RUNTIME

源码、编译期和运行时都起作用

另外还有两个可选元注解

@Documented

表示生成javadoc时也包括当前自定义注解

@Inherited

表示当前注解能被继承。但不是指继承自定义注解,是指某个类继承了一个使用了这个注解的类时,这个注解也被继承。

1.2 注解属性

接下来,我们来看看一个复杂一点的注解源码,这是Spring的@Bean源码:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Bean {

@AliasFor("name")

String[] value() default {};

@AliasFor("value")

String[] name() default {};

Autowire autowire() default Autowire.NO;

String initMethod() default "";

String destroyMethod() default "(inferred)";

}

这个注解和上面最大的区别是注解体内多了很多方法。其实这些不是方法,而是注解的属性。有了这些属性,我们就可以进一步描述代码。

注解属性定义格式为类型 属性名() default 初始值;。

注解属性对类型是有限制的,只能是下面的类型:

8个基础类型

Class

String

enum(上面Autowire 就是enum类型)

Annotation

或上面类型的数组形式

default是一个修饰符,和=类似;

初始值不为null,所以上面看到String类型用空字符串"";

另外如果注解只有一个参数时属性名必须时value。

在使用注解时,可以像上面元注解@Target后面()就是填写的属性。

当属性只有一个时,直接填写属性。即注解的value()属性;

如果多个需要用@Target(属性名=属性值,属性名=属性值)的形式填入;

2.0 Java自带注解

Java自带注解非常简单,只有三个。

@Override

用于标记方法是重写的。建议在重写的方法上标记,这有助与阅读和IDE对你的错误做出提示。

@Deprecated

用于声明被被标注的代码以过期,不建议使用。在编译时会得到错误导致编译失败。可以在除ANNOTATION_TYPE外的代码中标记。

@SupressWarning

虽然被标注了@Deprecated编译就会错误。当时有时久的程序代码,必须要使用这个类。这是可以使用@SupressWarning标注忽略@Deprecated导致编译错误。

注解处理

在开始我们讲到注解只是为代码提供描述,但是其他程序可以利用这些描述数据来判断如果执行操作。注解处理是使用Java反射来完成的。

注:反射简述。

类,方法,实例属性等本身也是对象,比如讲类定义的是什么修饰符,它有哪些方法,哪些实例属性,哪些注解。所以每个类其实都是Java的Class类型的实例,通过Class可以了解类本身的一切或操作某些特定功能。

比如讲,我们有一些动物类,我们创建了一个@Animal自定义注解表示他们的特性,例如脚数,咬不咬人。

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface AnimalTrait{

int footNum() default 0;

boolean bitePeople default false;

}

动物类

@AnimalTrait(footNum=4,bitePeople=true)

class Dog extends Call{

public void call(){

System.out.println("汪汪...");

}

}

@AnimalTrait(footNum=4,bitePeople=false)

class Cat extends Animal{

public void call(){

System.out.println("喵喵...");

}

}

@AnimalTrait(footNum=2,bitePeople=false)

class Monkey extends Animal{

public void call(){

System.out.println("吖吖...");

}

}

//...其他动物类

假设我们有一个动物园集合,存放了全部动物的实例。我们现在要写一个类将咬人的动物和不咬人的动物分开到连个集合以便管理它们。

import java.util.ArrayList;

public class Main {

public static void main(String[] args) {

ArrayList zooAnimal = new ArrayList<>();

ArrayList biteList = new ArrayList<>();

ArrayList notbiteList = new ArrayList<>();

for(int i=0;i<8;i++){

zooAnimal.add(new Cat());

zooAnimal.add(new Dog());

}

for(Animal animal:zooAnimal){

//主要部分,获取实例对应类型的@AnimalTrait注解的bitePeople属性

if(animal.getClass().getAnnotation(AnimalTrait.class).bitePeople()){

biteList.add(animal);

} else {

notbiteList.add(animal);

}

}

System.out.println("咬人的动物叫声:");

for(Animal animal:biteList){

animal.call();

}

System.out.println("不咬人的动物叫声:");

for(Animal animal:notbiteList){

animal.call();

}

}

}

其中主要的是的是获取注解信息的部分,条件中使用getClass获取实例类的Class实例,再用getAnnotation()获取类的@AnimalTrait的Annotation实例,最后通过.bitePeople()获取注解的属性值。

AnnotatedElement接口

所有反射类型Class、Constuctor、Method、Field等都继承了AnnotatedElement接口。接口的主要作用是获取注解的反射类型然后得到注解的属性。

AnnotatedElement接口常用方法

返回值

方法签名

描述

T

getAnnotation(Class annotationClass)

返回指定注解类型

Annotation[]

getAnnotations()

返回全部注解的数组

default boolean

isAnnotationPresent(Class extends Annotation> annotationClass)

判断是否存在指定类型的注解

Annotation类型

我们获得Annotation类型可以通过.注解属性名()的方式获取注解的属性。

总结

Java注解只是对代码元素提供描述,它并不影响代码执行;

影响代码执行的是注解处理器,利用反射机制获取注解属性;

通过@interface定义注解,通过@Target、@Retention、@Documented和@Inherited元注解来设定注解的类型、生命周期、是否生成到Javadoc和是否被继承。

注解可以有属性,但属性只能是8种基础类型、String、Class、enum、Annotation和以上的数组形式。

最后附上树状图,以便大家复习:

Java注解.png

java 注解入门 简书_Java注解入门相关推荐

  1. java 注解入门 简书_Java基础-注解

    注解是什么? Java注解(Annotation)又称为Java标注.可以从字面的意思理解它,其实就是一个标注.他可以根据定义作用于不同的地方.注解对他们注解的代码没有直接影响.注解是JDK 5中引入 ...

  2. java 枚举使用简书_Java枚举

    1.简介 java中,使用关键字enum来定义枚举类,枚举类是一个特殊的类,大部分功能和普通类是一样的,区别为: 枚举类继承了java.lang.Enum类,而不是默认的Object类.而java.l ...

  3. java 枚举使用简书_java枚举类型使用和详解

    1.定义 An enum type is a special data type that enables for a variable to be a set of predefined const ...

  4. java 面试题 简书_java面试题

    1.面向对象的三大基本特性: 封装:也就是把客观事物封装成抽象的类(向上抽象),并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏(访问权限). 继承:是指这样一种能力:它可 ...

  5. java interface作用是什么_Java注解总结:史上最全,有这一篇就够了

    什么是注解? 注解的定义 官网描述如下: Java 注解用于为 Java 代码提供元数据.作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的.Java 注解是从 Jav ...

  6. java 注解处理器的作用_Java注解处理器

    Java中的注解(Annotation)是一个很神奇的东西,特别现在有很多Android库都是使用注解的方式来实现的.一直想详细了解一下其中的原理.很有幸阅读到一篇详细解释编写注解处理器的文章.本文的 ...

  7. java注解的jar包_Java 注解 Annotation

    目录: 从 JDK5 开始,Java 增加了对元数据(MetaData)的支持,也就是 Annotation.Annotation 其实就是代码里面的特殊标记,这些标记可以在编译.类加载.运行时被读取 ...

  8. java js aes 简书_nodejs中aes-128-cbc加密和解密

    和java程序进行交互的时候,java那边使用AES 128位填充模式:AES/CBC/PKCS5Padding加密方法,在nodejs中采用对应的aes-128-cbc加密方法就能对应上,因为有使用 ...

  9. java判断读到末尾_Java Web入门之java--第一节 java 简介及开发环境安装

    本篇博客是Java web入门的第一篇博客,这篇博客主要讲述java语言的一些简介. 一)先从Java语言的诞生说起. 1991年,Sun公司在一个叫做James Gosling的人的带领下,成立了一 ...

最新文章

  1. Dubbo原码解析(version:2.5.3)
  2. 偏移量详解-源自csna 菜鸟飞人
  3. CTF-i春秋网鼎杯第一场misc部分writeup
  4. OCM备考 三. Managing Database Availability 之RMAN高级操作
  5. 基于.NetCore3.1系列 —— 日志记录之自定义日志组件
  6. 修改MYSQL 密码
  7. wxWidgets第三课 MSWWindowProc处理窗口消息
  8. [2018.03.13 T1] 比赛(contest)
  9. centos安装office及PDF阅读器
  10. SQL 2008升级SQL 2008 R2完全教程或者10 00 1600升级10 50 1600
  11. linux出现bash什么意思,linux中bash是什么
  12. 安装AutoCAD 2015提示net 4.5错误的解决方法
  13. Linux系统下利用共享内存模拟迅雷下载
  14. 自定义view之刻度尺
  15. Day2:python爬虫基础学习(大嘘)
  16. steam验证登录失败_如何向Steam添加两方面身份验证
  17. 什么叫资讯,资讯是什么?
  18. 【莫烦】python基础教程
  19. H264 profile 及帧类型介绍
  20. 一款基于chatGPT的插件【Merlin】,聊天式感受强大AI能力

热门文章

  1. IModelBinder
  2. 设计模式笔记 16. Mediator 中介者模式(行为型模式)
  3. html中li标签之间有缝隙,liimg标签之间空隙bug
  4. java写算法之二叉搜索树查找
  5. c语言win api函数,Win2K下的Api函数的拦截
  6. Python实现视频语音和字幕自动审查功能
  7. Python使用JSON序列化从入门到精通
  8. linux下如何升级gcc和g++编译器
  9. 一文搞定数据结构(图解)
  10. 港大计算机科学奖学金,香港大学奖学金情况怎么样?