Java Lombok:@AllArgsConstructor中如何省略一个字段?

173
如果我使用Lombok来指定@AllArgsConstructor,它将生成一个构造函数来设置所有已声明的(不是final,也不是static)字段。是否可能省略某些字段,并使生成的构造函数仅适用于所有其他字段?

2
那就不算是全参数构造函数了。 - Dave Newton
4
当然可以。也许使用lombok有一些解决方案? - user3656823
7个回答

213

不,那是不可能的。有一个特性请求可以创建一个@SomeArgsConstructor,您可以在其中指定涉及到的字段列表。

完全透明:我是核心Project Lombok开发人员之一。


21
在 Lombok 1.16.20 中缺少了@SomeArgsConstructor - Grigory Kislin
17
2020年是否有@SomeArgsConstructor可用? - theprogrammer
2
我希望我们能在即将到来的2021年看到这样的构造函数(看起来功能请求因我不理解的原因被拒绝了)。 - Nikita Kobtsev
1
请查看有关 @RequiredArgsConstructor 的答案,因为该注释可能满足大多数 OP 问题的用例。 - Gordon Bean
15
就像你使用 @EqualsAndHashCode.Exclude 一样,你可以在字段前加上 @AllArgsConstructor.Exclude - Erick Audet

182

或者,您可以使用@RequiredArgsConstructor。这将为所有字段添加一个构造函数,这些字段都是@NonNullfinal

请参阅文档


2
这是一个不错的解决方法,使用@NonNull。但请注意,这对具有默认值的字段无效。 - eeezyy
1
这对我很有效,我甚至使用了@Transient标记省略的字段,以避免它被Java持久层跟踪,因为它在我的DAO中。 - Encryption

30

如果有帮助的话,已初始化的 final 字段会被排除在外。

@AllArgsConstructor
class SomeClass {
    final String s;
    final int i;
    final List<String> list = new ArrayList<>(); // excluded in constructor
}

var x = new SomeClass("hello", 1);

这在集合或其他可变类中尤其有意义。

此解决方案可以与此处的其他解决方案一起使用,该解决方案涉及使用@RequiredArgsConstructor

@RequiredArgsConstructor
class SomeClass2 {
    final String s;
    int i; // excluded because it's not final
    final List<String> list = new ArrayList<>(); // excluded because it's initialized
}

var x = new SomeClass2("hello");

4
重要补充:“被初始化的 final 字段将被排除在外” -> 如果字段仅被初始化但不是 final 的话,构造函数(由 AllArgsConstructor 生成)将会包含该字段 :) - oruckdeschel
嗨,我想问一下有没有什么办法可以生成两种类型的构造函数,例如一个包含字符串s和整数i,另一个包含字符串s和字符串F。 - Compte Gmail
1
Lombok旨在为常见情况生成代码,而不是特定场景。您应该明确编写特定的构造函数。 - Ferran Maylinch
1
你的回答帮了大忙:如果你想要排除的字段是常量,因此它们是final的。 - avi.elkharrat
1
我使用了这个选项,它有效。 - Park JongBum
1
对我来说,这个答案被低估了,应该是任何寻找如何在Lombok构造函数中跳过字段的答案的人首先查看的。 - Bryn

18

在某些情况下,一个很好的解决方法是使用@Builder


参考示例:https://dev59.com/tV0a5IYBdhLWcg3wF1UL#39920328 - Stephan
2
假设有“_一种_方法”,而不是“_好的_方法”。如果您想要一个AllArgsConstructor来保证用户提供所有(必需的)成员,则使用标准构建器 不是 正确的方法。 - towi
1
我曾经说过,在某些情况下,我仍然坚持这个观点。 - enkara

13

这可以使用 Lombok 中的两个注释来完成:

请参见以下示例:

package com.ss.model;

import lombok.*;

@Getter
@Setter
@RequiredArgsConstructor
@ToString
public class Employee {

    private int id;

    @NonNull
    private String firstName;

    @NonNull
    private String lastName;

    @NonNull
    private int age;

    @NonNull
    private String address;
}

然后您可以按照下面所示创建一个对象:

Employee employee = new Employee("FirstName", "LastName", 27, "Address");

嗨,我想问一下是否有任何想法如何生成两种类型的构造函数,例如一个包含年龄和姓氏,另一个包含地址和年龄。 - Compte Gmail
嗨@CompteGmail,最好单独定义构造函数。 - Shubhasish Bhunia

0

Lombok旨在为您的POJO处理样板代码。自定义构造函数/设置器/获取器/toString/copy等不属于样板代码的一部分。对于这些情况,每个Java IDE都提供了易于使用的代码生成器,帮助您快速完成任务。 在您的情况下,

public MyClass(String firstName, String lastName) {....}

比起一个假设性的语句,这个更易读且更有意义:

@AllArgsConstructor(exclude = "id", exclude = "phone")

玩得开心!


0
当你只需要一些属性的构造函数时,你可以在类级别使用@RequiredArgsConstructor,并将选择的属性声明为final。然后,如果你需要一个空构造函数,你可以使用类似于@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)的东西。
这个注解将创建一个空的JPA构造函数,并且属性将被初始化为默认值(int为0,String为null等)。
示例:
@Data
@Entity
@Table(name = "VetFiles")
@RequiredArgsConstructor
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
public class FileInfo implements Serializable {

    private static final long serialVersionUID = 6719621520531075147L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private final String name;
    private final String url;

    @ManyToOne
    private Thing thing;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接