java注解入门

java注解入门

定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

作用分类:

①编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】

②代码分析:通过代码里标识的元数据对代码进行分析【使用反射】

③编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】

——参考《百度百科》

PS:注释是给人看的,注解是给计算机看的。

JDK提供的三个注解

@Override

JDK5中,它的作用是对覆盖超类中方法的方法进行标记,如果被标记的方法并没有实际覆盖超类中的方法,则编译器会发出错误警告,JDK6之后还可以表示实现接口的方法。

public class OverrideTest {
    @Override
    public String tostring() {
        return "test";
    }
}

@Deprecated

表示被修饰的方法已经过时。 过时的方法不建议使用, 但仍可以使用。一般被标记位过时的方法都存在不同的缺陷: 1安全问题; 2新的API取代。

public class DeprecatedDemoTest {
    public static void main(String[]args) {
        // 使用DeprecatedClass里声明被过时的方法
        DeprecatedClass.DeprecatedMethod();
    }
}

class DeprecatedClass {
    @Deprecated
    public static void DeprecatedMethod() {
    }
}

@SuppressWarnings

表示抑制警告, 被修饰的类或方法如果存在编译警告, 将被编译器忽略

参数

deprecation , 忽略过时
rawtypes , 忽略类型安全
unused , 忽略不使用
unchecked , 忽略安全检查
null, 忽略空指针
all, 忽略所有

import java.util.ArrayList;
import java.util.List;
public class SuppressWarningsDemoTest {
    public static Listlist = newArrayList();
    @SuppressWarnings("unchecked")
    public void add(Stringdata) {
        list.add(data);
    }
}

自定义注解

基本格式

public @interface Annotation1 {
    属性1;
    属性2;
    ......
}

属性格式

修饰符 返回值类型 属性名() [default默认值]

  1. 修饰符:默认值public abstract , 且只能是public abstract。
  2. 返回值类型: 基本类型、 字符串String、Class、 注解、 枚举, 以及以上类型的一维数组
  3. 属性名:自定义
  4. default默认值:可以省略
案例
自定义注解@Annotation1
package com.pc.annotation;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Annotation1 {
    // 基本类型,默认值为1
    int basic() default 1;

    // String类型,默认值为"string"
    String str() default "string";

    // Class类型
    Class<?> clazz();

    // 枚举类型
    Sex sex();

    // 注解类型
    MyTest test();

    // 数组类型
    String[] name();
}
package com.pc.annotation;

public enum Sex {
    Man, Woman
}
测试自定义注解
package com.pc.annotation;

/**
 * 测试Annotation
 * 
 * @author Switch
 * @data 2016年10月25日
 * @version V1.0
 */
public class TestAnnotation {
    @Annotation1(basic = 2, clazz = TestAnnotation.class, sex = Sex.Man, test = @MyTest, name = { "zs", "ls" })
    public void test1() {

    }
}
注解属性使用的注意事项:
  • 注解可以没有属性, 如果有属性需要使用小括号括住。 例如: @Annotation1@Annotation1()

  • 属性格式: 属性名=属性值, 多个属性使用逗号分隔。 例如: @Annotation1(username="Switch")

    • 如果属性名为 value, 且当前只有一个属性, value 可以省略,例如:@Annotation1("Switch")
  • 如果使用多个属性时, 属性名名称为 value的不能省略

  • 如果属性类型为数组, 设置内容格式为: { 1,2,3 }。 例如: names = {"Switch","Kity"}

  • 如果属性类型为数组, 值只有一个{ }可以省略的。 例如: names = "Switch"

  • 一个对象上, 注解只能使用一次,不能重复使用。

元注解

元注解:用于修饰注解的注解。(用于修饰自定义注解的JDK提供的注解)
JDK提供4种元注解:@Retention@Target@Documented@Inherited

@Retention用于确定被修饰的自定义注解生命周期

编译器的处理有三种策略:

  • RetentionPolicy.SOURCE被修饰的注解只能存在源码中,字节码class没有。用途:提供给编译器使用。
  • RetentionPolicy.CLASS被修饰的注解只能存在源码和字节码中,运行时内存中没有。用途:java虚拟机使用
  • RetentionPolicy.RUNTIME被修饰的注解存在源码、字节码、内存(运行时)。用途:取代xml配置
