Sadina Khatun
Sadina Khatun

Reputation: 1166

How to Create Immutable Class with List<String> Element in class

Immutable Class with List

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;
    }
} 

Testing Immutable Class to Break Immutability

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());

    } 
} 

Output is

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

why and how this new Course element added into the List as its from Client Side can be added up any time so how we can fix this issue as this immutable class should not allow to modifying after once created

Upvotes: 3

Views: 2906

Answers (4)

Martin Frank
Martin Frank

Reputation: 3454

read about immutableLists and you'll find that an Immutable and Unmodifiable Are Not the Same.

I guess (from your question) you are expecting an unmodifiable list which you simply don't create...

see this answer for a proper solution

Upvotes: 1

Koziołek
Koziołek

Reputation: 2874

Not the best in context of memory, but works:


// 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);
    }
} 

On input (in constructor) you create copy of list and on output (in getter) you create copy.

Upvotes: 2

javaGroup456
javaGroup456

Reputation: 333

With Collections.unmodifiableList, it creates a wrapper around the original list and that wrapper object is unmodifiable. The original list can still be updated.

So, in order for the List<String> courses list to be immutable, you can use Apache collection common library.

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

ImmutableList has overridden the List.add method to always throw exception java.lang.UnsupportedOperationException


Second alternative is to create the list inside the constructor itself.

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

}

And call it like this :

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

Upvotes: 0

GhostCat
GhostCat

Reputation: 140467

this.courses = Collections.unmodifiableList(courses);

That creates, as the name says, an unmodifiable list. But that is just a view on the original list. Thus changes to that original list become visible in your "unmodifiable" view.

When in doubt: clone your list, like:

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

And then ensure that your getter does:

return Collections.unmodifiableList(courses);

Upvotes: 4

Related Questions