转载请注明本文出自远古大钟的博客(http://blog.csdn.net/duo2005duo),谢谢支持!
简介
注解(annotation)是JDK5之后引进的新特性,是一种特殊的注释,之所以说它特殊是因为不同于普通注释(comment)能存在于源码,而且还能存在编译期跟运行期,会最终编译成一个.class文件,所以注解能有比普通注释更多的功能
使用Java自带的注解
这里只讲Java5 自带的3种注解
- @Deprecated 表明当前的元素已经不推荐使用
/**
* 一般来说使用@Deprecated注解的方法要加上一下的javadoc文档
* @deprecated 这里要写明因为什么原因抛弃了使用该方法,推荐使用什么方法代替
*/
@Deprecated
public void badMethod(){ //已经不推荐使用的方法
...
}
- @Override 表明当前方法是覆盖了父类方法,添加@Overrride是一种必须的编程习惯,因为帮助你找到代码中的错误,考虑以下情况
abstract class Fruit{
protected void showOnTheDesk(){
...
}
}
class Apple implements Fruit{
@Override
public void showInTheDesk(){ //编译报错,看出来没有?父类是On不是In!
...
}
}
以上代码在编译时报错the showInTheDesk() must oerride or implement a supertype method
,所以@Override帮助你避免写错方法名
- @SuppressWarnings 关闭不当的编译器警告信息,如下
class A{
final void doSth(){
//添加说明抑制警告的原因:A的getClass() 必然是Class<A>
@SuppressWarnings(unchecked)
Class<A> a=(Class<A>)getClass() //有unchecked警告
...
}
}
自定义注解
简单声明
注解的声明相对简单,有点类似接口的写法
@interface Empty{
String field1() default "it's empty"; //default 设置默认值
}
@Empty //使用 default默认值"it's empty"
class C{
}
//如果没有使用default设置默认值的话,field必须显式传入参数,如下
@Empty(field1="empty A")
class A{
}
@interface Value{
String value();
String other() default "it's great";
}
@Value("empty B") //当注解有一个方法value时,没有其他方法或者其他方法有默认值,不需要指明具体方法
class B{
}
以上是Java自带的一些注解,Java同时提供了另外一类注解,叫元注解。元注解可以用来设置注解,自定义注解一般都会使用到元注解
元注解
‘普通注解’只能用来注解’代码’,而’元注解’只能用来注解 ‘普通注解’。
JDK5时支持的元注解有@Documented @Retention @Target @Inherited,接下来分别介绍它们修饰注解的效果
让注解自动加入Javadoc
@Documented 被修饰的注解会生成到javadoc中
@Documented
@interface DocumentedAnnotation{
}
@interface UnDocumentedAnnotation{
}
@DocumentedAnnotation
@UnDocumentedAnnotation
class A{}
代码中注解DocumentedAnnotation添加了元注解@Documented,而UnDocumentedAnnotation则没有添加,通过'javadoc A.java'命令生成Javadoc如下图。可以看到,在A类的Javadoc中只能看到@DocumentedAnnotation注解,但是无法看到@UnDocumentedAnnotation注解
设置注解的级别
使用@Retention可以设置注解的级别
//RetentionPolicy是一个枚举类,默认是CLASS,此外还可选择SOURCE,RUNTIME
@Retention(RetentionPolicy.CLASS)
@interface ClassRetentionAnnotation{}
按照Retention的三种枚举类型,注解分为三种级别,每个级别有其特定的功能
- SOURCE代表源码级别,注解只存在源码中,其功能是与编译器交互,用于代码检测,如@Override,@SuppressWarings,许多框架如Dragger就是使用这个级别的注解,这个级别的框架额外效率损耗发生在编译时
- CLASS代表字节码级别,注解存在源码与字节码文件中,主要用于编译时生成而外的文件,如XML,Java文件等,这个级别需要添加JVM加载时候的代理(javaagent ),使用代理来动态修改字节码文件(由于Android虚拟机并不支持所以本专题不会再做介绍,在Android中可以使用aspectJ来实现类似这个级别的功能)
- RUNTIME代表运行时级别,注解存在源码,字节码与Java虚拟机中,主要用于运行时反射获取相关信息,许多框架如OrmLite就是使用这个级别的注解,这个级别的框架额外的效率损耗发生在程序运行时
限制注解的元素种类
不加元注解@Target的情况下,注解可以修饰各种元素,比如可以修饰类,可以修饰变量,可以修饰方法等,但是如果要限制注解的元素种类,比如限制只能修饰方法,则需要加入@Target,一下是@Override的源码
@Target(ElementType.METHOD) //限制了注解只能修饰方法,ElementType是一个枚举类
@Retention(RetentionPolicy.SOURCE)
public @interface Override{
}
可以看到@Override源码中已经限定了只能修饰方法。
让注解可以被继承
@Inherited可以让注解类似被继承一样,但是这并不是真的继承。通过使用@Inherited,只可以让子类类对象使用getAnnotations()反射获取父类被@Inherited修饰的注解。
@Inherited
@Retention(RetentionPolicy.Runtime)
@interface Inheritable{
}
@interface UnInheritable{
}
public class Test{
@UnInheritable
@Inheritable
public static class Super{
}
public static class Sub extends Super {
}
public static void main(String... args){
Super instance=new Sub();
System.out.println(Arrays.toString(instance.getClass().getAnnotations()));
}
}
输出:[Inheritable]
因为这种伪继承机制,被@Documented与@Inherited同时修饰的注解来注解某个类,其子类Javadoc并不会出现这个注解的提示,可以使用Javadoc命令执行以上代码,结果如下:
后续
自定义注解可以搭建框架,如何使用自定义注解搭建框架,后续将分Runtime级别跟Source级别介绍
Java注解(2)-运行时框架
Java注解(3)-源码级框架
附录
IDE会有提示,所以作为附录
SuppressWarning参数:
- all to suppress all warnings
- boxing to suppress warnings relative to boxing/unboxing operations
- cast to suppress warnings relative to cast operations
- dep-ann to suppress warnings relative to deprecated annotation
- deprecation to suppress warnings relative to deprecation
- fallthrough to suppress warnings relative to missing breaks in switch statements
- finally to suppress warnings relative to finally block that don’t return
- hiding to suppress warnings relative to locals that hide variable
- incomplete-switch to suppress warnings relative to missing entries in a switch statement (enum case)
- nls to suppress warnings relative to non-nls string literals
- null to suppress warnings relative to null analysis
- rawtypes to suppress warnings relative to un-specific types when using generics on class params
- restriction to suppress warnings relative to usage of discouraged or forbidden references
- serial to suppress warnings relative to missing serialVersionUID field for a serializable class
- static-access to suppress warnings relative to incorrect static access
- synthetic-access to suppress warnings relative to unoptimized access from inner classes
- unchecked to suppress warnings relative to unchecked operations
- unqualified-field-access to suppress warnings relative to field access unqualified
- unused to suppress warnings relative to unused code