3

带列表的不可变类

package com.text.immutable;

import java.util.Collections;
import java.util.List;

// An immutable class Student
public final class Student 
{ 
    final String name; 
    final int regNo; 
    final List<String> courses;  // want to make Immutable 

    public Student(String name, int regNo, List<String> courses) 
    { 
        this.name = name; 
        this.regNo = regNo; 
        this.courses = Collections.unmodifiableList(courses);
    } 
    public String getName() 
    { 
        return name; 
    } 
    public int getRegNo() 
    { 
        return regNo; 
    } 

    public List<String> getCourses() {
        return courses;
    }
} 

测试不可变类以打破不变性

package com.text.immutable;

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

class ImmutablityTest 
{ 
    public static void main(String args[]) 
    { 
        List<String> courses = new ArrayList<String>();
        courses.add("java");
        courses.add("spring");
        courses.add("hibernate");
        courses.add("rest");

        Student s = new Student("ABC", 101, courses); 

        System.out.println("Before Update List");
        System.out.println(s.getName()); 
        System.out.println(s.getRegNo()); 
        System.out.println(s.getCourses());
        courses.add("Hibernate"); // Able to Change which affect final OutCome
        //s.getCourses().add("SpringBoot"); // giving Exception in thread "main" java.lang.UnsupportedOperationException

        System.out.println("After Update List");
        System.out.println(s.getName()); 
        System.out.println(s.getRegNo()); 
        System.out.println(s.getCourses());

    } 
} 

输出是

Before Update List
ABC
101
[java, spring, hibernate, rest]
After Update List
ABC
101
[java, spring, hibernate, rest, Hibernate]

为什么以及如何将这个从客户端添加到列表中的新课程元素随时添加,所以我们如何解决这个问题,因为这个不可变类在创建后不允许修改

4

4 回答 4

4

this.courses = Collections.unmodifiableList(courses);

顾名思义,这将创建一个不可修改的列表。但这只是原始列表中的一个视图。因此,对原始列表的更改在您的“不可修改”视图中变得可见。

如有疑问:克隆您的列表,例如:

this.courses = new ArrayList<>(courses);

然后确保你的吸气剂做:

return Collections.unmodifiableList(courses);
于 2019-10-21T08:20:56.927 回答
2

在内存方面不是最好的,但有效:


// An immutable class Student
public final class Student 
{ 
    final String name; 
    final int regNo; 
    final List<String> courses;  // want to make Immutable 

    public Student(String name, int regNo, List<String> courses) 
    { 
        this.name = name; 
        this.regNo = regNo; 
        this.courses = new ArrayList(courses);
    } 
    public String getName() 
    { 
        return name; 
    } 
    public int getRegNo() 
    { 
        return regNo; 
    } 

    public List<String> getCourses() {
        return new ArrayList(courses);
    }
} 

在输入(在构造函数中)创建列表副本,在输出(在 getter 中)创建副本。

于 2019-10-21T09:00:56.693 回答
1

阅读有关 immutableLists的内容,您会发现Immutable 和 Unmodifiable Are Not the Same

我猜(从你的问题)你期待一个你根本不创建的不可修改的列表......

请参阅此答案以获得正确的解决方案

于 2019-10-21T08:18:07.513 回答
0

使用Collections.unmodifiableList,它会围绕原始列表创建一个包装器,并且该包装器对象是不可修改的。原始列表仍然可以更新。

因此,为了使List<String> courses列表不可变,您可以使用 Apache 集合公共库。

List<String> immutableList = com.google.common.collect.ImmutableList.of("Geeks", "For","Geeks");

ImmutableList 已覆盖 List.add 方法以始终抛出异常java.lang.UnsupportedOperationException


第二种选择是在构造函数本身内创建列表。

public Student(String name, int regNo,  String... args) 
{ 
    this.name = name; 
    this.regNo = regNo; 
    courses = (List)Arrays.asList(args);

}

并这样称呼它:

 Student s = new Student("ABC", 101, "a","a","a","a"); 
于 2019-10-21T08:47:51.497 回答