Reputation: 95
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?
Upvotes: 1
Views: 102
Reputation: 9424
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
Upvotes: 6
Reputation: 3488
If you check the definition of IntStream.range you would be able to see that range
is an static method of IntStream
, which means, you don't need to have an instance of IntStream to call it, you can just directly invoke it as you are doing in the piece of code you put as example. How can you do it? Just define an interface with an static method that returns an object of that interface type. You can also check the source code of IntStream and see the implementation
public static IntStream rangeClosed(int startInclusive, int endInclusive) {
if (startInclusive > endInclusive) {
return empty();
} else {
return StreamSupport.intStream(
new Streams.RangeIntSpliterator(startInclusive, endInclusive, true), false);
}
}
Upvotes: 1
Reputation: 425033
The "interface" is not returning anything.
IntStream.range(int, int)
is a static
method that returns an IntStream
.
It has little to do with the IntStream
interface and would work equally well if defined in another class.
Upvotes: 3