Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to an instance method of a particular object breaks the type-safety in Java?

Does the notion of a reference to an instance method of a particular object break the type-safety in Java?

According to

https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

you can have a custom class ComparisonProvider that DOES not implement the Comparator interface, and still use an instance of this class as the second argument of the method

Arrays.sort(T[] a, Comparator c)

Sure, the implementation of your ComparisonProvider MUST have a method whose signature exactly matches the Comparator.compare() method, but that is still not an instance of Comparator, isn't it?

In essence, Java 8 allows us to use instances of classes as if they were implementing a particular interface, while actually they are not.

This means, that we are loosing Type-safety in Java, do we?

like image 599
Alex Mi Avatar asked Jun 09 '17 06:06

Alex Mi


1 Answers

lambda expressions and method reference don't have a predefined type, they are poly expressions, as seen here. That means that their type is derived from the context in which they are used.

In your example these both would be legal for example:

 BiFunction<Person, Person, Integer> biFun = myComparisonProvider::compareByName;

 Comparator<Person> comp = myComparisonProvider::compareByName;

But at the same time you can't do:

Arrays.sort(pers, biFun);

When you actually try to sort the array like this:

Arrays.sort(pers, myComparisonProvider::compareByName);

At the bytecode level that is a Comparator:

// InvokeDynamic #0:compare:(LTest$ComparisonProvider;)Ljava/util/Comparator;

Also notice that this would print true:

Comparator<Person> comp = myComparisonProvider::compareByName;
System.out.println(comp instanceof Comparator); // true

You can enable a flag : -Djdk.internal.lambda.dumpProxyClasses=/Your/Path/Here

and look at what that method reference is transformed into:

final class Test$$Lambda$1 implements java.util.Comparator

and inside it there's the compare method implementation(I've simplified it and removed some of it's code to make it a little more obvious):

public int compare(java.lang.Object, java.lang.Object);
Code:
     4: aload_1
     5: checkcast // class Test3$Person
     8: aload_2
     9: checkcast // class Test$Person
    12: invokevirtual Test$ComparisonProvider.compareByName:(Test$Person;Test$Person;)I
like image 133
Eugene Avatar answered Sep 25 '22 04:09

Eugene