Search code examples
javainheritancefactoryfinal

Effective Java: Make constructors private or package-private


From Chapter 4 of Effective Java the following example is given:

public class Complex { 
    private final double re; 
    private final double im;

    private Complex(double re, double im) {
        this.re = re;
        this.im = im;
    }

    public static Complex valueOf(double re, double im) {
        return new Complex(re, im);
    }
    ... // Remainder unchanged
} 

[...] It is the most flexible because it allows the use of multiple package-private implementation classes. To its clients that reside outside its package, the immutable class is effectively final because it is impossible to extend a class that comes from another package and that lacks a public or protected constructor.

I understand that the class is effectively final,

but is there any actual advantage from not declaring it final?

Omitting this keyword when the class doesn't support extension seems like a less clear way to communicate how the API is meant to be used. Or was final only left out here to show the reader that non-extendable, non-final classes are possible?


Solution

  • The main benefit is to limit the scope of inheritance. Declaring it final will make it sealed everywhere; however, sometimes as an author of the class you would like to inherit the class within the same package or class file but you don't want others to do the same. And that's what this trick will do.

    It's a nightmare to change a class that is open for inheritance (Commonly used APIs). If you can limit the scope of inheritance, then it becomes a simple refactoring job.