Reputation: 1166
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
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
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
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
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