注解是在在代码中添加的额外信息,这些信息独立于业务逻辑,能在编译期、类加载期或运行时读取利用,用于实现编译期检查、代码标记与框架配置、运行时处理等特定功能,提升代码可读性与可维护性.分为注解和类型注解.
①SOURCE 注解:仅存在于源代码中,编译时被丢弃,如@Component.
②CLASS 注解:编译时记录到 class 文件,但运行时 JVM 不保留.常用于编译期处理,如生成辅助代码等.
③RUNTIME 注解:运行时保留,可通过反射获取,如 @Component.
元注解用于注解其他注解,规定被注解注解的特性.
(1) @Retention:决定注解的生命周期,即注解在什么阶段存在.
RetentionPolicy.SOURCE:仅存在于源代码中,编译时被丢弃.
RetentionPolicy.CLASS:编译时记录到 class 文件,但运行时 JVM 不保留.
RetentionPolicy.RUNTIME:运行时保留,可通过反射获取.
(2) @Target:指定注解可以应用的目标元素类型.
ElementType.TYPE:可应用于类、接口、枚举类型.
ElementType.FIELD:用于字段.
ElementType.METHOD:用于方法.
ElementType.PARAMETER:应用于方法参数.
ElementType.CONSTRUCTOR:用于构造函数.
ElementType.LOCAL_VARIABLE:用于局部变量.
ElementType.ANNOTATION_TYPE:用于注解类型本身,即可以注解其他注解.
ElementType.PACKAGE:用于包声明
ElementType.TYPE_USE:表示注解可应用于任何使用类型的地方,如对象创建、类型转换、泛型参数等场景.
ElementType.TYPE_PARAMETER:表示可应用于类型参数,如泛型类型参数.
(3) @Documented:表示使用该注解的元素应该被包含在 Javadoc 文档中,方便其他开发者了解该元素的特殊属性或用途.
(4) @Inherited:标记的注解具有继承性,子类会自动继承该注解,但仅对类注解有效,对于类的方法、字段等元素上的注解不具备继承性.
使用 @interface 关键字定义自定义注解,可包含成员变量,使用时需为成员变量赋值(除非有默认值).
// 定义
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 MyAnnotation {
String value() default "";
int count() default 0;
}
// 使用
public class MyClass {
@MyAnnotation(value = "example", count = 10)
public void myMethod() {
// 方法实现
}
}
(1) @overwrite:用于明确子类方法重写父类方法.编译器会检查其方法签名,若与父类不匹配则抛出编译错误,以此确保方法重写的正确性.
class Shape {
public void draw() {
System.out.println("Drawing a shape");
}
}
class Circle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
(2) Deprecated:标记不建议使用的代码元素(类、方法、字段等).使用被标记元素时编译器会警告,提示其可能在未来版本移除,为代码升级维护提供指引,避免使用废弃功能.
public class MathUtils {
@Deprecated
public static int addOld(int a, int b) {
return a + b;
}
public static int add(int a, int b) {
return Integer.sum(a, b);
}
}
(3) @Nullable 和 @NonNull:@Nullable 注解表示被注解的变量、参数或返回值在运行时可能为 null,@NonNull 注解则表示被注解的元素在运行时不会为 null.用于静态分析工具在编译期检测空指针异常,大大提高代码的健壮性.
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.NonNull;
public class NullabilityExample {
public void printLength(@NonNull String str) {
System.out.println(str.length());
}
public @Nullable String getNullableString() {
return null;
}
}
①@Component:标记类为 Spring 容器组件,容器会自动扫描并实例化该类,实现依赖注入和控制反转.是@Service、@Repository和@Controller注解的通用形式.
import org.springframework.stereotype.Component;
@Component
public class UserService {
// 业务逻辑代码
}
②@Controller:用于标记控制层的类,负责接收前端传来的请求,调用业务逻辑层的服务进行处理,并将处理结果返回给前端.
③@Service:用于标记业务逻辑层的类,负责接收控制层的请求,调用数据访问层的服务进行处理,并将处理结果返回控制层.
④@Repository:用于标记数据访问层的类,用于处理数据库相关的操作,还能将数据库操作中的异常抛给上层应用来处理.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.List;
// 标记为 Spring Boot 应用的主类
@SpringBootApplication
public class SpringAnnotationsExample implements CommandLineRunner {
@Autowired
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(SpringAnnotationsExample.class, args);
}
// 服务启动后做初始化
@Override
public void run(String... args) throws Exception {
// 调用服务层方法添加用户
userService.addUser(new User("John Doe"));
System.out.println("User added successfully.");
}
}
// 定义用户实体类
class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 数据访问层,处理数据库操作
@Repository
class UserRepository {
private List users = new ArrayList<>();
public void save(User user) {
users.add(user);
}
public List findAll() {
return users;
}
}
// 业务逻辑层,调用数据访问层方法
@Service
class UserService {
@Autowired
private UserRepository userRepository;
public void addUser(User user) {
userRepository.save(user);
}
public List getAllUsers() {
return userRepository.findAll();
}
}
// 控制器层,处理 HTTP 请求
@Controller
class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
@ResponseBody
public List getUsers() {
return userService.getAllUsers();
}
}
①@Test:标记测试方法,在测试时执行,用于验证代码的逻辑.
②@Before:标记的方法在测试方法前执行,用于初始化测试环境、准备数据.
③@After:标记的方法在测试方法后执行,用于清理测试环境(如关闭连接、释放资源).
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import static org.junit.Assert.assertEquals;
public class DatabaseTest {
private Connection connection;
@Before
public void setUp() throws SQLException {
connection = DriverManager.getConnection("jdbc:sqlite:test.db");
}
@Test
public void testDatabaseOperation() throws SQLException {
// 数据库操作测试逻辑
assertEquals(1, 1);
}
@After
public void tearDown() throws SQLException {
if (connection!= null) {
connection.close();
}
}
}