(一):我不是注释

我们在IDE(集成开发环境,比如:Eclipse)工具中开发程序时,经常会使用自动代码生成的方式完成一些重写操作。这个时候,我们常常发现工具会在重写方法上面会自动出现一行奇怪的代码:@Override

1
2
3
4
@Override
public String toString(){
return "返回对象的字符串描述";
}

我们试着保留它,或是删掉它,结果发现这个东西对我们重写的语法似乎并没有什么影响。久而久之,大家也就习惯了它的存在,并忽略了它,甚至误认为它不是Java代码而是Eclipse自己提供的一个东东,不关Java的事情。
今天,我们来认识认识这个语法,它叫做:注解———Annotation。

Annotation的概念

我们先明确一点,Annotation(注解)是一个确定的Java语法。虽然它出现的时间较晚,在JDK1.5才被提出来,但确实是Java的亲儿子。我们来看看官方对它的描述:

An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.

翻译如下:

Annotation 是一种能够被书写到Java源代码中的元数据(metadata:描述数据的数据)形式。类、方法、变量、参数和包都可以使用它来进行描述。Annotation不会对它描述的代码操作有任何的直接影响。

通过对上文的中文仔细分析,我们可以得到如下几个重要结论:
1、Annotation是一种元数据形式。也就是说它其实是属于Java中的一种数据类型,其地位和类、接口、数组、枚举这些都是一样的;
2、Annotation是书写在Java代码中的,但是其书写的位置被固定为类、方法、变量、参数和包的申明部分(原文中be annotated 直译为 附注);
3、Annotation不会对所描述的代码有直接影响。这句话是最让初学者困惑的,因为这个时候另一个概念在脑袋里面浮现出来了,它就是注释。

Annotation不是注释

注释是作为程序员的我们非常熟悉的一个概念。它是对代码的解释和说明,其目的是让阅读代码的人能够更加轻松地了解代码。编写程序时,写程序的人给一个语句、程序段、函数等作出解释或提示,能提高程序代码的可读性。
注释,只存在于Java源代码当中,由于对于编译和运行没有任何作用,它甚至不会被编译到class文件里面。因为它就是给人看的,编译器和JVM都不需要知道它。但Annotation也是如此吗?
我们还是以@Override为例:
第一种情况:假如我们没有书写这个Annotation,然后进行错误的重写:

第二种情况:假如我们书写了Annotation,然后进行错误的重写:

这时我们马上发现:第一种方式编译器根本就不给我们报错,它会默认为我们添加了一个全新的方法,而不是在进行重写;第二种方式则会立马编译失败,并且明确告诉我们这不是一个正确的重写。这说明什么? 这说明,@Override这个Annotation可不是仅仅给人读的,它还影响到了编译器,编译器也读到了它,并且做出了相应的操作!就凭这一点,就可以断言Annotation不是注释。怪不得给它翻译了一个独特的中文名:注解,以示区分。
我们再来看看官方对它的使用范围的描述:

Annotations have a number of uses, among them:
Information for the compiler — Annotations can
be used by the compiler to detect errors or
suppress warnings.
Compile-time and deployment-time processing
Software tools can process annotation information
to generate code, XML files, and so forth.
Runtime processing — Some annotations are
available to be examined at runtime.

翻译如下:

注解有非常多的用途,包括如下:
为编译器提供信息 —— 注解可用于让编译器检测错误或抑制警告。
编译时和部署时处理 —— 软件工具可以处理注解信息从而生成代码,XML文件等等。
运行时处理 —— 一些注解可以在运行时被检查到。

厉害了,我的哥!我们可以清楚的看到,注解可不是仅仅给程序员看的,它还可以在编译期和运行期起作用,影响到编译器的编译动作或是最终的运行效果。这个时候,你还认为它和注释是一回事情吗?
那么,这么厉害的玩意儿,咋用呢?

JDK自带的常用Annotation

我们先学一下JDK中最常用的三个Annotation。它们分别是:@Override、@Deprecated和@SuppressWarnings。

@Override

这个注解我们在上面已经大量使用过了,平时也见得很多。它是专门用来限定重写父类方法。对于子类中被@Override修饰的方法,如果存在对应的被重写的父类方法,则编译通过;如果不存在,则编译报错。@Override只能作用于方法,不能作用于其他程序元素。

@Deprecated

用于表示某个程序元素(类、方法等)已过时。如果使用被@Deprecated修饰的类或方法等,编译器会发出警告。

需要注意的是:过时的类或方法并不代表错误,只是有了更好的新的替代而不再推荐使用了。

@SuppressWarnings

抑制编译器警告。指示被@SuppressWarnings修饰的程序元素(以及该程序元素中的所有子元素,例如类以及该类中的方法…..)取消显示的编译器警告。比如:
使用前

使用后

可以很明显的发现,Eclipse中黄色的警告标记不见了。其中“unused”是抑制了lst变量申明后没有被使用的警告;“rawtypes”是抑制了没有使用泛型的警告。常见的能够抑制的警告及其关键字在下表中:

关键字 被抑制的警告类型
all 抑制所有警告
deprecation 抑制使用了过时的类或方法的警告
fallthrough 抑制switch块中没有break语句的警告
finally 抑制finally块不能正常完成的警告
rawtypes 抑制没有使用泛型的警告
serial 抑制可序列化类没有使用序列化ID的警告
unchecked 抑制未检查操作的警告
unused 抑制变量或方法申明定义后未使用的警告

总结

Annotation(注解)相当于一种标记,当我们在程序代码中加入注解就相当于为程序打上了某种标记。编译器、开发工具和其他程序可以通过了解类以及类中的各种元素上有无何种标记,从而执行相应的动作。注解标记可以加在包、类,属性、方法,方法的参数以及局部变量上。

系列:
注解Annotation全解析(一):我不是注释
注解Annotation全解析(二):自定义注解的定义
注解Annotation全解析(三):自定义注解的配置使用
注解Annotation全解析(四):自定义注解的运行时解析
注解Annotation全解析(五):注解与XML的比较

坚持原创技术分享,您的支持将鼓励我继续创作!