Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this class not immutable?

I had a Java interview today and I was asked to create an immutable class named Person and I was given a skeleton with some parameters: age, name, etc. I created the below class:

final class Person {
  private final int age;
  private final String name;
  private final List<String> petNames;


  public Person(int a, String n, List<String> p) {
    this.age = a;
    this.name = n;
    this.petNames = p;
  }

  int getAget() {
    return this.age;
  }

  String getName() {
    return this.name;
  }

  List<String> getPetnames() {
    return this.petNames;
  }

}

I was told that it is not complete because by performing the below sequence of code, you prove that it is not immutable:

int x = 3;
String name = "Alex";
List<String> ls = new ArrayList<>();
Person p1 = new Person(x, name, ls);

The hint I was given is that it is related to the list and that I should change sth in the constructor. But I really do not know why and I do not really understand what is wrong.

Can anyone explain me what should be added and why ? Maybe I did not understand completely immutability.

like image 976
Maria1995 Avatar asked Dec 18 '22 13:12

Maria1995


2 Answers

I assume they asked you to keep an immutable copy of the given pet collection.

this.petNames = List.copyOf(p);

Otherwise, you would still be able to modify the pets of a person.

p1.getPetnames().add("newPet");

You shouldn't be bothered with what will happen to ls, but you should take care of what you can do with p1.

  1. You make a copy to stop worrying whether the input is going to be changed sometime later.
  2. You make the collection immutable, which, along with the 2 final plain fields, makes the class immutable.
like image 195
Andrew Tobilko Avatar answered Jan 01 '23 10:01

Andrew Tobilko


To make list immutable, I believe you should use

       this.petnames=  ImmutableList.copyOf(p);

or

     this.petnames  = Collections.unmodifiableList(new ArrayList<>(p));

In java 9, you can use copyOf() method to create immutable list

 this.petnames = List.copyOf(p)

If you return this then its not possible to add or remove elements to it. However, they can be get elements out of it.

like image 35
Shubham Avatar answered Jan 01 '23 11:01

Shubham