-2

Not sure how to write the question, but I saw the following construct in https://stackoverflow.com/a/45971597/242042

public interface MyStream<T> {
    Stream<T> stream();
    static <T> MyStream<T> of(Stream<T> stream) {
        return () -> stream;
    }
}

Which I used in my answer https://softwareengineering.stackexchange.com/a/400492/42195

The of method returns a Callable that returns the delegate stream. But how did that even translate to <T> MyStream <T> ?

Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265

2 Answers2

2

What you are returning from your static of(Stream<T> stream) method is basically the functional interface MyStream<T> implementation

The lambda () -> stream is then implementation of Stream<T> stream() method (because it's the only one to be overridden) and because stream is of Stream<T> type everything is good here

Read more about functional interfaces here: What is use of Functional Interface in Java 8?

m.antkowicz
  • 13,268
  • 18
  • 37
2

It might be easier to understand if you separate the code a little more:

public interface MyStream<T> {
    Stream<T> stream();
}
class Util {
    static <T> MyStream<T> of(Stream<T> stream) {
        return () -> stream;
    }
}

It is still doing the same thing, but it is a little easier to follow.

Then in a second step, let's write this without a lamda expression in the "classic" way:

public interface MyStream<T> {
    Stream<T> stream();
}
class Util {
    static <T> MyStream<T> of(Stream<T> stream) {
        return new MyStream<>() {
            Stream<T> stream() {
                return stream;
            }
        };
    }
}

What you are doing here is create an anonymous class, that implements the interaface MyStream. It has a method stream which returns the stream you passed as method argument.

Now with Java 8 there is this fancy new format to write things. This is possible if the interface has only a single method. In this case the new Stream is not necessary, because the compiler knows the type from the return type of your method. Also the Stream<T> stream() definition is not necessary, because the compiler knows it from the interface definition. And in case of a single statement, you can even omit the return, because the compile will assume the result of the single statement to be the return-value.

Thus this:

return new MyStream<>() {
    Stream<T> stream() {
        return stream;
    }
};

can be written as:

  () -> stream;
//      ^^^^^^^ Return value
//^^ Argument list (in this case empty)
yankee
  • 38,872
  • 15
  • 103
  • 162
  • Ah so the key part was the "single method". That's good because when I tried to let IntelliJ do an "extract local variable" it gave me `Callable>` but that didn't match the signature – Archimedes Trajano Nov 02 '19 at 22:21
  • @ArchimedesTrajano: You can also annotate your interface with `@FunctionalInterface`, then the compiler checks that the interface is suitable for use in lampda-expressions. – yankee Nov 04 '19 at 06:52