2015-08-29 11 views
6
public interface MyFunc<T> { 

    boolean func(T v1, T v2); 

} 
public class HighTemp { 

    private int hTemp; 

    HighTemp(){ 

    } 
    public HighTemp(int ht) { 
     this.hTemp = ht; 
    } 

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

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

    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; 
     //Create an array of HighTemp objects. 
     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::lessThanTemp,new HighTemp(89));  
     System.out.println(count);   
    } 
} 

Proszę wyjaśnić, w jaki sposóbproszę wyjaśnić Java 8 metody referencyjnej do instancji metoda z użyciem nazwy klasy

  1. boolean sameTemp() jest kompatybilny z func() w interfejsie funkcjonalne.
  2. sameTemp() metoda została zaimplementowana na func() w interfejsie funkcjonalnym.
  3. count = counter(weekDayHighs, HighTemp::sameTemp, new HighTemp(89)); pracuje

proszę wyjaśnić wszystkie punkty oddzielnie.

+0

Ten kod działa na ale nie rozumiem, w jaki sposób metoda ta jest zgodna z func(), kiedy func() ma dwa parametry, a ten sam atrybut() ma. –

+0

skomentuj, jeśli nie rozumiesz mojego pytania –

+0

Czy na pewno działa kod? 'hTemp' jest zadeklarowany jako 'static', więc za każdym razem gdy skonstruujesz' HighTemp', wartość zmieni się dla wszystkich instancji, co spowoduje, że 'count' będzie zawsze 0. – MirMasej

Odpowiedz

4

Equivalent lambda wyrażenie HighTemp::lessThanTemp jest

(highTemp1, highTemp2) -> { 
    return highTemp1.lessThanTemp(highTemp2); 
} 

Jest to jedna z cech Java8 nazwanych Reference to an Instance Method of an Arbitrary Object of a Particular Type


Rozważmy następujący przykład,

interface FIface<T> { 
    int testMethod(T a, T b); 
} 

class Test2 { 

    private String str; 

    Test2(String str) { 
     this.str = str; 
    } 

    int ok(Test2 test2) { 
     System.out.println("Currnet String : "+ this.str);//Refer to t1 
     System.out.println("Test String : "+test2.str);//Refer to t2 
     return 0; 
    } 

} 

public class Test { 

    public static <T> int checkCall(T t1, T t2, FIface<T> fiFace) { 
     //Here Test2 :: ok is equivalent to t1.ok(t2) 
     return fiFace.testMethod(t1, t2); 
    } 

    public static void main(String[] args) { 
     checkCall(new Test2("a"), new Test2("b"), Test2 :: ok); 
    } 

} 

WYJŚCIE

Currnet String : a 
Test String : b 

Uwaga tutaj Test2 :: ok jest ważna dla wywołania nawet ok metoda nie jest statyczny.

Po wywołaniu metody checkCall dla interfejsu funkcjonalnego wciąż masz dwa argumenty, które są t1 i t2 a do tego ważnego wyrażenia lambda może mieć parametry (Test t1, Test t2) więc metoda Test2 :: ok tutaj staje się ważna dla wywołania. Wewnętrznie działa w ten sposób t1.ok(t2).

Więc fiFace.testMethod(t1, t2); będzie wywoła metodę jako t1.ok(t2)

+0

Panie, czy możesz mi wytłumaczyć na przykładzie użycia podpisu w małym programie podobnym do mojego. Tak, że mogę łatwo zrozumieć, dzięki –

+0

Dodaj komentarze w programie dla wyjaśnienia. To byłoby wspaniale. –

1

Na początek nie jestem profesjonalnym programistą. Ja też miałem wielką trudność w zrozumieniu tak zwanej "Odniesienia do metody instancji obiektu arbitralnego określonego typu" Myślę, że to może być pomocne dla kogoś, kto przychodzi tutaj z wyszukiwarki Google.
Rozumiałem to trochę z pomocą wyrażeń lambda.

W kodzie HighTemp::lessThanTemp jako wyrażenie Lambda będzie wyglądać (x,y)->{x.lessThanTemp(y);} Zastąpienie odwołania do metody tym wyrażeniem lambda spowoduje uzyskanie tego samego wyniku. Powyższe wyrażenie Lambda lub odwołanie do metody informują zarówno metodę interfejsu, co zrobić.
Podczas korzystania z metody reference informuje metodę interfejsu, aby używała określonej metody z danej klasy, do wykonywania jej funkcji.Dlatego jeśli konwertujesz HighTemp::lessThanTemp na angielskie słowa, brzmi to jak "implementuj metodę lessThanTemp z klasy HighTemp jako implementację funkcji interfejsu". Jak mogłeś zauważyć, w tym przypadku typy zwracane i typy argumentów powinny być zgodne. W przeciwnym razie nie można zaimplementować interfejsu.

Chciałbym podać inny prosty przykładowy kod. Więcej przykładów pomaga zrozumieć tę koncepcję.

interface myint{ 
    int returnit(Test t ,int y); 
} 
class Test{ 
    int x=0; 
    public Test(int x){ 
     this.x=x; 
    } 

    public int addNumbers(int y){ 
     return x+y; 
    } 
    public int subtractNumbers(int y){ 
     return x-y; 
    } 

} 

public class myclass{ 
    private static void myMethod(Test t,myint inf,int y){ 
     int x=inf.returnit(t, y); 
     System.out.println(x+""); 
    } 
    public static void main(String[] args){ 
     myMethod(new Test(4),Test::addNumbers,7); 
     myMethod(new Test(4),Test::subtractNumbers,7); 
    } 
} 


wyjściowy będzie:

11 
-3 


Jest to najprostszy sposób mogę to sobie wyobrazić. Zobacz, jak typy powrotu i typy argumentów są dopasowywane za pomocą powyższego wzorca zdania. Poświęć na to trochę czasu.

0

Jest to interfejs

package learninglambdaexp; 

@FunctionalInterface 
public interface TempInterface { 

    public boolean validTemp(Temperature temp); 
} 

Jest to klasa

package learninglambdaexp; 

public class Temperature { 

    private int temp; 

    public Temperature(int temp) { 
     this.temp = temp; 
    } 

    public boolean isEvenTemp() { 
     return temp % 2 == 0; 
    } 

    public boolean isOddTemp(){ 
    return !isEvenTemp(); 
    } 
} 

Jest to klasa z metody Main

package learninglambdaexp; 

import java.util.ArrayList; 
import java.util.List; 

public class AnotherMainClass { 

    public static void main(String[] args) { 

     List<Temperature> tempCollection = new ArrayList<>(); 
     tempCollection.add(new Temperature(100)); 
     tempCollection.add(new Temperature(20)); 
     tempCollection.add(new Temperature(30)); 
     tempCollection.add(new Temperature(40)); 
     tempCollection.add(new Temperature(50)); 
     tempCollection.add(new Temperature(60)); 
     tempCollection.add(new Temperature(70)); 
     int k1 = countVariation(tempCollection, Temperature::isEvenTemp); 
     //int k2 = countVariation(Temperature::lowTemp); 
     System.out.println(k1); 
     // System.out.println(k2); 
    } 

    private static int countVariation(List<Temperature> tempCollection, TempInterface ti) { 
     int count = 0; 
     for (Temperature eachTemp : tempCollection) { 
      if (ti.validTemp(eachTemp)) { // (eachTemp) -> {return eachTemp.isEvenTemp();}; 
       count++; 
      } 
     } 
     return count; 
    } 
} 

Z jednym argumentem jej łatwiej zrozumieć

Powiązane problemy