2016-09-11 1 views
1

Ich versuche, das die folgende Methode Referenzcode verstehen mit Lambda-Ausdrücke in Java:Java Lambda Ausdruck Parameter

interface MyFunc<T> { 

    boolean func(T v1, T v2); 
} 

class HighTemp { 

    private int hTemp; 

    HighTemp(int ht) { 
     hTemp = ht; 
    } 

    boolean sameTemp(HighTemp ht2) { 
     return hTemp == ht2.hTemp; 
    } 

    boolean lessThanTemp(HighTemp ht2) { 
     return hTemp < ht2.hTemp; 
    } 
} 

class InstanceMethWithObjectRefDemo { 

    static <T> int counter(T[] vals, MyFunc<T> f, T v) { 
     int count = 0; 
     for (int i = 0; i < vals.length; i++) { 
      if (f.func(vals[i], v)) { 
       count++; 
      } 
     } 
     return count; 
    } 

    public static void main(String args[]) { 
     int count; 

     HighTemp[] weekDayHighs = {new HighTemp(89), new HighTemp(82), 
      new HighTemp(90), new HighTemp(89), 
      new HighTemp(89), new HighTemp(91), 
      new HighTemp(84), new HighTemp(83)}; 

     count = counter(weekDayHighs, HighTemp::sameTemp, 
       new HighTemp(89)); 
     System.out.println(count + " days had a high of 89"); 

     HighTemp[] weekDayHighs2 = {new HighTemp(32), new HighTemp(12), 
      new HighTemp(24), new HighTemp(19), 
      new HighTemp(18), new HighTemp(12), 
      new HighTemp(-1), new HighTemp(13)}; 

     count = counter(weekDayHighs2, HighTemp::sameTemp, 
       new HighTemp(12)); 
     System.out.println(count + " days had a high of 12"); 

     count = counter(weekDayHighs, HighTemp::lessThanTemp, 
       new HighTemp(89)); 
     System.out.println(count + " days had a high less than 89"); 

     count = counter(weekDayHighs2, HighTemp::lessThanTemp, 
       new HighTemp(19)); 
     System.out.println(count + " days had a high of less than 19"); 
    } 
} 

Meine Frage ist, warum Funktion sameTemp nur einen Parameter hat? Die Schnittstelle deklariert, dass sie 2 Parameter haben muss, also ergibt das für mich keinen Sinn. Vielleicht reicht die hTemp-Instanzvariable für beide aus? Ich habe dies aus Java die komplette Nachschlagewerk und gibt der Autor erklärt dies:

Blockquote

Im Programm feststellen, dass HighTemp zwei Instanzmethoden hat: sameTemp( ) und lessThanTemp( ). Die erste gibt true zurück, wenn zwei HighTemp-Objekte die gleiche Temperatur enthalten. Die zweite gibt true zurück, wenn die Temperatur des aufrufenden Objekts kleiner als die des übergebenen Objekts ist. Jede Methode hat einen Parameter vom Typ HighTemp und jedes Metoreturn ein boolesches Ergebnis. Daher ist jedes mit der MyFunc-Funktionsschnittstelle kompatibel, weil der aufrufende Objekttyp dem ersten Parameter von func( ) und dem -Argument zugeordnet werden kann, das dem zweiten Parameter func( ) zugeordnet ist.

Vielen Dank!

+2

Siehe auch http://stackoverflow.com/questions/32855138/how-does-a-method-reference-to-an-instance-method-of-an-ibitrary- object-of-ap und http://stackoverflow.com/questions/23139725/using-method-reference-instead-of-multi-argument-lambda und http: // stackoverflow.com/questions/22516331/whats-the-difference-zwischen-instance-method-reference-types-in-java-8 (und http://stackoverflow.com/questions/37037015/why-stringbuilderappend-is-biconsumerstringbuilder-string) – Tunaki

Antwort

10

Was viele Leute bei der OO-Programmierung übersehen, ist ... wie das wirklich umgesetzt wird. Es sei angenommen:

class C { 
    public int foo(int parm) { return parm; } 

Der Punkt ist: die Idee der Aufruf einer Methode „auf“ ein Objekt ist eine Abstraktion . Wie würdest du das in Assembler implementieren? damit eine CPU diesen Code tatsächlich ausführen kann. Du erkennst: "Anrufen" ist dort nicht möglich. Auf dieser Ebene rufen Sie nur Funktionen irgendwo im Speicher auf. Aber wie würde eine Funktion über ihr eigenes Objekt wissen ?!

Führende zu etwas, das nur wenige Menschen wissen - Sie den obigen Code schreiben können, wie:

class C { 
    public int foo(C this, int i) { 
     System.out.println("i: " + i); 
     return i; 
    } 
} 

auf der sicheren Seite zu sein, schrieb ich auch einen kleinen Test in Eclipse für die:

@Test 
public void testIt() { 
    assertThat(new C().foo(5), is(5)); 
} 

Läuft in meiner Eklipse, Einheit Test bestanden und druckt "i: 5".

So ist das ganze Geheimnis: wenn Methoden auf einem Objekt definiert wird, gibt es immer ein (normalerweise unsichtbares) erstes Argument "this", das dieser Methode gegeben wird!

Also: Obwohl Ihre Methoden aussehen wie nur einen Parameter zu nehmen, ist der "fehlende" Parameter das Objekt, auf dem Sie die Methode aufrufen!

Und in diesem Sinne: boolean func(T v1, T v2) bittet um zwei Parameter des Typs T. Und beide Methoden, wie boolean sameTemp(HighTemp ht2) ... als boolean sameTemp(HighTemp this, HighTemp ht2) geschrieben werden können; et voila: zwei Parameter des Typs T.

Verwandte Themen