Lombok不可变:构造函数,用于复制参数深]

问题描述 投票:2回答:2

我如何获得一个构造函数,该构造函数将构造函数参数的副本分配给字段,以使实例真正不可变?下面的类具有@Value批注,但这不是不可变的,因为它的属性不是:(问题不是特定于不可变的Collections的,我只是用它演示了可变的DS。我正在寻找任何可变的bean代替这里的List,例如它来自库,不在我的控制范围内]

@Value
class ImmutableBean {
    List<String> props;
}
    @Test
    void checkImmutability() {
        var props = new ArrayList<String>();
        props.add("abc");
        var immutableBean = new ImmutableBean(props);
        System.out.println(immutableBean.getProps()); // abc
        props.add("pqr");
        System.out.println(immutableBean.getProps()); // abc pqr
    }
java functional-programming immutability lombok
2个回答
1
投票

对于Singleton类,您需要使用@Singular并将您的收藏字段标记为private final

import lombok.*;

import java.util.ArrayList;
import java.util.List;

@Value
@AllArgsConstructor
@Getter
@Builder
class ImmutableBean {

    @Singular
    private final List<String> props;

    public static void main(String[] args) {
        List<String> props = new ArrayList<>();
        props.add("abc");
        ImmutableBean immutableBean = ImmutableBean.builder().props(props).build();
        System.out.println(immutableBean.getProps()); // abc
        props.add("pqr");
        System.out.println(immutableBean.getProps()); // abc
    }
}

0
投票

用lombook @Value注释的类使默认情况下将所有字段设为私有和final,并且不生成设置器。这意味着一旦创建对象,该对象将是不可变的,并且您不能覆盖其属性。该类使用setter方法,例如

@Test
void checkImmutability() {
    var props = new ArrayList<String>();
    props.add("abc");
    var immutableBean = new ImmutableBean(props);
    System.out.println(immutableBean.getProps()); // abc
    immutableBeansetProps(new ArrayList<>());  //compile time error

}

因此lombook @Value注释将使属性成为不可变的,因此您不能像上面的示例那样用另一个对象覆盖该对象,但是可以更新相同的对象

var props = new ArrayList<String>();
props.add("abc");
var immutableBean = new ImmutableBean(props);
System.out.println(immutableBean.getProps().hashCode()); // object1
props.add("pqr");
System.out.println(immutableBean.hashCode()); // object1 (same object)

避免这种情况的唯一方法是,您需要创建那些属性的不可变对象,例如,您可以创建不可变列表

var immutableBean = new ImmutableBean(Collections.unmodifiableList(props));

@@ Value是@Data的不可变形式; 默认情况下,所有字段都设为私有和最终字段,并且不会生成设置器。默认情况下,该类本身也被设置为final]],因为不可变性不是可以强制进入子类的东西。像@Data一样,还会生成有用的toString(),equals()和hashCode()方法,每个字段都有一个getter方法,并且还会生成一个覆盖每个参数的构造函数(除了在字段声明中初始化的最终字段之外) 。

© www.soinside.com 2019 - 2024. All rights reserved.