13

I read the following code in "Java - The beginner's guide"

interface SomeTest <T> { boolean test(T n, T m); } class MyClass { static <T> boolean myGenMeth(T x, T y) { boolean result = false; // ... return result; } } 

The following statement is valid

SomeTest <Integer> mRef = MyClass :: <Integer> myGenMeth; 

Two points were made regarding the explanation of the above code

1 - When a generic method is specified as a method reference, its type argument comes after the :: and before the method name.

2 - In case in which a generic class is specified, the type argument follows the class name and precedes the ::.

My query:-

The code above is the example of the first quoted point

Can someone provide me an example of code which implement the second quoted point?

(Basically I don't understand the second quoted point).

7
  • This code does not compile. Commented Jul 6, 2015 at 12:21
  • @ChetanKinger : This code will not compile as it is. First you have to add a main class in it and then put SomeTest <Integer> mRef = MyClass :: <Integer> myGenMeth; in that main class Commented Jul 6, 2015 at 12:23
  • Please post MVC code sample. As far I know, it won't compile even after we do what you said in the previous comment. Commented Jul 6, 2015 at 12:34
  • @kevingomes, unfortunately the accepted answer from Keppil is probably still not correct in the context of your actual question. While that is one form of method reference, it probably isn't what the book means in that quote. Commented Jul 6, 2015 at 14:39
  • @AndyBrown :please post the correct answer then. Commented Jul 6, 2015 at 19:08

3 Answers 3

2

The second quoted point just means that the type parameter belongs to the class. For example:

class MyClass<T> { public boolean myGenMeth(T x, T y) { boolean result = false; // ... return result; } } 

This would then be called like this:

SomeTest<Integer> mRef = new MyClass<Integer>() :: myGenMeth; 
Sign up to request clarification or add additional context in comments.

16 Comments

why can't I add static before boolean myGenMeth(T x, T y);
static would turn the method into a class method instead of an instance method. Since you have to create an instance of the class to set the type parameter here, you can't declare a static method that uses the generic class type parameter.
dude, your code isn't working; I used SomeTest <Integer> mRef = MyClass <Integer> :: genMeth;
@kevingomes It won't work because you don't have OtherClass. Keppil was hyst giving you an example. Change it to Integer :)
@ChetanKinger : I am using Integer, still it is not working
|
2

For example

 Predicate<List<String>> p = List<String>::isEmpty; 

Actually we don't need the type argument here; the type inference will take care of

 Predicate<List<String>> p = List::isEmpty; 

But in cases type inference fails, e.g. when passing this method reference to a generic method without enough constraints for inference, it might be necessary to specify the type arguments.

2 Comments

can you please tell me the difference between your answer and Keppil's answer
@Keppil unnecessarily constructs an instance of MyClass.
0

I'm also learning from that book (Java The Complete Reference Twelfth Edition)

The only way i understood the second quote, its in the code below:

interface FuncInterf<O, T> { int func(O op, T[] arr, T val); } class Operations<T> { int countMatches(T[] arr, T val) { int counter = 0; for(int i=0; i<arr.length; i++) if(arr[i] == val) counter++; return counter; } } public class Main { static <O, T> int methRef(FuncInterf<O, T> fI, O op, T[] arr, T val) { return fI.func(op, arr, val); } public static void main(String[] args) { Integer[] iArr = {1, 2, 3, 4, 3, 5}; int iVal = 3; int matches = 0; FuncInterf<Operations<Integer>, Integer> fI = Operations<Integer>::countMatches; matches = methRef(fI, new Operations<Integer>(), iArr, iVal); System.out.println("Total of " + iVal + "'s: " + matches); } } 

The interesting part is that, an extra type parameter (letter 'O') on interface FuncInterface <O, T> and also, an extra parameter (O op) on method func is needed to be able to reference the method countMatches and do what the book says:

In cases in which a generic class is specified, the type argument follows the class name and precedes the ::

Which is: Operations<Integer>::countMatches;

The reason that O op is created its because it will be the object thats going to call/reference countMatches method from methRef method in return fI.func(op, arr, val);

O will be type Operations<T>, and <T> Integer in this example. Resulting in Operations<Integer>

This kind of method reference its a 'Reference to instance method of an arbitrary object of a given type'. The method (countMatches) thats implementing Functional Interface's SAM (Single Abstract Method) doesn't need to have an extra parameter O op, because actually op its "indirectly" calling countMatches

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.