0035 Java学习笔记-注解
什么是注解
- 注解可以看作类的第6大要素(成员变量、构造器、方法、代码块、内部类)
- 注解有点像修饰符,可以修饰一些程序要素:类、接口、变量、方法、局部变量等等
- 注解要和对应的配套工具(APT:Annotation Processing Tool)一起使用,APT会对含有注解进行一些处理
- 比如API文档里面,有些方法下边的“@Deprecated”,就是一个注解,它表示这个方法已经过时,使用的时候会收到警告
- 注解完全不影响程序的功能
元注解
- 元注解有6个,位于java.lang.annotation包下
- @Retention
- 只能修饰注解
- 用于指定被修饰的注解,可以保留到什么时间
- @Retention只有一个元素:value,是RetentionPolicy类型,这是个枚举类,只有如下三个值
- RetentionPolicy.SOURCE:注解只保留在源代码中,编译阶段即被丢弃
- RetentionPolicy.CLASS:保留在class文件中,程序运行时,JVM不能获取到该注解
- RetentionPolicy.RUNTIME:保留在class文件中,程序运行时,可以通过反射获得该注解
- @Target
- 只能修饰注解
- 用于指定被修饰的注解,可以用于修饰哪些程序元素
- @Target只有一个元素:value,是ElementType[]类型,ElementType也是个枚举类,只有如下十个值
- ElementType.TYPE:表示被修饰的注解可以修饰类、接口、注解、枚举
- ElementType.FIELD:只能修饰成员变量
- ElementType.METHOD:只能修饰方法
- ElementType.PARAMETER:可以修饰参数
- ElementType.CONSTRUCTOR:只能修饰构造器
- ElementType.LOCAL_VARIBLE:只能修饰局部变量
- ElementType.ANNOTATION_TYPE:只能修饰注解
- ElementType.PACKAGE:只能修饰包
- ElementType.TYPE_USE:since 1.8,表示注解能写在
使用
类型变量的语句中 - ElementType.TYPE_PARAMETER:since 1.8,表示注解能写在类型变量的
声明
语句中
- @Documented
- 修饰注解,该注解将被javadoc提取进入文档
- 该元注解没有元素
- @Inherited
- 修饰注解,表示该注解具有继承性
- 比如:一个父类使用了一个注解X修饰,而X注解在定义时用了@Inherited修饰,那么子类自动被X修饰
- @Repeatable
- 用于修饰一个注解,表示该注解可以用于重复注解
- 包含一个变量value,是Annotation的Class类型
- @Native
基本注解
- 基本注解有5个,位于java.lang包下
- @Override
- 只能修饰方法;保留在源代码阶段
- 告诉编译器,被该修饰符修饰的方法是在重写父类的方法,如果父类中没有相同签名的方法,那么会发生错误
- @Deprecated
- 修饰构造器、成员变量、局部变量、方法、包、参数、类、注释、枚举;保留到运行阶段;javadoc提取
- 表示该元素已过时,其他地方使用这些元素时,编译器会给出警告
- @SuppressWarnings
- 修饰类、接口、注解、枚举、成员变量、方法、参数、构造方法、局部变量;保留在源代码阶段;
- 只有一个变量value,类型为String[]
- 被修饰的程序元素及子元素取消value指定的编译器警告
- @SafeVarargs
- 修饰构造器、方法;保留在运行阶段;javadoc提取
- 专门修饰会引发“堆污染”警告的方法或者构造器
- since 1.7
- @FunctionalInterface
- 只能修饰接口;保留到运行阶段;javadoc提取
- 告诉编译器严格检查,该接口为函数式接口
- since 1.8
自定义注解
- 自定义注解跟定义接口类似,只是用“@interface”关键字替换“interface”
- 可以用一些元注解修饰即可,对于保留时间,如果不写@Target,那么默认是修饰任何程序要素
- 可以包含变量
- 比如@Deprecated的源代码是这样的
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
@Documented //元注解:表示该注解会被javadoc提取到文档中
@Retention(RetentionPolicy.RUNTIME) //元注解:保留到运行阶段
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) //元注解:可以修饰的程序元素
public @interface Deprecated {
}
- 再比如@SuppressWarnings的源代码
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value(); //可以包含变量,String[]是该变量的类型
}
- 包含变量的时候,使用时就不能只写注解名称,还得写变量的值,比如:
@SuppressWarnings(value="unchecked")
//如果只有一个变量,那么可以省略变量名:
@SuppressWarnings("unchecked")
- 不写变量名和值,那么该注解在定义的时候,就得定义默认值,用default关键字,比如
@Target({TYPE, FIELD}) //只有一个变量,省略变量名
@Retention(RetentionPolicy.CLASS) //只有一个变量,省略变量名
public @interface Test{
String name() default "Java"; //用default指定默认值
int age() default 18; //用default指定默认值
}
- 实际上,自定义注解默认都是继承了java.lang.annotation.Annotation接口的,见示例:
package testpack;
public class Test1 {
public static void main(String[] args){
Class clazz=Test.class;
Class[] is=clazz.getInterfaces();
for (Class i:is) {
System.out.println(i); //输出:interface java.lang.annotation.Annotation
}
}
}
@interface Test{
}
注解的分类
- 标记注解:不包含成员变量
- 元数据注解:包含成员变量
获取程序元素的注解信息
- 光有注解没用,还得有对应的工具来处理,要处理,得先获取注解信息
- 获取到注解信息的前提是,注解能保留到"获取"这个操作的时候
- 在文章0033 Java学习笔记-反射-初步1中提到,通过反射可以获取一个类的注解信息,有六个方法,其实这些方法都来自于一个接口:java.lang.reflect.AnnotatedElement,Class是它的实现类之一
- java.lang.reflect.AnnotatedElement是个接口,表示程序中可以接受注解的程序元素,主要有如下几个实现类
- Package
- Class
- Filed
- Constructor
- Method
- Parameter
- 以上这些类都包含0033 Java学习笔记-反射-初步1中关于获取注解的那6个方法,
- 除以上6个方法外,还有一个方法用于判断程序元素上是否存在指定类型的注解:boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
- 见示例:
package testpack;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Test(name="Java",age=18)
public class Test1 {
public static void main(String[] args){
Class clazz=Test1.class;
Annotation a=clazz.getAnnotation(Test.class); //获取对应类的Test类型的注解
System.out.println(a);
if (a instanceof Test){
System.out.println(((Test)a).name()); //强制类型转型后获取name的值
System.out.println(((Test)a).age()); //强制类型转型后获取age的值
}
}
}
@Retention(RetentionPolicy.RUNTIME) //保留到运行时,这条很重要
@interface Test{
public String name(); //定义两个变量
public int age();
}
重复注解
- 重复注解是Java8新增的功能
- 重复注解是值:用多个相同类型的注解修饰同一个程序元素
- 使用重复注解要分3步走:
- 定义一个注解,并用@Repeatable修饰
- 再定义一个该注解的容器注解
- 使用重复注解
- 示例:
package testpack;
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Test(name="C++",age=30)
@Test(name="Java",age=18) //使用了两个相同类型的注解
public class Test1 {
public static void main(String[] args){
Class clazz=Test1.class;
Annotation[] as=clazz.getAnnotations();
for (Annotation a:as){
System.out.println(a);
//输出:@testpack.Tests(value=[@testpack.Test(name=C++, age=30), @testpack.Test(name=Java, age=18)])
//其实还是只有一个注解,就是Tests这个容器注解
}
}
}
@Repeatable(Tests.class) //用@Repeatable修饰
@Retention(RetentionPolicy.RUNTIME)
@interface Test{ //定义Test注解
public String name();
public int age();
}
@Retention(RetentionPolicy.RUNTIME) //容器注解的保留时间不能早于其对应的注解
@interface Tests{ //定义Test的容器注解Tests
Test[] value(); //容器注解的变量
}
类型注解
- 类型注解也是Java8新增功能
- Java8以前的注解只能用在一些特定的程序元素上,
- ElementType.TYPE_PARAMETER:表示注解能写在类型变量的
声明
语句中 - ElementType.TYPE_USE:表示注解能写在
使用
类型变量的语句中 - 对该部分内容没什么理解,更详细的内容见:Java 8的类型注解:工具和机会
APT工具
- APT(Annotation Processing Tool):一种注解处理工具,用于对源代码文件进行检测,找出特定的注解信息,然后进行特别的处理
- 比如可以在编译源代码的同时,生成一些附属的描述文件,
- 在用javac.exe编译源代码时,可以用“-processor”选项指定注解处理器
- 注解处理器一般实现javax.annotation.processing.Processor接口或者继承AbstractProcessor抽象类
- 一个注解处理器,可以处理一个或多个注解
其他
- 注解在提高开发效率方面,作用很大
- 参考:Java 8的类型注解:工具和机会
0035 Java学习笔记-注解的更多相关文章
- Java学习笔记--注解和反射
注解和反射 1. 注解 注解作用: 对程序做出解释 被其他程序读取 注解格式: @注释名,还可以添加一些参数值,例如@SuppressWarnings(value="unchecked&qu ...
- Java学习笔记--注解
注解的使用与实例:http://www.cnblogs.com/pepcod/archive/2013/02/16/2913474.html 注解的作用及使用方法:http://wenku.baidu ...
- 0028 Java学习笔记-面向对象-Lambda表达式
匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...
- 《Java学习笔记(第8版)》学习指导
<Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...
- Java学习:注解,反射,动态编译
狂神声明 : 文章均为自己的学习笔记 , 转载一定注明出处 ; 编辑不易 , 防君子不防小人~共勉 ! Java学习:注解,反射,动态编译 Annotation 注解 什么是注解 ? Annotat ...
- Java学习笔记之---Servlet
Java学习笔记之---Servlet (一)如何实现Servlet 1.实现javax.servlet.Servlet接口: 2.继承javax.servlet.GenericServlet类: 3 ...
- java学习笔记之基础篇
java选择语句之switch //switch可以用于等值判断 switch (e) //int ,或则可以自动转化成int 的类型,(byte char short)枚举jdk 7中可以防止字 ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- Java学习笔记(04)
Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...
随机推荐
- 使用R画地图数据
用R画地图数据 首先,从这里下载中国地图的GIS数据,这是一个压缩包,完全解压后包含三个文件(bou2_4p.dbf.bou2_4p.shp和bou2_4p.shx),将这三个文件解压到同一个目录下. ...
- Atitit 会话层和表示层的异同
Atitit 会话层和表示层的异同 会话层 这一层也称为会晤层或对话层.在会话层及以上的更高层次中,数据传送的单位没有另外再取名字,一般都可称为报文. 会话层虽然不参与具体的数据传输,但它却对数据传输 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(11)-系统日志和异常的处理①
系列目录 系统需要越来越自动化,我们需要引入日志记录和异常捕获管理员的操作记录需要被记录,看出哪些模块是频繁操作,分析哪些是不必要的功能,哪些是需要被优化的.系统的异常需要被捕获,而不是将系统出错显示 ...
- WebGIS中快速整合管理多源矢量服务以及服务权限控制的一种设计思路
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在真实项目中,往往GIS服务数据源被其他多个信息中心或者第三方 ...
- 通过Http接口及SolrNet 两种方法基于Solr5.5.1 实现CURD
前言 老规矩,任何技术的入门我通常都会总结增删改查,本文我就通过HttpWebRequest和SolrNet的方式实现Solr最基础的增删改查(CURD).对于自己的完整项目,同时不想过于依赖第三方类 ...
- 【分布式】Zookeeper使用--开源客户端
一.前言 上一篇博客已经介绍了如何使用Zookeeper提供的原生态Java API进行操作,本篇博文主要讲解如何通过开源客户端来进行操作. 二.ZkClient ZkClient是在Zookeepe ...
- 探寻 JavaScript 逻辑运算符(与、或)的真谛
十二月已经过半,冬季是一个美妙的季节,寒冷的空气逼得人们不得不躲在安逸舒适的环境里生活.冬季会给人一种安静祥和的氛围,让人沉浸在其中,仿佛是一个旧的阶段的结束,同时也是一个新的阶段的开始.这么说来,西 ...
- Effective前端1:能使用html/css解决的问题就不要使用JS
div{display:table-cell;vertical-align:middle}#crayon-theme-info .content *{float:left}#crayon-theme- ...
- mongodb在java中的查询
mongodb 根据_id 查询记录: public Price queryPriceById(String id) throws Exception { return mongoTemplate.f ...
- 运用css,对于下拉菜单的制作
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <met ...