如何使对象在Java中不可变

plzdontkillme

由于这是当今的热门话题,我无法理解某些概念。如果我听起来很蠢,请原谅,但是当我尝试创建不可变对象时,我发现大多数帖子都包含以下几点

  • 使班级最终-有道理
  • 不允许属性使用更改符(设置者)-有意义
  • 将属性设为私有-有意义

现在我不明白为什么我们需要以下几点

  • 将构造函数设为私有,并为createInstance方法提供与构造函数或工厂方法相同的属性?它有什么帮助?
  • 将属性设为final-帖子的发布无法解释这一点,并且我在其中阅读了一些内容以避免意外修改。当没有变种器并且class是final时,如何意外修改?将属性定为final有什么帮助?
  • 除了工厂模式,我可以使用构建器模式吗?

我在这里添加我的课程和测试用例:

    public final class ImmutableUser {
    private final UUID id;
    private final String firstName;
    private final String lastName;

    public ImmutableUser(UUID id, String firstName, String lastName) {
        super();
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }
    /**
     * @return the id
     */
    public UUID getId() {
        return id;
    }
    /**
     * @return the firstName
     */
    public String getFirstName() {
        return firstName;
    }
    /**
     * @return the lastName
     */
    public String getLastName() {
        return lastName;
    }
}

测试用例

public class ImmutableUserTest {

        @Test(expected = IllegalAccessException.class)
        public void reflectionFailure() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
            ImmutableUser user = new ImmutableUser(UUID.randomUUID(), "john", "liu");
            Field i =user.getClass().getDeclaredField("firstName");
            i.setAccessible(true);
            i.set(user, "cassandra");
            System.out.println("user " + user.getFirstName()); // prints cassandra
        }

    }

该测试用例失败并打印cassandra。

让我知道我做错了什么。

尼尔·阿尔法西
  • 将构造函数设为私有,并为createInstance方法提供与构造函数或工厂方法相同的属性?它有什么帮助?

答案:将构造函数createInstance()设为私有并提供(工厂方法)本身并不能帮助:这是您应该做的几件事,以允许用户在仍然可以控制实例的方式的同时实际使用该类及其实例。被创建。

  • 将属性设为最终版本-该帖子无法解释这一点,我在此处读过一些地方,以免意外修改。当没有变种器并且class是final时,如何意外修改?将属性定为final有什么帮助?

答案:将类声明为final意味着用户无法扩展它,因此它“阻止”用户使用这种“解决方法”。将属性声明为final不允许类的用户对其进行更改。不能“意外地修改”它,但是可以使用反射来“恶意地修改”它。让我们看一个例子,假设您有:

final public class SomeClass {
    final Integer i = 1;
}

从另一个类中,您可以执行以下操作:

class AnotherClass {

    public static void main (String[] args) throws Exception {

        SomeClass p = new SomeClass();
        Field i =p.getClass().getDeclaredField("i");
        i.setAccessible(true);
        i.set(p, 5);
        System.out.println("p.i = " + p.i); // prints 5
    }
}
  • 可以代替工厂使用构建器模式吗?

:您可以使用构建器模式或任何有助于您控制类实例创建的模式。

进一步:
如果要确保您的类是不可变的,请确保任何类都getter返回该类成员深层副本此技术称为“保护性/防御性复制”。您可以在此处了解更多信息

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何使对象在Java中不可变

来自分类Dev

在不可变对象Java中限制可变对象

来自分类Dev

如何更新不可变对象中的字段

来自分类常见问题

制作不可变的Java对象

来自分类Dev

使对象在Groovy中不可变

来自分类Dev

如何使用XJC生成不可变的Java对象?

来自分类Dev

如何从不可变数组中删除对象?

来自分类Dev

如何从JavaScript中的工厂函数返回不可变对象

来自分类Dev

Java中的不可变类

来自分类Dev

Java中的不可变集合

来自分类Dev

Java中的不可变类

来自分类Dev

Java中的不可变集合

来自分类Dev

如何在JS中创建对象的可变且不可变的副本

来自分类Dev

如何在以用户定义的类对象作为类成员的Java中创建用户定义的不可变类?

来自分类Dev

Java:如何使私有字段Map在类中不可变?

来自分类Dev

如何在Java中创建不可变列表?

来自分类Dev

用Java安全发布不可变对象

来自分类Dev

val或var在不可变对象中的意义

来自分类Dev

在Python中对不可变对象进行操作时,如何创建新对象?

来自分类Dev

如何根据f#中定义的类型的对象生成新的不可变对象?

来自分类Dev

为什么不可变对象的属性在Swift中是可变的?

来自分类Dev

Python和C / C ++中的可变/不可变对象

来自分类Dev

将可变属性作为Python中的不可变对象返回

来自分类Dev

Python和C / C ++中的可变/不可变对象

来自分类Dev

不可变对象的缺点

来自分类Dev

实习不可变对象

来自分类Dev

更新不可变对象

来自分类Dev

实习不可变对象

来自分类Dev

不可变的Lisp对象