java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java的注解

Java中的注解详解(Annotation)

作者:小宝945

文章介绍了Java中的注解,包括注解的定义、元注解、Java内置的三大注解、自定义注解、反射注解以及注解的作用,注解是一种特殊的标记,可以用于类、方法、字段等元素,用于提供元数据信息

所有的注解类型都继承自 java.lang.annotation.Annotation 接口。

注解(Annotation)是一种引用数据类型。编译之后也是生成 xxx.class 文件。

一个注解准确意义上来说,只不过是一种特殊的注释而已,如果没有解析它的代码,它可能连注释都不如。

解析一个类或者方法的注解往往有两种形式

一种是编译期直接的扫描。=====> @Retention(RetentionPolicy.SOURCE)

一种是运行期反射。====> @Retention(RetentionPolicy.RUNTIME)

一、元注解

Java 中的元注解

@Target:注解的作用目标

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
	/**
 	* Returns an array of the kinds of elements an annotation interface
 	* can be applied to.
 	* @return an array of the kinds of elements an annotation interface
 	* can be applied to
 	*/
	ElementType[] value();
}

@Retention:注解的生命周期

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
   /**
 	* Returns the retention policy.
  	* @return the retention policy
	*/
	RetentionPolicy value();
}

@Documented:注解是否应当被包含在 JavaDoc 文档中

@Inherited:是否允许子类继承该注解

二、Java 中内置的三大注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

它没有任何的属性,所以并不能存储任何其他信息。它只能作用于方法之上,编译结束后将被丢弃。

仅被编译器可知,编译器在对 java 文件进行编译成字节码的过程中,一旦检测到某个方法上被修饰了该注解,就会去匹对父类中是否具有一个同样方法签名的函数,如果不是,自然不能通过编译。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
    String since() default "";
    boolean forRemoval() default false;
}

可以修饰所有的类型,作用是,标记当前的类或者方法或者字段等已经不再被推荐使用了,可能下一次的 JDK 版本就会删除。

三、自定义注解

语法格式:

[修饰符列表] @interface 注解类型名{
	类型 属性() [defauult 值];
}
// 样例
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String name() default "gdb";
    String[] phoneNumbers() default {};
}

注解当中的属性类型可以是:byte short int long float double boolean char String Class 枚举类型以及以上每一种的数组形式。

四、反射注解

要求必须使用 @Retention(RetentionPolicy.RUNTIME),这样该注解才能够被反射到。

例子:反射类上的 @MyAnnotation 注解。

package annotation1;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String name() default "gdb";
    String[] phoneNumbers() default {};
}	
package annotation1;

@MyAnnotation(name = "zhangsan", phoneNumbers = {"123456", "654321"})
public class MyAnnotationTest {

}
package annotation1;

import java.util.Arrays;

public class ReflectAnnotation {
    public static void main(String[] args) throws Exception {
        //获取类
        Class<?> c = Class.forName("annotation1.MyAnnotationTest");
        //判断类上面是否有 @MyAnnotation
        if (c.isAnnotationPresent(MyAnnotation.class)){
            //获取注解对象
            MyAnnotation myAnnotation = (MyAnnotation)c.getAnnotation(MyAnnotation.class);
            //获取注解对象的属性和调用接口没有区别
            System.out.println(myAnnotation.name() + ", " + Arrays.toString(myAnnotation.phoneNumbers()));
        }
        //判断 Date 类上面是否有 @MyAnnotation 这个注解。
        Class<?> s = Class.forName("java.lang.String");
        System.out.println(s.isAnnotationPresent(MyAnnotation.class));
    }
}

五、注解的作用

注解在程序当中等同于一种标记,如果这个元素上有这个注解怎么办,没有这个注解怎么办。

应用场景:假设有这样一个注解,叫做 @Id,这个注解只能出现在类上面,当这个类上有这个注解的时候,要求这个类中必须有一个 int 类型的 id 属性。如果没有这个属性就报异常。如果有这个属性就正常执行。

package annotation1;

public class NotHasIdException extends RuntimeException{
    public NotHasIdException() {
    }

    public NotHasIdException(String message) {
        super(message);
    }
}
package annotation1;

public class NotHasIdException extends RuntimeException{
    public NotHasIdException() {
    }

    public NotHasIdException(String message) {
        super(message);
    }
}
package annotation1;

@Id
public class IdAnnotationTest {
    int id;
}
package annotation1;

import java.lang.reflect.Field;

public class ReflectAnnotation {
    public static void main(String[] args) throws Exception {
        //获取类
        Class<?> c = Class.forName("annotation1.IdAnnotationTest");
        //判断类上面是否有 @Id 注解
        if (c.isAnnotationPresent(Id.class)){
            //当一个类上面有 @Id 注解的时候,要求类中必须存在 int 类型的id属性。
            //如果没有int类型的id属性则报异常。
            //获取类的所有属性
            Field[] fields = c.getDeclaredFields();
            boolean isOK = false;
            for(Field field : fields){
                if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){
                    isOK = true;
                    break;
                }
            }
            //判断是否合法
            if (!isOK)
                throw new NotHasIdException("被@Id注解标注的类没有int类型的id属性!!!");
        }
    }
}

六、总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文