2015-08-29 1 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);   
    } 
} 

S'il vous plaît expliquer commentExpliquer Java 8 S'il vous plaît Méthode de référence à l'instance Méthode utilisant la classe

  1. boolean sameTemp() est compatible avec func() dans l'interface fonctionnelle.
  2. sameTemp() méthode a été implémentée sur func() dans l'interface fonctionnelle.
  3. count = counter(weekDayHighs, HighTemp::sameTemp, new HighTemp(89)); travaille

S'il vous plaît expliquer tous les points séparément.

+0

Ce code fonctionne f ine mais je ne comprends pas comment sameTemp() est compatible avec func(), quand func() a deux paramètres et sameTemp() en a un. –

+0

commentez-moi si vous ne comprenez pas ma question –

+0

Êtes-vous sûr que le code fonctionne? 'hTemp' est déclaré comme' static' donc chaque fois que vous construisez 'HighTemp' la valeur change pour toutes les instances, ce qui ferait que' count' soit toujours 0. – MirMasej

Répondre

4

expression équivalente lambda de HighTemp::lessThanTemp est

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

Ceci est l'une des caractéristiques de Java8 elle porte le nom Reference to an Instance Method of an Arbitrary Object of a Particular Type


Tenir compte exemple suivant,

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); 
    } 

} 

SORTIE

Currnet String : a 
Test String : b 

Notez ici que Test2 :: ok est valable pour la méthode appel même ok est pas statique.

Lorsque vous appelez la méthode checkCall pour l'interface fonctionnelle vous avez encore deux arguments qui sont t1 et t2 et pour cette expression lambda valide peut avoir des paramètres comme (Test t1, Test t2) de sorte que votre méthode Test2 :: ok ici devient valable pour l'appel. En interne, cela fonctionne de cette façon t1.ok(t2).

Ainsi, fiFace.testMethod(t1, t2); va invoqueront méthode comme t1.ok(t2)

+0

Monsieur, pouvez-vous m'expliquer avec un exemple d'utilisation de sous-signature dans un petit programme similaire au mien. Alors que je peux facilement comprendre, merci –

+0

Ajouter des commentaires dans le programme pour explication. Ce serait génial. –

1

Pour commencer, je ne suis pas un programmeur professionnel. J'ai aussi eu une grande difficulté à comprendre le soi-disant "Référence à une méthode d'instance d'un objet arbitraire d'un type particulier" Je pense que cela pourrait être utile pour quelqu'un qui vient ici d'une recherche google.
Je l'ai compris un peu à l'aide d'expressions lambda.

Dans votre code HighTemp::lessThanTemp comme une expression Lambda ressemblerait (x,y)->{x.lessThanTemp(y);} Le remplacement de la référence de méthode par cette expression lambda produirait le même résultat. L'expression Lambda ci-dessus ou la référence de méthode indiquent à la méthode d'interface quoi faire.
Lorsque vous utilisez la référence de méthode, elle indique à la méthode d'interface d'utiliser la méthode référencée de la classe donnée pour exécuter sa fonction.Par conséquent, si vous convertissez HighTemp::lessThanTemp en mots anglais, il semblerait que quelque chose comme "implémenter la méthode lessThanTemp forme la classe HighTemp comme l'implémentation de la fonction d'interface". Comme vous avez pu le remarquer dans ce cas, les types de retour et les types d'argument doivent être compatibles. Sinon, vous ne pouvez pas implémenter une interface.

Je voudrais vous fournir un autre exemple de code simple. D'autres exemples aident à comprendre ce concept.

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); 
    } 
} 


sortie serait:

11 
-3 


C'est le moyen le plus simple que je pouvais l'imaginer. Voyez comment les types de retour et les types d'argument sont mis en correspondance en utilisant le modèle de phrase ci-dessus. Passer du temps là-dessus.

0

Ceci est l'interface

package learninglambdaexp; 

@FunctionalInterface 
public interface TempInterface { 

    public boolean validTemp(Temperature temp); 
} 

C'est la classe

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(); 
    } 
} 

Ceci est la classe avec la principale méthode

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; 
    } 
} 

Avec un argument le plus facile à comprendre