计算机系统应用教程网站

网站首页 > 技术文章 正文

分享几个Lombok中不常用但很实用的注解

btikc 2024-11-04 12:21:39 技术文章 1 ℃ 0 评论

虽然许多 Java 开发人员熟悉 Lombok 的常用注解,例如@Getter@Setter@ToString,但还有大量鲜为人知的注解可以进一步简化我们的开发工作。在这篇文章中,将介绍一些不常用但很实用的Lombok注解。

  • @Delegate

考虑这样一个场景,当有一个类Person和另一个类PersonHelperPersonHelper提供了用于处理Person对象的各种实用方法。现在可以使用 Lombok 的@Delegate注解自动生成这些方法,而不需要在Person类中手动创建。

示例代码:

import lombok.experimental.Delegate;

public class Person {
    @Delegate
    private final PersonHelper helper = new PersonHelper();

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // Other custom methods for the Person class
}

class PersonHelper {
    public void sayHello() {
        System.out.println("Hello!");
    }

    public void sayAge(int age) {
        System.out.println("I am " + age + " years old.");
    }
}

在这个例子中:

  • 我们有一个Person的类带有nameage字段。
  • 我们还有一个PersonHelper类,其中包含与 Person相关的操作的方法。
  • 我们用@Delegate 注解Person类中的helper字段。这告诉 Lombok 在Person类中生成PersonHelperPerson的所有公共方法。
  • 因此,无需编写任何额外的代码,类Person将具PersonHelper有.sayAge(int age)sayHello()方法。

在Person类中直接使用这些方法:

public class Main {
    public static void main(String[] args) {
        Person person = new Person("John", 30);
        
        person.sayHello();  // Delegated call to PersonHelper's sayHello()
        person.sayAge(person.getAge());  // Delegated call to PersonHelper's sayAge()
    }
}

这种方法有助于保持Person类的整洁并专注于其主要职责,同时允许调用PersonHelper提供的方法而无需显式实现。当有一个实用程序类包含一组方法并且希望通过另一个类公开这些方法而无需手动编写包装器方法时,@Delegate 注解特别有用。

  • @Cleanup

@Cleanup注解有助于 Java中资源的自动清理,特别是需要显式关闭的资源,例如流、数据库连接或文件。即使存在异常,它也可以确保资源得到正确释放,而无需显式finally块。

示例代码:

import lombok.Cleanup;

import java.io.*;

public class FileCopyExample {

    public static void main(String[] args) throws IOException {
        String sourceFile = "source.txt";
        String destFile = "destination.txt";
        copyFile(sourceFile, destFile);
    }

    public static void copyFile(String sourceFile, String destFile) throws IOException {
        @Cleanup FileInputStream in = new FileInputStream(sourceFile); // Automatically closed after leaving scope
        @Cleanup FileOutputStream out = new FileOutputStream(destFile); // Automatically closed after leaving scope

        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
    }
}

在这个例子中:

  1. 定义一个copyFile方法,将源文件和目标文件路径作为参数。
  2. copyFile方法内部:
  • 声明FileInputStreamFileOutputStream变量,并使用@Cleanup注解。当这些变量超出范围时将自动关闭。
  • 我们创建一个缓冲区来读取和写入文件的内容。
  • 我们从输入流中读取并写入输出流,直到到达文件末尾。

4. 在main方法中,调用copyFile方法,传入源文件路径和目标文件路径。

通过@Cleanup注解,我们不需要使用finally块手动关闭流。 Lombok 负责添加必要的清理代码,使我们的代码更干净且不易出错。

值得注意的是,@Cleanup注解不仅限于流。它可以与实现java.lang.AutoCloseable接口的任何资源一起使用,其中包括许多 IO 和 JDBC 类。在使用@Cleanup可能在关闭期间引发异常的资源时必须小心谨慎,因为默认情况下 Lombok 会默默地处理这些异常。

  • @Value

