简体   繁体   English

请解释 Java 8 方法引用实例 方法使用 class 名称

[英]Please Explain Java 8 Method Reference to instance Method using class name

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

Please explain how请说明如何

  1. boolean sameTemp() is compatible with func() in Functional interface. boolean sameTemp()与功能接口中的func()兼容。
  2. sameTemp() method got implemented on func() in Functional Interface. sameTemp()方法在功能接口中的func()上实现。
  3. count = counter(weekDayHighs, HighTemp::sameTemp, new HighTemp(89)); is working正在工作中

Please Explain All points separately.请分别解释所有要点。

Equivalent lambda expression of HighTemp::lessThanTemp is HighTemp::lessThanTemp 等效 lambda表达式为

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

This is one of the features of Java8 named Reference to an Instance Method of an Arbitrary Object of a Particular Type 这是Java8的功能之一,名为对特定类型的任意对象的实例方法的引用


Consider following example, 考虑以下示例,

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

}

OUTPUT 输出值

Currnet String : a
Test String : b

Note here that Test2 :: ok is valid for the call even ok method is not static. 请注意,即使ok方法不是静态的, Test2 :: ok对于调用也是有效的。

When you call the method checkCall for the functional interface you still have two arguments which are t1 and t2 and for that valid lambda expression can have parameters as (Test t1, Test t2) so your method Test2 :: ok here becomes valid for the call. 当您为功能接口调用方法checkCall ,您仍有两个参数t1t2并且该有效lambda表达式的参数可以为(Test t1, Test t2)因此您的方法Test2 :: ok在此处对调用有效。 Internally it works this way t1.ok(t2) . 在内部,它以t1.ok(t2)方式工作。

So, fiFace.testMethod(t1, t2); 因此, fiFace.testMethod(t1, t2); will will invoke method as t1.ok(t2) 将调用方法为t1.ok(t2)

For starters I'm not a professional programmer. 对于初学者来说,我不是专业的程序员。 I too had a great difficulty in understanding the so called " Reference to an Instance Method of an Arbitrary Object of a Particular Type " I think this might be helpful for somebody who comes here from a google search. 我也很难理解所谓的“ 对特定类型的任意对象的实例方法的引用 ”,我认为这可能对来自谷歌搜索的人有所帮助。
I understood it a little bit with the help of lambda expressions. 在lambda表达式的帮助下,我对此有所了解。

In your code HighTemp::lessThanTemp as a Lambda expression would look like (x,y)->{x.lessThanTemp(y);} Replacing the method reference with this lambda expression would produce the same result. 在您的代码HighTemp::lessThanTemp作为Lambda表达式将看起来像(x,y)->{x.lessThanTemp(y);} ,用此lambda表达式替换方法引用将产生相同的结果。 The above Lambda expression or the method reference both tell the interface method what to do. 上面的Lambda表达式或方法参考都告诉接口方法该做什么。
When you use the method reference it tells the interface method to use the referred method from the given class, to carryout its function. 当您使用方法引用时,它会告诉接口方法使用给定类中的引用方法来执行其功能。 Therefore if you convert HighTemp::lessThanTemp to English words it would sound something like " implement the lessThanTemp method form the class HighTemp as the implementation of the interface function ". 因此,如果将HighTemp::lessThanTemp转换为英语单词,听起来会像是“ 从类HighTemp实现lessThanTemp方法作为接口函数的实现 ”。 As you might've noticed in that case the return types and the argument types should be compatible. 如您可能已经注意到的那样,返回类型和参数类型应该兼容。 Otherwise you cannot implement an interface. 否则,您将无法实现接口。

I would provide you another simple example code. 我将为您提供另一个简单的示例代码。 More examples helps to understand this 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);
    }
}


Output would be: 输出为:

11
-3


This is the simplest way I could imagine it. 这是我能想到的最简单的方法。 See how return types and argument types gets matched using the above sentence pattern. 了解如何使用上述句子模式匹配返回类型和参数类型。 Spend some time on it. 花一些时间。

This is the Interface 这是接口

package learninglambdaexp;

@FunctionalInterface
public interface TempInterface {

    public boolean validTemp(Temperature temp);
}

This is the class 这是班

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

This is the Class with the Main Method 这是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;
    }
}

With one argument its easier to understand 一个论点更容易理解

Please, correct me if I am wrong, but the way I think about this type of method references ( Reference to an Instance Method of an Arbitrary Object of a Particular Type ) is that when we pass a method reference, in this case to the counter method, the instance of anonymous class which implements MyFunc interface is created. 请纠正我,如果我错了,但是我对这种类型的方法引用( 对特定类型的任意对象的实例方法的引用)的思考方式是,当我们将方法引用传递给计数器时方法,创建实现MyFunc接口的匿名类的实例。 Then, inside this anonymous class, we override func method which is passed two parameters. 然后,在这个匿名类中,我们重写了传递两个参数的func方法。 And then inside the func method, lessThanTemp method is called like this: 然后在func方法内部, lessThanTemp方法被这样调用:

v1.lessThanTemp(v2); 

So for me this concept looks something like this: 所以对我来说,这个概念看起来像这样:

public class Demo {
    public static void main(String[] args) {
        AnonymousClass an = new AnonymousClass();
        System.out.println(an.apply(new SomeClass(3), 4));
    }
}
interface SomeInterface {
    int apply(SomeClass obj, int n);
}

class SomeClass {
    private int n;

    SomeClass(int n) {
        this.n = n;
    }

    int add(int n) {
        return this.n + n;
    }
}
class AnonymousClass implements SomeInterface {

    @Override
    public int apply(SomeClass o, int n) {
        return o.add(n);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM