Thursday, August 18, 2016

Java 8 Method References explained in 5 minutes

At IDR Solutions I spend alot of time on working on the development of our Java PDF Library. As I spend alot of time using Java 8 in our JavaFX PDF Viewer I thought that it might be useful to a series article of the new features in JDK8.

In my previous articles, we have looked at Lambda Expression, Streams API and Default Methods. In this latest article in the series, we will be looking at Method References.

What is Method References?
It is a feature which is related to Lambda Expression. It allows us to reference constructors or methods without executing them. Method references and Lambda are similar in that they both require a target type that consist of a compatible functional interface.

Types of Method Reference
There are four types of method reference, the table below summarizes this.


I will explain further about the four types of method referenced in the table.

1 . Reference to a Static Method
  1. public class ReferenceToStaticMethodExample {
  2.      /**
  3.      * @param args the command line arguments
  4.      */
  5.     public static void main(String[] args) {
  6.         List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16);
  7.         List primeNumbers = ReferenceToStaticMethodExample.findPrimeNumbers(numbers, 
  8.                 (number) -> ReferenceToStaticMethodExample.isPrime((int) number));
  9.  
  10.         System.out.println("Prime Numbers are " + primeNumbers);
  11.     }
  12.  
  13.     public static boolean isPrime(int number) {
  14.         if (number == 1) {
  15.             return false;
  16.         }
  17.         for (int i = 2; i < number; i++) {             
  18.             if (number % i == 0) {                 
  19.                 return false;             
  20.             }         }         
  21.         return true;     
  22.     }     
  23.  
  24.     public static List findPrimeNumbers(List list, Predicate predicate) {         
  25.         List sortedNumbers = new ArrayList();         
  26.         list.stream().filter((i) -> (predicate.test(i))).forEach((i) -> {
  27.             sortedNumbers.add(i);
  28.         });
  29.         return sortedNumbers;
  30.  
  31.     }
  32. }
As you can see in this code, we made reference to a static method in this class.

ContainingClass::staticMethodName


2. Reference To Constructor
  1. public class ReferenceToConstructor {
  2.  
  3.     /**
  4.      * @param args the command line arguments
  5.      */
  6.     public static void main(String[] args) {
  7.         // TODO code application logic here
  8.          List  numbers = Arrays.asList(4,9,16,25,36);
  9.          List squaredNumbers = ReferenceToConstructor.findSquareRoot(numbers,Double::new);
  10.          System.out.println("Square root of numbers = "+squaredNumbers);
  11.     }
  12.  
  13.     private static List findSquareRoot(List list, Function<double,double -> f){
  14.         List result = new ArrayList();
  15.         list.forEach(x -> result.add(f.apply(Math.sqrt(x))));
  16.         return result;
  17.     }
  18. }
This is very similar to reference to to a static method.The difference between the two is, the constructor reference method name is new.


3. Reference To an Instance Method Of An Arbitrary Object Of A Particular Type
  1. public class ReferenceToInstanceMethodAOPT {
  2.  
  3.     /**
  4.      * @param args the command line arguments
  5.      */
  6.  
  7.      private static class Person {
  8.  
  9.             private final String name;
  10.             private final int age;
  11.  
  12.  
  13.             public Person(String name, int age) {
  14.                 this.name = name;
  15.                 this.age = age;
  16.  
  17.             }
  18.  
  19.             public String getName() {
  20.                 return name;
  21.             }
  22.  
  23.             public int getAge() {
  24.                 return age;
  25.             }
  26.  
  27.  
  28.         }
  29.     public static void main(String[] args) {
  30.         // TODO code application logic here
  31.         List persons = new ArrayList();
  32.             persons.add(new Person("Albert", 80));
  33.             persons.add(new Person("Ben", 15));
  34.             persons.add(new Person("Charlote", 20));
  35.             persons.add(new Person("Dean", 6));
  36.             persons.add(new Person("Elaine", 17));
  37.  
  38.  
  39.             List allAges = ReferenceToInstanceMethodAOPT.listAllAges(persons, Person::getAge);
  40.             System.out.println("Printing out all ages \n"+allAges);
  41.     }
  42.  
  43.  
  44.     private static List listAllAges(List person, Function < person, integer="" -> f){
  45.         List result = new ArrayList();
  46.         person.forEach(x -> result.add(f.apply(x)));
  47.         return result;
  48.     }
  49. }
This mean providing reference to any of the persons object in the List of a particular type which is the Person.So the containing type is persons and the method name is getAge();


4. Reference To An Instance Method Of A Particular Object
  1. public class ReferenceToInstanceMethodOAPO {
  2.  
  3.     /**
  4.      * @param args the command line arguments
  5.      */ 
  6.     public static void main(String[] args) {
  7.         // TODO code application logic here
  8.         List names = new ArrayList();
  9.             names.add("David");
  10.             names.add("Richard");
  11.             names.add("Samuel");
  12.             names.add("Rose");
  13.             names.add("John");
  14.  
  15.            ReferenceToInstanceMethodOAPO.printNames(names,System.out::println);
  16.     }
  17.   
  18.     private static void printNames(List list, Consumer c ){
  19.         list.forEach(x -> c.accept(x));
  20.     }
  21. }
Since System.out is an instance of type PrintStream, we then call println method of the instance.


So what can we Take Away?
  1. You can use replace Lambda Expressions with Method References where Lamdba is invoking already defined methods.
  2. You can’t pass arguments to methods Reference
  3. To use Lambda and Method Reference, make sure you have Java 8 installed. They do not work on Java 7 and earlier versions.
Hopefully you have found this quick guide useful
Written by Ernest Duodu

If you found this post interesting, follow and support us.
Suggest for you:

The Complete Java Developer Course

Java Programming For Beginners

Complete Java For Selenium WebDriver And Test Automation

The Complete Android & Java Course - Build 21 Android Apps

Java for Android Development - Getting Started (Khmer)

No comments:

Post a Comment