有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

不变性使Java对象不可变

我的目标是使Java对象不可变。我有一个班级Student。为了实现不变性,我采用以下方式对其进行编码:

public final class Student {

private String name;
private String age;

public Student(String name, String age) {
    this.name = name;
    this.age = age;
}

public String getName() {
    return name;
}

public String getAge() {
    return age;
}

}

我的问题是,实现Student类不变性的最佳方法是什么


共 (6) 个答案

  1. # 1 楼答案

    How do you make a mutable object immutable?

    1. 将该类声明为final,这样它就不能被扩展
    2. 将所有字段设置为私有,以便不允许直接访问
    3. 不要为变量提供setter方法
    4. 将所有可变字段设为最终字段,以便其值只能指定一次
    5. 通过执行深度复制的构造函数初始化所有字段
    6. 在getter方法中执行对象克隆以返回副本,而不是返回实际的对象引用

    source

    Why do we create immutable objects?
    Immutable objects are simply objects whose state (the object's data) cannot change after construction.

    • 安全性:存储敏感信息,如用户名、密码、连接URL、网络连接等
    • 易于构造、测试和使用
    • 是自动线程安全的,没有同步问题
    • 不需要复制构造函数
    • 不需要克隆的实现
    • 允许hashCode使用延迟初始化,并缓存其返回值
    • 当用作字段时,不需要防御性地复制
    • 制作好映射键并设置元素(这些对象在集合中时不得更改状态)
    • 一旦构建了它们的类不变量,就不需要再次检查
    • 始终具有“失败原子性”(Joshua Bloch使用的一个术语):如果一个不可变对象抛出异常,它永远不会处于不受欢迎或不确定的状态

    Source

    在Java中,字符串是不可变的,这提供了缓存、安全性、无需复制即可轻松重用等功能。 Source

  2. # 2 楼答案

    使用final关键字:

    private final String name;
    private final String age;
    
  3. # 3 楼答案

    这很好,但我也会制作字段final

    我也会把年龄变成intdouble而不是字符串

  4. # 4 楼答案

    对于一个不可改变的类,你必须考虑的事情很少:

    • 让你的班级final——你已经有了
    • 对所有字段privatefinal进行适当的代码更改
    • 不要提供任何改变实例状态的方法
    • 如果类中有可变字段,比如ListDate,那么让它们final就不够了。您应该从它们的getters返回一个防御副本,这样它们的状态就不会因调用方法而发生变化

    对于第四点,假设您的类中有一个Date字段,那么该字段的getter应该如下所示:

    public Date getDate() {
        return new Date(this.date.getTime());
    }
    

    当你的可变场本身包含一些可变场,而这些可变场又包含一些其他可变场时,制作一个防御副本可能会成为一个头疼的问题。在这种情况下,您需要以迭代的方式复制它们中的每一个。我们将这个可变字段的迭代副本命名为深度副本

    自己实现深度复制可能很麻烦。但是,如果你认为你自己陷入了这样一个要求,那就是,你应该重新考虑你的课堂设计。p>

  5. # 5 楼答案

    严格来说,你的类不是一成不变的,它只是实际上是一成不变的。要使其不可变,需要使用final

    private final String name;
    private final String age;
    

    尽管差异似乎很微妙,但。不可变类本质上是线程安全的,有效不可变类只有在安全发布时才是线程安全的

  6. # 6 楼答案

    将变量设置为私有且无setter方法将适用于原始数据类型。我的类是否有对象集合

    使任何类与集合对象不可变

    使用extends collection类编写自己的集合对象,并遵循私有变量和no setter方法。或者返回集合对象的克隆对象

    public final class Student {
    
    private StudentList names;//Which is extended from arraylist
    
    public Student() {
    names = DAO.getNamesList()//Which will return All Student names from Database  its upto you how you want to implement.
    }
    
    public StudentList getStudentList(){
    return names;//you need to implement your own methods in StudentList class to iterate your arraylist; or you can return Enumeration object.
    }
    
    public Enumeration getStudentNamesIterator(
    Enumeration e = Collections.enumeration(names);
    return e;
    }
    
    public class StudentList extends ArrayList {
    
    }