java path 注解_Java内置系统注解和元注解
第一节:注解(Annotation)的作用
Annotation(注解)是JDK5.0及以后版本引入的。它的作用是修饰程序元素。什么是程序元素呢?例如:包、类、构造方法、方法、成员变量等。
注解,就是对某一事物进行添加注释说明,会存放一些信息,这些信息可能对以后某个时段来说是很有用处的。
java提供了一套机制,使得我们可以对方法、类、参数、包、域以及变量等添加标注(即附上某些信息)。且在以后某个时段通过反射将标注的信息提取出来以供使用。
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记。程序可以利用java的反射机制来了解你的类及各种元素上有无何种标记,针对不同的标记,就去做相应的事件。
第二节:定义注解
定义新的Annotation类型使用@interface关键字(在原有interface关键字前增加@符号)。定义一个新的Annotation类型与定义一个接口很像,例如:
public @interface Test{
}
定义完该Annotation后,就可以在程序中使用该Annotation。使用Annotation,非常类似于public、final这样的修饰符,通常,会把Annotation另放一行,并且放在所有修饰符之前。例如:
@Test
public class MyClass{
....
}
根据注解是否包含成员变量,可以把注解分为如下两类:标记注解:没有成员变量的Annotation被称为标记。这种Annotation仅用自身的存在与否来为我们提供信息,例如@override等。
元数据注解:包含成员变量的Annotation。因为它们可以接受更多的元数据,因此被称为元数据Annotation。 成员以无参数的方法的形式被声明,其方法名和返回值定义了该成员变量的名字和类型。
成员变量Annotation只有成员变量,没有方法。Annotation的成员变量在Annotation定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。例如:
public @interface MyTag{
string name();
int age();
}
示例中定义了2个成员变量,这2个成员变量以方法的形式来定义。
一旦在Annotation里定义了成员变量后,使用该Annotation时就应该为该Annotation的成员变量指定值。例如:
public class Test{
@MyTag(name="红薯",age=30)
public void info(){
......
}
}
也可以在定义Annotation的成员变量时,为其指定默认值,指定成员变量默认值使用default关键字。示例:
public @interface MyTag{
string name() default "我兰";
int age() default 18;
}
如果Annotation的成员变量已经指定了默认值,使用该Annotation时可以不为这些成员变量指定值,而是直接使用默认值。例如:
public class Test{
@MyTag
public void info(){
......
}
}
如果注解只有一个成员变量,则建议取名为value,在使用时可用忽略成员名和赋值符=
第三节:基本注解
在java.lang包下,JAVA提供了5个基本注解::
@Override
限定重写父类方法。对于子类中被@Override 修饰的方法,如果存在对应的被重写的父类方法,则正确;如果不存在,则报错。@Override 只能作用于方法,不能作用于其他程序元素。
@Deprecated
用于表示某个程序元素(类、方法等)已过时。如果使用了被@Deprecated修饰的类或方法等,编译器会发出警告。
@SuppressWarnings
抑制编译器警告。指示被@SuppressWarnings修饰的程序元素(以及该程序元素中的所有子元素,例如类以及该类中的方法.....)取消显示指定的编译器警告。例如,常见的@SuppressWarnings(value="unchecked")
SuppressWarnings注解的常见参数值的简单说明:
1.deprecation:使用了不赞成使用的类或方法时的警告(使用@Deprecated使得编译器产生的警告);
2.unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型; 关闭编译器警告
3.fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
4.path:在类路径、源文件路径等中有不存在的路径时的警告;
5.serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告;
6.finally:任何 finally 子句不能正常完成时的警告;
7.all:关于以上所有情况的警告。
@SafeVarargs
@SafeVarargs是JDK 7 专门为抑制“堆污染”警告提供的。
@FunctionalIterface (java 8 新增的)
函数式接口。Java8规定:如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法),该接口称为函数式接口。
@FunctionalInterface就是用来指定某个接口必须是函数式接口,否则就会编译出错。
@FunctionalInterface
public interface Fun
{
static void foo()
{
System.out.println("foo类方法");
}
default void bar()
{
System.out.println("bar默认方法");
}
void test();//只定义了一个抽象方法
}
如在上面的接口中再加一个抽象方法abc(),则会编译出错。
第四节 元注解
在java.lang.annotation包下,定义了6个元注解。元注解就是修饰注解的注解。
拿到一个注解,如何知道它是否是元注解呢?需要看它的元注解(无论是元注解还是普通注解都是有元注解的),如果看到这样的元注解:@Target(ElementType.ANNOTATION_TYPE),那么此时这个注解一定是元注解。
@Retention
@Target
@Documented
@Inherited
@Repeatable (java 8新增)
类型注解
@Repetable和类型注解在另外一篇博文中介绍。
4.1 @Retention
@Retention用于指定注解可以保留多长时间(生命周期)。
@Retention包含一个名为“value”的成员变量,该value成员变量是RetentionPolicy枚举类型。使用@Retention时,必须为其value指定值。value成员变量的值只能是如下3个:
RetentionPolicy.SOURCE:Annotation只保留在源代码中,编译器编译时,直接丢弃这种Annotation,不记录在.class文件中。
RetentionPolicy.CLASS:编译器把Annotation记录在class文件中。当运行Java程序时,JVM中不可获取该Annotation信息。这是默认值
RetentionPolicy.RUNTIME:编译器把Annotation记录在class文件中。当运行Java程序时,JVM可获取该Annotation信息,程序可以通过反射获取该Annotation的信息。
示例:
package com.demo1;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
//name=value形式
//@Retention(value=RetentionPolicy.RUNTIME)
//直接指定
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTag{
String name() default "我兰";
}
如果Annotation里有一个名为“value“的成员变量,使用该Annotation时,可以直接使用XXX(val)形式为value成员变量赋值,无须使用name=val形式。
4.2 @Target
@Target指定Annotation用于修饰哪些程序元素。@Target也包含一个名为”value“的成员变量,该value成员变量类型为ElementType[ ],ElementType为枚举类型,值有如下几个:
ElementType.TYPE:能修饰类、接口或枚举类型
ElementType.FIELD:能修饰成员变量
ElementType.METHOD:能修饰方法
ElementType.PARAMETER:能修饰参数
ElementType.CONSTRUCTOR:能修饰构造器
ElementType.LOCAL_VARIABLE:能修饰局部变量
ElementType.ANNOTATION_TYPE:能修饰注解
ElementType.PACKAGE:能修饰包
示例1(单个ElementType):
package com.demo1;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
public @interface AnnTest {
String name() default "sunchp";
}
示例2(多个ElementType):
package com.demo1;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface AnnTest {
String name() default "sunchp";
}
4.3 @Documented
如果定义注解A时,使用了@Documented修饰定义,则在用javadoc命令生成API文档后,所有使用注解A修饰的程序元素,将会包含注解A的说明。
示例:
@Documented
public @interface Testable {
}
public class Test {
@Testable
public void info() {
}
}
4.4 @Inherited
@Inherited指定注解具有继承性。如果某个类使用了@xxx注解(定义该注解时使用了@Inherited修饰)修饰,则其子类将自动被@xxx修饰
示例:
package com.demo2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyTag{
}
package com.demo2;
@MyTag
public class Base {
}
package com.demo2;
//SubClass只是继承了Base类
//并未直接使用@MyTag注解修饰
public class SubClass extends Base {
public static void main(String[] args) {
System.out.println(SubClass.class.isAnnotationPresent(MyTag.class));
}
}
示例中Base使用@MyTag修饰,SubClass继承Base,而且没有直接使用@MyTag修饰,但是因为MyTag定义时,使用了@Inherited修饰,具有了继承性,所以运行结果为true。
如果MyTag注解没有被@Inherited修饰,则运行结果为:false。
第五节:注解的语法与定义形式
(1)以@interface关键字定义
(2)注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。
上面的语法不容易理解,下面通过例子来说明一下,这个例子就是Target注解的源码,
1
2
3
4
5
6
@Retention(value=RetentionPolicy.RUNTIME)
@Target(value={ElementType.ANNOTATION_TYPE})
public@interfaceTarget
{
ElementType[]value();
}
源码分析如下:
第一:元注解@Retention,成员value的值为RetentionPolicy.RUNTIME。
第二:元注解@Target,成员value是个数组,用{}形式赋值,值为ElementType.ANNOTATION_TYPE
第三:成员名称为value,类型为ElementType[]
另外,需要注意一下,如果成员名称是value,在赋值过程中可以简写。如果成员类型为数组,但是只赋值一个元素,则也可以简写。如上面的简写形式为:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
第六节:注解的底层实现
定义一个注解:
1
2
3
4
5
6
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public@interfaceCache
{
Stringvalue()default"cache";
}
分析其字节码,如下图所示:
C:\Users\Administrator\workspace\cache\bin>javap -verbose Cache
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Classfile/C:/Users/Administrator/workspace/cache/bin/Cache.class
Last modified2016-7-23;size429bytes
MD5checksum771f9c4d63ce2ded5d3b093deebd2c69
Compiled from"Cache.java"
publicinterfaceCacheextendsjava.lang.annotation.Annotation
minor version:0
majorversion:52
flags:ACC_PUBLIC,ACC_INTERFACE,ACC_ABSTRACT,ACC_ANNOTATION
Constantpool:
#1 = Class #2 // Cache
#2 = Utf8 Cache
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Class #6 // java/lang/annotation/Annotation
#6 = Utf8 java/lang/annotation/Annotation
#7 = Utf8 value
#8 = Utf8 ()Ljava/lang/String;
#9 = Utf8 AnnotationDefault
#10 = Utf8 cache
#11 = Utf8 SourceFile
#12 = Utf8 Cache.java
#13 = Utf8 RuntimeVisibleAnnotations
#14 = Utf8 Ljava/lang/annotation/Retention;
#15 = Utf8 Ljava/lang/annotation/RetentionPolicy;
#16 = Utf8 RUNTIME
#17 = Utf8 Ljava/lang/annotation/Target;
#18 = Utf8 Ljava/lang/annotation/ElementType;
#19 = Utf8 TYPE
{
publicabstractjava.lang.Stringvalue();
descriptor:()Ljava/lang/String;
flags:ACC_PUBLIC,ACC_ABSTRACT
AnnotationDefault:
default_value:s#10
}
SourceFile:"Cache.java"
RuntimeVisibleAnnotations:
0:#14(#7=e#15.#16)
1:#17(#7=[e#18.#19])
分析上面的字节码,我们可以得出:
第一:
public interface Cache extends java.lang.annotation.Annotation,说明Cache注解是继承自Annotation,仍然是interface。
第二:
public abstract java.lang.String value(),说明value方法是abstract类型。
当开发者使用了注解修饰了类、方法、成员变量等成员之后,这些注解不会自己生效,必须由开发者提供相应的代码来提取并处理注解信息。这些提取和处理注解的代码统称为APT(Annotation Processing Tool)注解处理工具。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。这一部分在《Java自定义注解中讲解》 。
java path 注解_Java内置系统注解和元注解相关推荐
- java 表达式写法_java内置核心4大函数式接口写法和lambda表达式
java.util.function , Java 内置核心四大函数式接口标准写发和lambda表达式 消费型接口,有一个输入参数,没有返回值 public static void main(Stri ...
- JDK注解(内置和自定义)
JDK注解(内置和自定义) 1.内置 @Override:可以确保重写的方法,的确存在与父类.接口中,可以有效避免单词拼错的情况 @Deprecated:给用于提示,该方法由于安全,性能问题等,已经不 ...
- java 反射泛型方法_java基础之反射和泛型以及注解
java基础之反射和泛型以及注解 泛型擦除 泛型擦除: 泛型只在编译时期有效,编译后的字节码文件中不存在泛型信息. 声明泛型集合,集合两端类型必须一致.类型也可以用包装类型,泛型的类型必须是引用类型, ...
- Android内置系统apk问题
平台:Rockchip android版本: 7.1 个人博客:https://www.letcos.top/ 1.问题描述 一款产品需要内置定制的launcher,使用了一些第三方的sdk.按系 ...
- java对嵌入式_Java用于嵌入式系统的优点
Java用于嵌入式系统的优点 与个人计算机这样的通用计算机系统不同,嵌入式系统通常执行的是带有特定要求的预先定义的任务.yjbys小编下面为你整理了关于Java用于嵌入式系统的优点,希望对你有所帮助. ...
- 企业级JAVA快速开发平台, 内置代码生成器 - JavaFast快速开发平台
企业级JAVA快速开发平台, 内置代码生成器 - JavaFast快速开发平台 JavaFast是一款基于代码生成器的智能快速开发平台,可以帮助解决java项目中80%的重复工作,让开发者更多关注业务 ...
- JavaFast技术特点介绍-企业级JAVA快速开发平台, 内置java代码生成器
企业级JAVA快速开发平台, 内置代码生成器 - JavaFast快速开发平台 JavaFast是一款基于代码生成器的智能快速开发平台,可以帮助解决java项目中80%的重复工作,让开发者更多关注业务 ...
- Windows内置系统账户Local system/Network service/Local Service
内置系统账户:Local system/Network service/Local Service 区别 [ LocalSystem 账户] LocalSystem是预设的拥有本机所有权限的本地 ...
- 我的世界java版使用剑_我的世界:JAVA版藏“私货”内置绝世好剑与神功,你玩的版本有吗...
导语:我的世界:JAVA版藏"私货"内置绝世好剑与神功,你玩的版本有吗! 在我的世界这款游戏中,每件物品都有它自己存在的作用,铁镐挖矿,盔甲防护,却也有一些物品被创作者赋予了奇怪的 ...
最新文章
- 《 嵌入式系统设计与实践》一一3.6 测试硬件(和软件)
- Apache Ignite——集合分布式缓存、计算、存储的分布式框架
- python帮助文档在哪_python文档在哪里
- IDEA :windows下Hadoop报错null\bin\winutils.exe
- 通过程序包管理器控制台解决版本错误(CS1705)
- Jackson Annotation Examples
- 推荐学习网页标准的20个好去处
- 在eclipse中搭建struts2框架的详细过程
- 进度管理工具 planner
- 网络流(最大流)基础入门
- 常见元件、封装及尺寸
- Go-Redis使用手册
- 生成扩散模型漫谈:DDPM = 自回归式VAE
- React Native 中使用图标
- 服务器win7无限重启,win7系统无限重启的解决方法
- DOS时代后,金山系再出神级办公软件,会像WPS一样普及
- keyshot渲染图文教程_keyshot基础图文教程,手把手教你用keyshot制作动画效果
- 【百元钱买百只鸡问题】一只公鸡5元钱,一只母鸡3元钱,三只小鸡1元钱。要求100元买100只鸡,请给出所有可行的结果?
- 图像传感器binning_CMOS图像传感器调试问题汇总
- weidl x DeepRec:热门微博推荐框架性能提升实战
热门文章
- wsdl和soap协议详细解析
- vivox21支持html,vivo X21支持快充吗_vivo X21支持无线充电吗-太平洋IT百科
- 2019宁夏计算机考试报名时间,2019年上半年宁夏计算机二级考试报名时间
- 在谷歌浏览器上面安装AxueRP插件。
- 【渝粤题库】广东开放大学 经济法实务 形成性考核
- 计算机平面设计教材,《计算机平面设计软件应用——全国中等职业技术学校计算机教材》低价购书_教材教辅考试_孔网...
- 室内设计师面试技巧有哪些?
- 计算机毕业设计django基于python企业资产管理系统
- 头牌知产介绍减肥药商标注册属于哪一类?
- 【计算机毕业设计】029网上购物商城系统