深入理解注解:
1、注解,@param是参数的解释。如
/**
*@param s 这里表示对s的文字说明,描述
*//
java注解的作用
1、生成文档。这是最常见的,也是Java 最早提供的注解。常用的有@see @param @return 等
2、跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量。以后java的程序开发,最多的也将实现注解配置,具有很大用处;
3、在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
2、javadoc
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
复习一下接口的知识:
现在才是真正开始讲解注解的时候了:
1、想要真正了解注解,我们就要进入的注解的内部,注解实在jdk1.5才引入的。它是在java.lang.annotation包中
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 的字符串表示形式。 |
指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用 Documented 来注释的,则其注释将成为注释元素的公共 API 的一部分。
这里是API文档的解释。http://blog.youkuaiyun.com/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 注释,则保留策略默认为 RetentionPolicy.CLASS。
只有元注释类型直接用于注释时,Target 元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。
它的取值是一个枚举类型,取自枚举类RetentionPolicy类型。且该枚举类有三种取值,
CLASS 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。 |
RUNTIME 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。 |
SOURCE 编译器要丢弃的注释。 |
package com.lanling;
public class Test2 {
@SuppressWarnings("unused")
private int age;
public void f(){
@SuppressWarnings("unused")
String name;
}
}意思是变量未被使用的,一般情况下都可以根据意思猜出编译器要警告你什么东西。
public @interface Target,target中文是目标; 目的的意思。我猜测该注解类型是描述、声明的意思。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 {
...
}