Java注解是一种用于为代码添加元数据的机制,它能够被编译器、开发工具或其他代码读取和处理,主要分为自定义注解、内置注解和元注解三类。 以下从自定义注解、内置注解、元注解三个方面进行详细介绍:
自定义注解自定义注解是通过@interface关键字定义的,开发者可以根据需求创建特定功能的注解。
- 定义注解:使用@interface声明注解,并通过元注解指定其保留策略和作用目标。例如,以下代码定义了一个名为Kevin的注解,该注解有一个默认值为"kevin"的name属性,且保留策略为RUNTIME(运行时保留):
package com.kevin.annotation;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)public @interface Kevin { String name() default "kevin";}- 解析并测试注解:通过反射机制在运行时解析注解信息。以下代码展示了如何检查类上是否存在Kevin注解,并获取其属性值:
package com.kevin;import com.kevin.annotation.Kevin;@Kevinpublic class Test { public static void showKevin(Class c) { System.out.println(c.getName()); boolean isExist = c.isAnnotationPresent(Kevin.class); if (isExist) { Kevin kevin = (Kevin) c.getAnnotation(Kevin.class); System.out.println(kevin.name()); } } public static void main(String[] args) { Test.showKevin(Test.class); }}- 运行结果:程序输出类名com.kevin.Test和注解属性值kevin,表明注解定义和解析成功。
内置注解Java提供了一些内置注解,用于常见场景的标记和处理。
- @Override:用于标记子类中重写父类的方法,编译器会检查该方法是否确实重写了父类方法,若未重写则报错。例如:
package com.kevin.demo;public class Demo1 { @Override public String toString() { return "demo1"; }}- @Deprecated:标记已过时的代码(如类、方法、字段等),编译器会发出警告,但允许继续使用。例如:
package com.kevin.demo;public class Demo1 { @Deprecated public void goHome() { System.out.println("过时的方法"); }}- @SuppressWarnings:用于压制编译器警告,需指定警告类型(如"deprecation")。例如:
@SuppressWarnings("deprecation")public static void main(String[] args) { Demo1 demo1 = new Demo1(); demo1.goHome();}- 常见警告类型:
all:抑制所有警告。
boxing:抑制装箱/拆箱操作警告。
cast:抑制类型转换警告。
deprecation:抑制使用过时方法的警告。
unchecked:抑制未检查操作警告。
unused:抑制未使用代码警告。
元注解元注解是用于修饰其他注解的注解,Java提供了以下几种元注解:
- @Target:指定注解的作用目标,取值来自ElementType枚举,包括:
TYPE:类、接口或枚举声明。
FIELD:字段(包括枚举常量)。
METHOD:方法。
PARAMETER:方法参数。
CONSTRUCTOR:构造方法。
LOCAL_VARIABLE:本地变量。
ANNOTATION_TYPE:注解类型。
PACKAGE:包。
若未声明@Target,默认适用于所有类型。例如,@Override的@Target为ElementType.METHOD,表示仅适用于方法。
- @Retention:指定注解的保留策略,取值来自RetentionPolicy枚举,包括:
SOURCE:仅保留在源代码中,编译时丢弃。
CLASS:保留到字节码文件,但JVM加载时不一定保留(默认策略)。
RUNTIME:保留到运行时,可通过反射读取。
例如,@Override和@SuppressWarnings的@Retention为SOURCE,因为它们仅供编译器使用。
- @Documented:标记注解是否包含在Javadoc生成的API文档中,无成员属性。例如:
@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public @interface Documented {}- @Inherited:标记注解是否可被子类继承。若父类注解有@Inherited,子类会自动继承该注解。例如:
public class Demo1 { @Inherited @Retention(RetentionPolicy.RUNTIME) static @interface Test { } @Test static class Base { } static class Child extends Base { } public static void main(String[] args) { System.out.println(Child.class.isAnnotationPresent(Test.class)); // 输出true }}若去掉@Inherited,输出结果为false。