深入理解注解:
http://www.cnblogs.com/whoislcj/p/5671622.html(关于JAVA注解深入解析。)
1、注解,@param是参数的解释。如
/**
*@param s 这里表示对s的文字说明,描述
*//
java注解的作用
1、生成文档。这是最常见的,也是Java 最早提供的注解。常用的有@see @param @return 等
2、跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量。以后java的程序开发,最多的也将实现注解配置,具有很大用处;
3、在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
2、javadoc
javadoc是Sun公司提供的一个技术,它从程序
源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档。也就是说,只要在编写程序时以一套特定的标签作注释,在程序编写完成后,通过Javadoc就可以同时形成程序的开发文档了。
javadoc命令是用来生成自己
API文档的,使用方式:使用命令行在目标文件所在目录输入javadoc +文件名.java。
实验一下:
在命令提示符中敲下: javadoc HelloWorld.java(我这里只是句HelloWorld.java这个例子。)
http://88250.b3log.org/when-the-little-things-count-javadoc(讲的那个关于注解的,反正我没听太懂)
default关键字
http://blog.csdn.net/lin6286878/article/details/53464804(深入解析default关键字。)
(1)public:可以被所有其他类所访问。
(2)private:只能被自己访问和修改。
(3)protected:自身,子类及同一个包中类可以访问。
(4)default(默认):同一包中的类可以访问,声明时没有加修饰符,认为是friendly。
我们知道default关键字可以修饰修饰一个接口中的方法,让这个方法有方法体
然后实现类如果想继承重写就重写,不想重写也无所谓。
interface T {
public void f();
public default void m(){
System.out.println("haha");
}
}
interface TTT extends T{
}
public class Test5 implements T {
@Override
public void f() {
}
public static void main(String[] args) {
Test5 t=new Test5();
t.m();
}
}
输出结果为:haha
复习一下接口的知识:
https://www.runoob.com/java/java-interfaces.html(还算详细,捡重点看,不重要的可以跳过去了。)
现在才是真正开始讲解注解的时候了:
1、想要真正了解注解,我们就要进入的注解的内部,注解实在jdk1.5才引入的。它是在java.lang.annotation包中
从该图中我们可以看出该包中使用的java.lang包中的一些类和接口,在定义里面一些注解起到了不可忽视的作用。
2、接下来我们就开始正式进入到java.lang.annotation包中了。
3、当我们进入包中后,我们现在开始进入到Annotation这个接口中去真正的了解一下这些注解。
Class<? extendsAnnotation> | annotationType() 返回此 annotation 的注释类型。 |
boolean | equals(Object obj) 如果指定的对象表示在逻辑上等效于此接口的注释,则返回 true。 |
int | hashCode() 返回此 annotation 的哈希码,具体说明如下: 一个 annotation 的哈希码是其成员(包括那些带有默认值的成员)的哈希码的和,具体说明如下: annotation 成员的哈希码是成员值哈希码的 XOR(它是 String.hashCode() 计算得到的成员名哈希码的 127 倍),具体说明如下: 成员值的哈希码取决于其类型: 基值v 的哈希码等于 WrapperType.valueOf(v).hashCode(),其中WrapperType 是对应v 的基本类型的包装器类型(Byte 、Character 、Double 、Float 、Integer 、Long 、Short 或 Boolean )。 |
String | toString() 返回此 annotation 的字符串表示形式。 |
这是该接口的一些方法,那么该接口的所有实现类(也就是各种注解类型)都有该方法
先就让我们一起走进Annotation接口的实现类。
Deprecated,
Documented,
Inherited, Override,
Retention, SuppressWarnings,
Target
其中四种比较常用也是比较重要的注解我将它们用蓝色给标记出来了。
首先来看一下第一个Deprecated这个实现类,也是这个注解类型。
public @interface Deprecated,deprecated中文是
不赞成,反对的意思。
用 @Deprecated 注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器会发出警告。
总结:不鼓励程序员这样使用。了解一下就可以了。这是因为有时程序员使用了一些类的成员或是方法中会提示这样的注解,这是编译器在警告你,这个类成员或是方法在将来的jdk版本中可能会删除,不推荐使用,之所以现在还在使用,是因为要给那些已经使用了这些类成员或是方法的成员有一个缓冲期。
接下来我们就要分析一下第二个注解类型了-----Documented
public @interface Documented,Documented中文意思是备有证明文件的。
指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用 Documented 来注释的,则其注释将成为注释元素的公共 API 的一部分。
这里是API文档的解释。
本来javadoc是不包括注解的,但是指定了这样一个注解类型的话,表示该注解也会被javadoc之类的工具处理。
(
javadoc命令是用来生成自己API文档的,使用方式:在dos中在目标文件所在目录输入javadoc +文件名.java。
javadoc是Sun公司提供的一个技术,它从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档。也就是说,只要在编写程序时以一套特定的标签作注释,在程序编写完成后,通过Javadoc就可以同时形成程序的开发文档了。
)
然后我们再来分析一下Inherited这个注解类型。
public @interface Inherited,中文意思是通过继承得到的,遗传的; 继承权的
指示注释类型被自动继承。如果在注释类型声明中存在 Inherited 元注释,并且用户在某一类声明中查询该注释类型,同时该类声明中没有此类型的注释,则将在该类的超类中自动查询该注释类型。此过程会重复进行,直到找到此类型的注释或到达了该类层次结构的顶层 (Object) 为止。如果没有超类具有该类型的注释,则查询将指示当前类没有这样的注释。
http://blog.csdn.net/snow_crazy/article/details/39381695(开完我只是感觉人类好复杂啊)
下面介绍Override注解类型
public @interface Override
http://blog.csdn.net/snow_crazy/article/details/39381695(开完我只是感觉人类好复杂啊)
package com.lanling;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
@Retention(RUNTIME)
@Inherited
public @interface InheritedTest {
//String value();
String value();
}
package com.lanling;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
@Retention(RUNTIME)
public @interface InheritedTest2 {
String value();
}
package com.lanling;
@InheritedTest("使用Inherited的注解 class")
@InheritedTest2("未使用Inherited的注解class")
public class Parent {
@InheritedTest("使用Inherited的注解 method")
@InheritedTest2("未使用Inherited的注解 method")
public void method(){
}
@InheritedTest("使用Inherited的注解 method2")
@InheritedTest2("未使用Inherited的注解 method2")
public void method2(){
}
@InheritedTest("使用Inherited的注解 field")
@InheritedTest2("未使用Inherited的注解 field")
public String a;
}
package com.lanling;
public class Child extends Parent {
@Override
@InheritedTest("zilei")
public void method(){
}
}
package com.lanling;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, NoSuchFieldException {
//@SuppressWarnings("unused")
Class<Child> clzz=Child.class;
//对类进行测试
System.out.println("对类进行测试");
if(clzz.isAnnotationPresent(InheritedTest.class)){
System.out.println(clzz.getAnnotation(InheritedTest.class).value());
}
if(clzz.isAnnotationPresent(InheritedTest2.class)){
System.out.println(clzz.getAnnotation(InheritedTest2.class).value());
}
System.out.println();
System.out.println("对方法进行测试");
//@SuppressWarnings("unused")
Method method1=clzz.getMethod("method", null);
if(method1.isAnnotationPresent(InheritedTest.class)){
System.out.println(method1.getAnnotation(InheritedTest.class).value());
}
if(method1.isAnnotationPresent(InheritedTest2.class)){
System.out.println(method1.getAnnotation(InheritedTest2.class).value());
}
System.out.println();
System.out.println("对方法2进行测试");
//@SuppressWarnings("unused")
Method method2=clzz.getMethod("method2", null);
if(method2.isAnnotationPresent(InheritedTest.class)){
System.out.println(method2.getAnnotation(InheritedTest.class).value());
}
if(method2.isAnnotationPresent(InheritedTest2.class)){
System.out.println(method2.getAnnotation(InheritedTest2.class).value());
}
System.out.println();
System.out.println("对属性进行测试");
Field field=clzz.getField("a");
if(field.isAnnotationPresent(InheritedTest.class)){
System.out.println(field.getAnnotation(InheritedTest.class).value());
}
if(field.isAnnotationPresent(InheritedTest2.class)){
System.out.println(field.getAnnotation(InheritedTest2.class).value());
}
}
}
下面介绍Override注解类型
public @interface Override
表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。
接下来就是一个非常重要的注解类型了。叫做Retention。
接下来就是一个非常重要的注解类型了。叫做Retention。
public @interface Retention
指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。
只有元注释类型直接用于注释时,Target 元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。
它的取值是一个枚举类型,取自枚举类RetentionPolicy类型。且该枚举类有三种取值,
指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。
只有元注释类型直接用于注释时,Target 元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。
它的取值是一个枚举类型,取自枚举类RetentionPolicy类型。且该枚举类有三种取值,
CLASS 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。 |
RUNTIME 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。 |
SOURCE 编译器要丢弃的注释。 |
(其中VM就是JVM,java虚拟机的意思。)
public @interface SuppressWarnings
顾名思义,是编译器在警告你的意思。
指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。
package com.lanling;
public class Test2 {
@SuppressWarnings("unused")
private int age;
public void f(){
@SuppressWarnings("unused")
String name;
}
}意思是变量未被使用的,一般情况下都可以根据意思猜出编译器要警告你什么东西。
public @interface Target,target中文是目标; 目的的意思。我猜测该注解类型是描述、声明的意思。
取自来自ElementType枚举类型,该枚举类型的取值一共有八种。
ANNOTATION_TYPE 注释类型声明 |
CONSTRUCTOR 构造方法声明 |
FIELD 字段声明(包括枚举常量) |
LOCAL_VARIABLE 局部变量声明 |
METHOD 方法声明 |
PACKAGE 包声明 |
PARAMETER 参数声明 |
TYPE 类、接口(包括注释类型)或枚举声明 |
@Target(ElementType.ANNOTATION_TYPE)
public @interface MetaAnnotationType {
...
}
这是一个编译时错误,它表明一个 ElementType 常量在 Target 注释中出现了不只一次。例如,以下元注释是非法的:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
public @interface Bogus {
...
}