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?
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