Java注解(1)-基础

转载请注明本文出自远古大钟的博客(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注解

Java注解(1)-基础_第1张图片

设置注解的级别

使用@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

你可能感兴趣的:(java)