· · ─ ·✶· ─ · ·

Assume you write a class like so,

class MyClass {
    private List<Integer> nums;
 
    public MyClass(List<Integer> nums) {
        this.nums = nums;
    }
}

Spotbugs will immediately spit out the EI_EXPOSE_REP2 warning.

What does this mean? You exposed your internal mutable representation by storing a reference to externally mutable data.

    public MyClass(List<Integer> nums) {
        this.nums = nums; // <- exposes internal representation
    }

because now outside code and inside code both share the same mutable list object. Someone from outside could make changes to the contents of the list and our internal list would also get changed. This could be potentially bad.

Full example:

import java.util.*;
 
class MyClass{
    private List<Integer> numbers;
    
    public MyClass(List<Integer> numbers){
        this.numbers = numbers;
    }
    
    public void func(){
        System.out.println(this.numbers);
    }
}
 
class Main {
    
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        
        MyClass cl = new MyClass(numbers);
        numbers.set(0, 99);
        cl.func(); // prints [99, 2, 3]
    }
}

So how do you avoid this?

class MyClass{
    private List<Integer> numbers;
    
    public MyClass(List<Integer> numbers){
        this.numbers = new ArrayList<>(numbers); // create own copy
    }
    
    public void func(){
        System.out.println(this.numbers);
    }
}

We can just create our own copy of the list inside the class. This decouples it from the outside list (which originally got coupled because of Java’s pass-by-reference behaviour)

· · ─ ·✶· ─ · ·