Please Explain Java 8 Method Reference to instance Method using class name

后端 未结 4 1964
栀梦
栀梦 2020-12-03 18:04
public interface MyFunc {

    boolean func(T v1, T v2);

}
public class HighTemp {

    private int hTemp;

    HighTemp(){

           


        
相关标签:
4条回答
  • 2020-12-03 18:41

    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.

    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. The above Lambda expression or the method reference both tell the interface method what to do.
    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". 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.

    0 讨论(0)
  • 2020-12-03 18:51

    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

    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

    0 讨论(0)
  • 2020-12-03 18:56

    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. Then, inside this anonymous class, we override func method which is passed two parameters. And then inside the func method, lessThanTemp method is called like this:

    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-03 19:02

    Equivalent lambda expression of HighTemp::lessThanTemp is

    (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


    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.

    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. Internally it works this way t1.ok(t2).

    So, fiFace.testMethod(t1, t2); will will invoke method as t1.ok(t2)

    0 讨论(0)
提交回复
热议问题