Question

I was reading this page about using the new keyword in the constructor, and I was wondering if it applies to copy constructors for collections.

Suppose I have a Book class and a collection to store a set of authors.

class Book {

    private String title;
    private Set<Author> authorsSet;

    Book (title, authors){
        this.title = title
        this.authorsSet = Collections.unmodifiableSet(new HashSet<Author>(authors)) 
    }
}

It's a good idea to make a defensive copy so that client code cannot change the internals of authorsSet.

Is calling this.authorsSet = Collections.unmodifiableSet(new HashSet<Author>(authors)) a violation of the guideline that a constructor shouldn't call the new keyword? If so, how do we make a defensive copy without the new keyword?

Was it helpful?

Solution

If in a constructor of class A another object of class B is constructed by new, then A has a hard dependency on B, which makes it impossible to test A isolated from B, which can be resolved by injecting a B instance into A through a constructor parameter of some interface type which B implements. But that is only a necessary

  • if you actually want or need to unit test A isolated from B.

In the shown case, that would mean to unit test Book isolated from the class HashSet - which is probably not what you want or need. Collection classes like HashSet can be treated as elements of your framework or programming languages (actually, in some languages like Perl or Python they are elements of the language). They are lightweight, fast, can be assumed to be bugfree for all practical purposes, and often most your code depends on them anyway. So it typically makes no sense to break a dependency on them.

Licensed under: CC-BY-SA with attribution
scroll top