Supplier eine Function?

Hallo Forum,

beim Thema Methodenreferenzen in Java 8 bin ich über etwas gestolpert, dass ich zwar schon verwende, es aber nicht 100% verstehe. Gegeben sei folgende Klasse:


  String myString;

  /**
    * Methoden können per Methodenreferenz als Implementierung funktionaler Interfaces genutzt werden.
    * Diese Methode ist ein Supplier<String>
    */
  public String getMyString() {
    return myString;
  }

  /**
    * Methoden können per Methodenreferenz als Implementierung funktionaler Interfaces genutzt werden.
    * Diese Methode ist ein Consumer<String>
    */
  public void setMyString(String myString) {
    this.myString = myString;
  }
}```
Die Klasse implementiert kein Interface und hat mehrere nicht abstrakte Methoden. Sie ist also selbst KEINE Implementierung eines funktionalen Interfaces. Das nur als Hinweis, um Verwechslungen zu vermeiden.

Zur Verwendung der Klasse folgender Code:
```public final class Main {

  public static void main(String[] args) {
    MyBean unerTest = new MyBean();

    // 1. Übergabe einer Methodenreferenz auf einer INSTANZ von MyBean als Supplier.
    // Nichts Überraschendes
    withSupplier(underTest::getMyString);

    // 2. Übergabe einer Methodenreferenz der KLASSE MyBean
    // Hier ist ein Supplier plötzlich eine Function.
    withFunction(MyBean::getMyString);
  }

  static void withSupplier(Supplier<String> stringSupplier) {
    // do nothing, just test, if compiles
  }

  static void withFunction(Function<MyBean,String> myBeanToString) {
    // do nothing, just test, if compiles
  }
}```
Unabhängig von der Sinnhaftigkeit obigen Codes (es ist ja auch nur ein Beispiel zur Verdeutlichung): Wie wird eine Methode, die offensichtlich ein Supplier ist, zu einer Function, wenn ich eine "statische" Methodenreferenz übergebe (Punkt 2. im Code)? Was macht der Compiler da?

Der Compiler versucht einfach, “das Beste aus der Situation zu machen”: Im einen Fall hat er alles, was er braucht, um das Ding als “Supplier” anzusehen: Ein “get”, was man aufrufen kann, und was etwas liefert. Im anderen Fall, braucht er noch etwas zusätzliches, nämlich das Objekt auf dem das “get” aufgerufen werden kann - und das ist dann das Argument der Function. Der entsprechende Teil der JLS ist vermutlich Chapter 15. Expressions , aber da müßte ich genauer schauen, um mit dem Finger auf die passende Zeile zeigen zu können.

Es sind zwei unterschiedliche Dinge. Der Aufruf T::M, erzeugt ein Lambda das ein t von T als Argument übergeben bekommt. Mit dieser Notation beziehst du dich auf eine Instanzmethode von T ohne das du ein existierendes t greifbar haben musst.
Der Aufruf t::M erzeugt dir ein Lambda passend zur Instanzmethode basierend auf einem zum Zeitpunkt existierenden t also einem Objekt.

Danke für die beiden Antworten. WAS da passiert, war mir schon klar. Nur wäre ich selbst nie drauf gekommen (war Zufall, dass ich das entdeckt habe). Das WIE war mir nur völlig unverständlich. Ich werde mal Marco’s Link folgen und etwas in der JLS lesen.

Also ich hab noch keine Ahnung von Java8 aber mir kommt das ganze ein bisschen vor wie Reflection, aber eben in schöner Notation. Man kann in Reflection ja auch von einer Klasse eine Methodenreferenz erhalten.

Reflection mag eine gute Hilfe sein, Lambdas zu verstehen. Lambdas haben mit Reflection aber NICHTS zu tun. Reflection ist eine Laufzeitgeschichte. In diesem Fall befinden wir uns aber noch innerhalb der Entwicklungszeit.

*** Edit ***

Mit dem Link auf die JLS habe ich erstmal genug Infos. Ich setze das hier darum auf gelöst.