Search code examples
javastatic-factoryconcreteclass

Java interface that returns objects with its own type


I was looking at an interface that is built into Java, and noticed that it has methods which return objects of its own type.

Specifically, the IntStream interface has a method range which returns an IntStream object (i.e. some object that implements IntStream). This method can be used by only importing the interface, as follows:

import java.util.stream.IntStream;

class Foo {
    public static void main(String[] args) {
        IntStream s = IntStream.range(0,10);
        System.out.println(s.average());
    }
}

It therefore seems that 'under the hood' the interface is choosing an implementation for me, and allowing me to use it. How exactly is this working?

Crucially, how would I do the same thing? If I wanted to export an interface that can instantiate objects of its own type, so that a user could simply import my interface and it would drag along my implementation, how would I do this? Or is this only a special privilege of interfaces built into Java?


Solution

  • range is a static method of the IntStream interface that returns an instance of a class that implements IntStream. Take a look in the example below.

    public interface MyInterface {
    
        public static class MyClass implements MyInterface {
            @Override 
            public void doSomething() {
                System.out.println( "i'm an implementing class!" );
            }
        }
    
        public static MyInterface createMagicInstance() {
            return new MyClass();
        }
    
        public void doSomething();
    
    }
    
    public class Test {
        public static void main( String[] args ) {
            MyInterface mi = MyInterface.createMagicInstance();
            mi.doSomething();
        }
    }
    

    In my example I tried to design something self-contained, but implementations of createMagicInstance may vary. You don't need to implement the returning type as a static inner class. I would recomend you to take a look at the source code of IntStream class of OpenJDK: https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/stream/IntStream.java