@Value注解用于在 Java 中创建不可变对象。不可变对象是指在创建对象后其状态(对象的数据)无法修改的对象。它们具有多种优点,例如线程安全性防止意外修改引起的错误。

示例代码:

import lombok.Value;

@Value
public class ImmutablePerson {
    String name;
    int age;
}

在这个例子中:

  • 有一个ImmutablePerson的类带有@Value注解。
  • 我们定义两个字段:nameage
  • @Value注释为我们做了几件事:
  • 构造函数:一个构造函数,它接受所有字段的参数并初始化对象。
  • Getters:所有字段的 Getter 方法。
  • equals():比较对象字段是否相等的equals()方法实现。
  • hashCode():根据对象字段生成哈希码的hashCode()方法实现。
  • toString():返回对象状态的字符串表示形式的toString()方法。

通过@Value注解,ImmutablePerson类实际上变得不可变。对象一旦ImmutablePerson创建,其状态就无法修改。让我们看看如何使用它:

public class Main {
    public static void main(String[] args) {
        ImmutablePerson person = new ImmutablePerson("John", 30);

        System.out.println(person.getName()); // Output: John
        System.out.println(person.getAge());  // Output: 30

        // ImmutablePerson objects cannot be modified
        // person.setAge(31);  // Compilation error: Cannot assign a value to final variable 'age'
    }
}

Lombok 自动生成的构造函数中的字段默认添加final关键字,使字段成为不可变的。这意味着一旦在对象创建期间设置了字段,就无法更改它们。

总的来说,Lombok 中的@Value注解通过减少样板代码简化了不可变值对象的创建,使代码更干净、更简洁,同时确保不可变性和线程安全。

@With

  • @With使用场景就为克隆对象。修改一个值而保留其他值不变。@With 可以使用在类上,也可以使用在成员变量上。加在类上相当于给所有成员变量 @With注解
  • 它在处理不可变对象时特别有用,因为它允许创建对象的修改副本而不更改原始对象。

示例代码:

import lombok.Value;
import lombok.experimental.Wither;

@Value
public class ImmutablePerson {
    String name;
    int age;
    
    @With
    int age; // Generates withAge(int age) method
}
ImmutablePerson person = new ImmutablePerson("John", 30);
ImmutablePerson modifiedPerson = person.withAge(31);

在此示例中,age字段上的@With注解会在ImmutablePerson类中生成一个withAge(int age)方法。调用时,此方法返回ImmutablePerson具有指定年龄的新对象,而原始对象保持不变。

@SneakyThrows

  • @SneakyThrows注解允许抛出已检查的异常,而无需在方法签名中声明或显式处理。
  • 在使用抛出已检查异常的方法时,对于减少样板代码很有用。

示例代码:

import lombok.SneakyThrows;

public class Example {
    @SneakyThrows
    public void riskyMethod() {
        throw new InterruptedException();
    }
}

在此示例中,riskyMethod()方法抛出了一个InterruptedException异常,而没有在方法签名中显示声明或在方法中捕获。 Lombok 的@SneakyThrows注解为我们处理已检查的异常,使我们能够编写简洁的代码,而不会因异常处理而使其混乱。

@FieldDefaults

  • 注解@FieldDefaults可用于控制类中字段的访问级别。
  • 指定类中字段的默认访问级别( privateprotectedpublic或package-private)。

示例代码:

import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class Example {
    String name;
    int age;
}

在此示例中,Example类中的所有字段默认都具有private访问级别,并会使用默认值进行初始化。

@Builder.Default:

  • @Builder.Default注解与@Builder注解结合使用,为字段提供默认值。

示例代码:

import lombok.Builder;
import lombok.Builder.Default;

@Builder
public class Example {
    @Default
    String name = "John";
    int age;
}

@Builder

  • @Builder注解用来生成对象,并且可以为对象链式赋值。

示例代码:

import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
public class Person {
    private String name;
    private int age;
}
Person person = Person.builder()
                      .name("John")
                      .age(30)
                      .build();

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表