请使用类名解释Java 8方法参考实例方法

时间:2015-08-29 07:46:10

标签: java java-8 method-reference functional-interface

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

请解释如何

  1. boolean sameTemp()与功能界面中的func()兼容。
  2. sameTemp()方法已在功能界面的func()上实施。
  3. count = counter(weekDayHighs, HighTemp::sameTemp, new HighTemp(89));正在运作
  4. 请分别解释所有要点。

5 个答案:

答案 0 :(得分:6)

HighTemp::lessThanTemp的等效 lambda表达式是

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

这是名为Reference to an Instance Method of an Arbitrary Object of a Particular Type

Java8的功能之一

考虑以下示例,

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

}

<强>输出

Currnet String : a
Test String : b

请注意,Test2 :: ok对呼叫有效,即使ok方法不是静态的。

当您为函数接口调用方法checkCall时,您仍然有两个参数t1t2,对于该有效的lambda表达式,参数可以为(Test t1, Test t2)所以你的方法Test2 :: ok在这里对呼叫有效。在内部,它以这种方式工作t1.ok(t2)

因此,fiFace.testMethod(t1, t2);将调用方法t1.ok(t2)

答案 1 :(得分:2)

首先,我不是专业程序员。我也非常难以理解所谓的&#34; 对特定类型的任意对象的实例方法的引用 &#34;我认为这可能对从谷歌搜索来到这里的人有所帮助 我在lambda表达的帮助下理解了一点。

在代码HighTemp::lessThanTemp中,Lambda表达式看起来像(x,y)->{x.lessThanTemp(y);}用这个lambda表达式替换方法引用会产生相同的结果。上面的Lambda表达式或方法引用都告诉接口方法要做什么。
当您使用方法引用时,它告诉接口方法使用给定类中的refer方法来执行其功能。因此,如果您将HighTemp::lessThanTemp转换为英语单词,它会听起来像&#34; 实现lessThanTemp方法形成类HighTemp作为接口函数的实现&#34 ;.正如您可能已经注意到的那样,返回类型和参数类型应该是兼容的。否则您无法实现接口。

我会提供另一个简单的示例代码。更多示例有助于理解这一概念。

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

输出将是:

11
-3

这是我能想象到的最简单的方式。了解如何使用上述句型匹配返回类型和参数类型。花些时间在上面。

答案 2 :(得分:0)

这是界面

package learninglambdaexp;

@FunctionalInterface
public interface TempInterface {

    public boolean validTemp(Temperature temp);
}

这是班级

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

这是使用主要方法的类

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

有一个论点更容易理解

答案 3 :(得分:0)

Java 8允许我们使用称为方法引用的::直接引用具有类和方法名称的方法。

java中有四种不同的方法引用方式

  1. 静态方法参考
  2. 对象方法参考
  3. 按类类型引用实例方法
  4. 构造函数参考

Using Lambda Expression

 (s) -> System.out.println(s)

Using Method Reference

   System.out::println

有关更多详细信息,请访问What is method reference in java?

答案 4 :(得分:0)

请纠正我,如果我错了,但是我对这种类型的方法引用(对特定类型的任意对象的实例方法的引用)的思考方式是:一个方法引用(在这种情况下为 counter 方法),将创建实现 MyFunc 接口的匿名类的实例。然后,在这个匿名类中,我们重写了传递两个参数的 func 方法。然后在 func 方法中,如下调用 lessThanTemp 方法:

v1.lessThanTemp(v2); 

所以对我来说,这个概念看起来像这样:

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