“@”Java中的特殊符号——注解(Java中’@‘符号是什么意
思?)
在Java中经常看到这样的字眼
1.@Override
2.@Deprecated
3.@SuppressWarnings
4.@SafeVarargs
5.@FunctionalInterface
很多⼩伙伴不知道什么意思,其实这是⼀种注解,注意是注解 ,不是“ // ”注释哦。
1. 什么是注解(百度百科)
注解,可以看作是对 ⼀个 类/⽅法 的⼀个扩展的模版,每个 类/⽅法 按照注解类中的规则,来为 类/⽅法 注解不同的参数,在⽤到的地⽅可以得到不同的 类/⽅法 中注解的各种参数与值
注解也就是Annotation,相信不少⼈也和我之前⼀样以为和注释和doc⼀样,是⼀段辅助性的⽂字,其实注解不是这样的。
从JDK5开始,java增加了对元数据(描述数据属性的信息)的⽀持。其实说⽩就是代码⾥的特殊标志,这些标志可以在编译,类加载,运⾏时被读取,并执⾏相应的处理,以便于其他⼯具补充信息或者进⾏部署。
2.基本的Annotation
java提供了5个基本的注解,分别是
1.@Override
2.@Deprecated
3.@SuppressWarnings
4.@SafeVarargs
5.@FunctionalInterface
1.限定⽗类重写⽅法:@Override
当⼦类重写⽗类⽅法时,⼦类可以加上这个注解,那这有什么什么⽤?这可以确保⼦类确实重写了⽗类的⽅法,避免出现低级错误
2.标⽰已过时:@Deprecated
这个注解⽤于表⽰某个程序元素类,⽅法等已过时,当其他程序使⽤已过时的类,⽅法时编译器会给出警告(删除线,这个见了不少了吧)。
3.抑制编译器警告:@SuppressWarnings
被该注解修饰的元素以及该元素的所有⼦元素取消显⽰编译器警告,例如修饰⼀个类,那他的字段,⽅法都是显⽰警告
4.“堆污染”警告与@SafeVarargs
想理解这个就要明⽩什么是堆污染,堆污染是什么?
其实很好理解,就是把不带泛型的对象赋给⼀个带泛型的对象,为什么不⾏?很简单,因为不带泛型
的话,默认会给泛型设定为object,意思就是什么类型都可以往⾥⾯塞,那你⼀个不带泛型的怎么可能给⼀个带泛型塞呢。
例如运⾏如下代码:
List list = new ArrayList(); list.add(20); List<String> ls = list; System.out.(0));则会抛出堆污染异常Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at
Test.Test1.main(Test1.java:29)
框架是什么意思注意:可变参数更容易引发堆污染异常,因为java不允许创建泛型数组,可变参数恰恰是数组。
抑制这个警告的⽅法有三个:
1.@SafeVarargs修饰引发该警告的⽅法或构造器
2.使⽤@suppressWarnings("unchecked")
3.编译时使⽤-Xlint:varargs
5.函数式接⼝与@Functionallnterface
什么是函数式?如果接⼝中只有⼀个抽象⽅法(可以包含多个默认⽅法或多个static⽅法)
接⼝体内只能声明常量字段和抽象⽅法,并且被隐式声明为public,static,final。
接⼝⾥⾯不能有私有的⽅法或变量。
这个注解有什么⽤?这个注解保证这个接⼝只有⼀个抽象⽅法,注意这个只能修饰接⼝
3.⾃定义注解
定义注解⾮常的简单,如下
public @interface Test{}
然后这个注解就可以⽤在别的地⽅
例如:
@Test
public class MyClass{}
这个⾃定义注解可以修饰程序中的类、⽅法、变量、接⼝等。通常放在所有修饰符之前。
你还可以为⾃⼰的注解类添加成员变量
例如:
public @interface MyTag{
//注解中的成员变量以⽅法的⽅式来定义
String name();
int age
}
然后
public class Test{
/
/当使⽤⾃定义注解的时候,这个注解本⾝是不会⽣效的,必须由开发者⼯具提取出来并进⾏处理。
@MyTag(name = "XX" , age = 6)
public void info(){}
}
你甚⾄还可以为成员变量指定初始值
public @interface MyTag{
String name() default "yeeku"
int age() default 32;
}
当你指定完默认值的时候,你可以直接@MyTag使⽤不需要带参数。
4.JDK的元Annotation
1.使⽤@Retention
这个注解是⽤来修饰注解定义的,作⽤是被修饰的注解可以保存多久,这个注解需要使⽤参数。
这个参数的类型是RetentionPolicy,所以使⽤这个注解就要对value赋值。
value的值有且仅有三个:
->RetenionPolicy.CLASS 编译器把该注解记录在class⽂件中。当运⾏java程序时,JVM不可获取注解信息。这是默认值!
->RetenionPolicy.RUNTIME编译器把该注解记录在class⽂件中。当运⾏java程序时,JVM可获取注解信息,程序可以通过反射获取该注解信息
->RetenionPolicy.SOURCE 该注解只保存在源代码中,编译器直接丢弃该注解
例如:@Retention(value =RetenionPolicy.SOURCE) 可简写为@Retention(RetenionPolicy.SOURCE)
2.使⽤@Target
@Target也只能修饰⼀个注解定义,作⽤是指定被修饰的注解能⽤于修饰哪些程序单元,@Target也包含了⼀个value值,他的值只能是下⾯的:ElementType.
取值注解使⽤范围
METHOD可⽤于⽅法上
TYPE可⽤于类或者接⼝上
ANNOTATION_TYPE可⽤于注解类型上(被@interface修饰的类型)
CONSTRUCTOR可⽤于构造⽅法上
FIELD可⽤于域上
LOCAL_VARIABLE可⽤于局部变量上
PACKAGE⽤于记录java⽂件的package信息
PARAMETER可⽤于参数上
例如:
@Target(ElementType.METHOD) (这是简写)
public @interface Action()
上⾯就是他的⽤法,不过有个⽐较容易混淆的地⽅就是@interface和interface不是同⼀个东西:
@interface 不是interface,是注解类 是jdk1.5之后加⼊的,java没有给它新的关键字
,所以就⽤@interface 这么个东西表⽰了 这个注解类,就是定义⼀个可⽤的注解
,包括这个注解⽤于什么地⽅,是类,还是⽅法,还是property,还是⽅法⼊参等等
,还有这个注解是否编译后进⼊class ⽐如我们知道的⽤于javadoc的注解,是不进⼊class⽂件的。
然后在后⾯你就可以⽤这个注解写代码了。总的来说,这就是⼀个⽣成javadoc时⽤到的注释类
3.使⽤@Documented
这个注解⽤于指定被修饰的注解类将被javadoc⼯具提取成⽂档,如果定义注解类时使⽤了这个注解修饰,则所有使⽤该注解修饰的程序员苏API⽂档将会包含该注解说明。
例如:@Documentedpublic @interface Testable{}
4.使⽤@Inherited
这个注解指定被他修饰的注解将具有继承性——如果某个类使⽤了@Xxx,则其⼦类将⾃动被@Xxx修饰
5.使⽤@Result
作⽤是在同⼀个程序元素前使⽤多个相同类型的注解在java8之前只能通过@Results配置,
java8简化了它的写法例如:
@test(age=5)@test(age=8)public void resultTest(){}
6.使⽤类型注解
创建类实例new@InternedMyObject();
类型映射myString = (@NonNullString) str;
implements 语句中class UnmodifiableList<T> implements@ReadonlyList<@Readonly T> { ... }
throw exception声明void monitorTemperature() throws@CriticalTemperatureException { ... }
等等地⽅都可以⽤类型注解
新增ElementType.TYPE_USE和ElementType.TYPE_PARAMETER(在Target上)新增的两个注释的程序元素类型
ElementType.TYPE_USE 和 ElementType.TYPE_PARAMETER⽤来描述注解的新场合。ElementType.TYPE_PARAMETER 表⽰该注解能写在类型变量的声明语句中。
ElementType.TYPE_USE 表⽰该注解能写在使⽤类型的任何语句中(eg:声明语句、泛型和强制转换语句中的类型)。还是那句话,这些注解本⾝是没有意义的。要靠⾃⼰实现类型注解的检查框架,或者第三⽅,类型注解最⼤的意义在于,让编译器执⾏更严格的检查,保证代码更加的健壮。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论