static factory method in interface class java

Java 8 finally allows interfaces to have static methods.

See this archived copy of the TechEmpower blog for details.


You can define the factory as returning the Interface but internally it creates a concrete class.

For example:

public Interface I { }

private class Impl implements I {
}

I buildI() {
    return new Impl();
}

The trick is to create the implementations with package private (or even if they are inner classes private) constructors and then only the factory can build them.

The power of this method is that the factory can build the appropriate implementation depending on the requirements and that all happens invisibly to the user. For example when you create an EnumSet using the factory there are multiple internal implementations depending on how many entries there are in the Enum that the EnumSet is being built for. A super-fast version using bitfields on a long for Enums with less than 64 entries, a slower version for longer enumerations.

To specify the interface for a factory all you need to do is:

public interface Factory {
   I buildI();
}

Now people can call you with setFactory(new FactoryImpl()); you can then call factory.buildI() and their code then returns the concrete implementation.

You can take this a step further and use Generics:

public interface GenericFactory<T> {
    T buildInstance();
}

And then your setFactory becomes:

public void setFactory(GenericFactory<I> factory);

To create a factory they do:

public class FactoryImpl implements GenericFactory<I> {
     @override
     I buildInstance() {
        return new impl();
     }
}

But now you can use that same factory class for absolutely anything that needs a factory, just change the generics requirement.

The reason it can call the private constructor is very simple - it's declared in the same class!

Inside one Java file you can create the class with the private constructor. You then define the static method inside the class and even though it is static it still has the privileges required to access the constructor.

If the factory and implementation are in separate classes then they will be placed in the same package and the method made package private instead of private.