具有List作为字段的不可变Java类

时间:2017-06-23 05:28:28

标签: 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正在改变对象的状态。

请帮忙。

3 个答案:

答案 0 :(得分:4)

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

有必要制作在构造函数中从外部传递的集合的副本。否则,调用者仍然可以在将它们存储在对象中后修改它们:

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

要真正不变,这个班级及其领域也应该是最终的。

答案 1 :(得分:0)

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 = new HashSet<>(subjects);
    this.marks = new ArrayList<>(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);

答案 2 :(得分:0)

以下是答案

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Student implements Comparable<Student> {

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

    public Student(int rollNumber, String name, Set<String> subjects, List<Integer> marks) {
        this.rollNumber = rollNumber;
        this.name = name;
        this.subjects = new HashSet<>(subjects);
        this.marks = new ArrayList<>(marks);
        setPercentage();
    }

    private float percentage;

    public int getRollNumber() {
        return rollNumber;
    }

    public String getName() {
        return name;
    }

    public Set<String> getSubjects() {
        return Collections.unmodifiableSet(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();
        }
    }

    @Override
    public String toString() {
        return subjects.toString();
    }

    @Override
    public int compareTo(Student o) {
        return -1;
    }
}

主要方法:

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class NewClass {

    public static void main(String[] args) {
        Set<String> sub = new HashSet<>();
        sub.add("Maths");
        sub.add("Science");
        sub.add("English");
        List<Integer> marks1 = new LinkedList<Integer>();
        marks1.add(45);
        marks1.add(36);
        marks1.add(98);
        Student student1 = new Student(1, "Payal", sub, marks1);
        sub.add("History");
        System.out.println(student1);
    }
}

1:其他代码不起作用的原因是它们是集合unmodifiableSetunmodifiableList,而是在我们只需要创建新对象而不是指向旧引用时对本地对象。 2:And second阻止修改返回值,因为只需将实例变量设为final,或者你可以创建新的集合对象并返回它,但如果你这样做,那么每次调用getXXXX方法时它都会创建新对象实际上你不需要那个对象。