Illuminatiiiiii
11/18/2018 - 4:02 AM

Method & Constructor References

For Episode 67 of the Java Series:

interface ISmellElephants{
    boolean elephante(int a, int b);
}
//Generic Functional Interface
interface ISmellDemons<X>{
    int doSomething(X[] array, X a); //Method that takes an array and a variable(both same type)
}
//Functional Interface that uses a constructor
interface ISmellCows{
    Cow doCowFunc(int a);
}
//A class that will hold our static method
class ElephantClass{
    static boolean elephanteMethod(int a, int b){
        if (a > b){
            return true;
        }else{
            return false;
        }
    }
}
//Class to hold the instance method
class Fart{
    boolean isLesser(int a, int b){
        if(a < b){
            return true;
        }else{
            return false;
        }
    }
}
//Class that holds our generic method implementation
class DemonClass{
    static <X> int countNumOfMatched(X[] array, X a){ //method that takes an array and a number that searches that array for that number and returns the amount of times that number is found in the array
        int num = 0; //Number of matched variables in array
        for (int i = 0;i < array.length;i++){
            if (array[i] == a){
                num++;
            }
        }
        return num;
    }
}
//Class that holds our constructors and stuff
class Cow{
    int number;
    
    Cow(int a){ //Constructor that will hook into the functional interface because the interface takes a parameter
        number = a;
    }
    Cow(){
        number = 0;
    }
    int getCowNumber(){
        return number;
    }
}
public class Main {

    public static void main(String[] args){


//        ISmellElephants y33t = (int a, int b) -> {
//            return ElephantClass.elephanteMethod(a, b);
//        };
        ISmellElephants y33t = ElephantClass::elephanteMethod; //This line is a simplification for the line above
        System.out.println(y33t.elephante(5, 3));

        //Instead of directly using a lambda to provide the implementation for our functional interface,
        //we plug in a statis method reference that serves as our lambda expression, like we might do with
        //lambda object reference
        boolean result = anotherMethod(ElephantClass::elephanteMethod, 24, 1);
        System.out.println(result);

        //Example with an instance method
        Fart yummyfart = new Fart();
        boolean result2 = anotherMethod(yummyfart::isLesser, 7, 6); //Notice we use the object in front of the method name this time because its not a static method anymore
        System.out.println(result2);

        //An example with a generic method
        String[] stringsArray = {"yes", "no", "booty", "no", "yes", "yes"};
        Integer[] integersArray = {1, 4, 1, 4, 1, 5, 2, 12, 1231};
        int matches1 = anotherAnotherMethod(DemonClass::<String>countNumOfMatched, stringsArray, "yes");
        System.out.println(matches1);
        int matches2 = anotherAnotherMethod(DemonClass::<Integer>countNumOfMatched, integersArray, 11);
        System.out.println(matches2);

        //Finally, an example using a constructor
        ISmellCows cows = Cow::new; //Constructor Reference. The abstract method and constructor are now linked
        Cow cowObject = cows.doCowFunc(20); //Running the constructor and creating an object by calling upon the functional interface method
        System.out.println(cowObject.getCowNumber()); //Calling the method within the Cow class
    }

    //Here is an example of a method that takes a lambda as a parameter
    static boolean anotherMethod(ISmellElephants elephantInterface, int a, int b){
        return elephantInterface.elephante(a, b);
    }
    //Method using our generic functional interface as a parameter
    static <X> int anotherAnotherMethod(ISmellDemons<X> demonInterface, X[] array, X a){
        return demonInterface.doSomething(array, a);
    }
}