public enum RetentionPolicy {
    // 此类型会被编译器丢弃
    SOURCE,
    // 此类型注解会保留在class文件中,但JVM会忽略它
    CLASS,
    // 此类型注解会保留在class文件中,JVM会读取它
    RUNTIME
}
// 让保持性策略为运行时态,即将注解编码到class文件中,让虚拟机读取
@Retention(RetentionPolicy.RUNTIME)
public @interface Greeting {
    // 使用枚举类型
    public enum FontColor {
        BLUE,RED,GREEN
    };
    String name();
    FontColor fontColor() default FontColor.RED;
}
@Target用于确定被修饰的自定义注解的使用位置

编译器的修饰位置有八种:

  • ElementType.TYPE修饰类 、接口
  • ElementType.METHOD修饰方法
  • ElementType.FIELD修饰字段
  • ElementType.PARAMETER修饰方法参数
  • ElementType.CONSTRUCTOR修饰构造
  • ElementType.LOCAL_VARIABLE修饰本地变量或catch语句
  • ElementType.ANNOTATION_TYPE修饰注解类型
  • ElementType.PACKAGE修饰java包
public enum ElementType {
    // 用于类,接口,枚举但不能是注解
    TYPE,
    // 字段上,包括枚举值
    FIELD,
    // 方法,不包括构造方法
    METHOD,
    // 方法的参数
    PARAMETER,
    // 构造方法
    CONSTRUCTOR,
    // 本地变量或catch语句
    LOCAL_VARIABLE,
    // 注解类型(无数据)
    ANNOTATION_TYPE,
    // Java包
    PACKAGE
}
// 限制注解使用范围
@Target({ElementType.METHOD,ElementType.CONSTRUCTOR})
public @interface Greeting {
    // 使用枚举类型
    public enum FontColor {
        BLUE,RED,GREEN
    };
    String name();
    FontColor fontColor() default FontColor.RED;
}
@Documented

使用javaDoc生成api文档时,是否包含此注解。

// 让它定制文档化功能
// 使用此注解时必须设置RetentionPolicy为RUNTIME
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Greeting {
    // 使用枚举类型
    public enum FontColor {
        BLUE,RED,GREEN
    };
    String name();
    FontColor fontColor() default FontColor.RED;
}
@Inherited

如果父类使用被修饰的注解,子类是否继承。

// 让它允许继承,可作用到子类
@Inherited
public @interface Greeting {
    // 使用枚举类型
    public enum FontColor {
        BLUE,RED,GREEN
    };
    String name();
    FontColor fontColor() default FontColor.RED;
}

自定义注解解析AnnotatedElement

如果给类、方法等添加注解,如果需要获得注解上设置的数据, 那么就必须对注解进行解析,JDK提供了java.lang.reflect.AnnotatedElement接口允许在运行时通过反射获得注解。

常用方法
  • boolean isAnnotationPresent(Class annotationClass)当前对象是否有注解
  • T getAnnotation(Class<T> annotationClass)获得当前对象上指定的注解
  • Annotation[] getAnnotations()获得当前对象及其从父类上继承的,所有的注解
  • Annotation[] getDeclaredAnnotations()获得当前对象上所有的注解
Class<TestAnnotation> clazz = TestAnnotation.class;
// 创建实例
TestAnnotation annotation = clazz.newInstance();
// 获取所有方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
    // 如果存在"MyTest"注解,则调用该方法
    if (method.isAnnotationPresent(MyTest.class)) {
        method.invoke(annotation, null);
    }
}

案例:模拟JUnit,@Test注解

MyTest
package com.pc.annotation;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTest {

}
TestAnnotation
package com.pc.annotation;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTest {

}

package com.pc.annotation;

import java.lang.reflect.Method;

/**
 * 测试Annotation
 * 
 * @author Switch
 * @data 2016年10月25日
 * @version V1.0
 */
public class TestAnnotation {
    public static void main(String[] args) throws Exception {
        // 模拟@Test注解
        // 获取当前类的Class对象
        Class<TestAnnotation> clazz = TestAnnotation.class;
        // 创建实例
        TestAnnotation annotation = clazz.newInstance();
        // 获取所有方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            // 如果存在"MyTest"注解,则调用该方法
            if (method.isAnnotationPresent(MyTest.class)) {
                method.invoke(annotation, null);
            }
        }
    }

    @MyTest
    public void test2() {
        System.out.println("test2");
    }

    @MyTest
    public void test3() {
        System.out.println("test3");
    }

    @MyTest
    public void test4() {
        System.out.println("test4");
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值