Why make defensive copies in getters inside immutable classes?

前端 未结 7 645
余生分开走
余生分开走 2020-12-08 16:13

This question is about good programming practices and avoiding potential holes.
I read Joshua Bloch\'s Effective Java and here is what I wonder:
Why should I conside

7条回答
  •  醉酒成梦
    2020-12-08 16:51

    I believe this is the case that justifies this statements:

    public class Immutable {
    
        private final String name;
    
        private Date dateOfBirth;
    
        public Immutable(String name, Date dateOfBirth) {
            this.name = name;
            this.dateOfBirth = dateOfBirth;
        }
    
        public String getName() {
            return name;
        }
    
        public Date getDateOfBirth() {
            return dateOfBirth;
        }
    
    }
    

    getName() is fine as it returns immutable object as well. However the getDateOfBirth() method can break immutability because the client code can modify returned object, hence modifying the Immutable object as well:

    Immutable imm = new Immutable("John", new Date());
    
    imm.getName(); //safe
    Date dateOfBirth = imm.getDateOfBirth();
    //hundreds of lines later
    dateOfBirth.setTime(0);  //we just modified `imm` object
    

    It is safe to return immutable objects and primitives (as they are returned by value). However you need to make defensive copies of mutable objects, like Date:

    public Date getDateOfBirth() {
        return new Date(dateOfBirth.getTime());
    }
    

    and wrap collections in immutable views (if they are mutable), e.g. see Collections.unmodifiableList():

    public List getSomeIds() {
        return Collections.unmodifiableList(someIds);
    }
    

提交回复
热议问题