java - 具有列表作为字段的不可变 Java 类

标签 java

我们能否使以集合作为字段之一的类不可变?

public class Student implements Comparable<Student> {

    private int rollNumber;
    private String name;
    private Set<String> subjects;
    private List<Integer> marks ;

    public Student(int rollNumber, String name, Set<String> subjects,
            List<Integer> marks) {
        this.rollNumber = rollNumber;
        this.name = name;
        this.subjects = Collections.unmodifiableSet(subjects);
        this.marks = Collections.unmodifiableList(marks);
        setPercentage();
    }

    private float percentage;

    public int getRollNumber() {
        return rollNumber;
    }

    public String getName() {
        return name;
    }

    public Set<String> getSubjects() {
        return new HashSet<>(subjects);
    }

    public List<Integer> getMarks() {
        return new ArrayList<>(marks);
    }

    public float getPercentage() {
        return percentage;
    }

    private void setPercentage() {
        float sum = 0;

        for (Integer i : marks)
            sum = sum + i;
        if (!marks.isEmpty())
            percentage = sum / marks.size();

    }
}

我做不到。

我试过:

Set<String> subjects= new HashSet<>();
subjects.add("Maths");
subjects.add("Science");
subjects.add("English");
List<Integer> marks1= new LinkedList<Integer>();
marks1.add(45);
marks1.add(36);
marks1.add(98);
Student student1= new Student(1, "Payal", subjects, marks1);
//student1.getSubjects().add("History");
subjects.add("History");
System.out.println(student1);

但是 subjects.add 正在改变对象的状态。

请帮忙。

最佳答案

在从 getter 返回它们之前,您正在制作两个集合的副本。这是不必要的,因为集合是不可修改的(除非您希望调用者获得可变集合而不是不可修改的集合)。

必要的是在构造函数中复制从外部传递的集合。否则,调用者仍然可以在集合存储在您的对象中后对其进行修改:

this.subjects = Collections.unmodifiableSet(new HashSet<>(subjects));
this.marks = Collections.unmodifiableList(new ArrayList<>(marks));

要真正做到不可变,类及其字段也应该是最终的。

关于java - 具有列表作为字段的不可变 Java 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44713689/

相关文章:

java,线程何时(以及多长时间)可以缓存非 volatile 变量的值?

java - 如何将日期转换为毫秒

java - Java Parceler 问题

java - JComboBox 恢复为 JTable 中的原始值

java - 不知道为什么我的 gui 应用程序出现 nullpointerException

java - 使用bat文件启动视频播放器,java窗口中出现失败消息

java - Android 以编程方式打开设置-> 按钮单击上的安全选项卡

java - 这可以递归地完成吗?

java - 如何反编译成java文件 intellij idea

java - Java中的while循环错误