• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Using charAt() by method reference

 
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I was studying through the Practice Test book by Scott Selikoff and Jeanne Boyarsky. I was going through the chapter on Generics and Collections where I found a question like :

Why can't String::charAt be used as a method refernce ?



The answer given in the book was..

Method references can pass either the instance or the parameter from the lambda,but not both.



The answer was further explained in the solutions as...

With method references, only one item can be supplied at runtime. Here, we need either a String instance with no parameter in the method or a static method with a single parameter. The charAt() method is an instance method with a single parameter so does not meet this requirement.



I did not understand the answer given so I decided to try it out and I wrote this code...



The code runs fine and output is as expected but what I understand is the book says that charAt() method cannot be used via method references... I am confused.
Where am I going wrong ? or is their a mistake in the book ?
 
Saloon Keeper
Posts: 15485
363
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, you didn't actually use String::charAt, right? You used str::charAt, thereby already supplying one of the arguments.

Put a String parameter before your int parameter in the test method, and then assign String::charAt to ob, and see what happens.
 
Bartender
Posts: 5465
212
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, the statement in the book seems incorrect. As Stephan mentions, the String::charAt is a BiFunction that takes two input parameters.

Now, in a java 8 stream, you will usually have only one parameter available, and thus you can't use the String::charAt reference. But if you use a concrete String (like you did), then you have a method with only one parameter, and thus it can be used in a stream.
For instance:

But for the two-parameter String::charAt, this is possible:
 
Arpan Ghoshal
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
From what I understand we cannot use String::charAt() because charAt() is an instance method, if it was a static method we could have written String::charAt() directly.
This is why I created a String instance str and then called charAt() on it.

I can even do this..

Do I understand correctly ?
 
Arpan Ghoshal
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:Well, you didn't actually use String::charAt, right? You used str::charAt, thereby already supplying one of the arguments.

Put a String parameter before your int parameter in the test method, and then assign String::charAt to ob, and see what happens.



I tried what you said and it did work...


But I don't understand why this works. I thought chartAt() needed only one parameter that is
public char charAt(int index)
The String is not a parameter, it is known to charAt() from the currently calling instance.
Does charAt() have an overloaded static version like .. static char charAt(String str,int index) ?  
 
Piet Souris
Bartender
Posts: 5465
212
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Suppose you have a function f(x, y) = x + y. This is a function of two parameters x and y. Now, suppose that x is given in some way. We get then the one parameter function g(y) = f(X, y). The same goes for String.charAt. It takes two parameters, namely the String of which we want to know the char at some position, and the position.

Your Char_At is a functional interface taking twp parameters, a String and an int. This is not unlike the BiFunction interface from java 8.
You can instantiate this interface in two ways (well, actually three ways):

and what you do:

In the second case, java substitutes the two arguments neatly into the right places. As said, these two ways are equivalent! Perhaps the first way is more clear in the beginning, because you literally see the two parameters specified, but it it is just a matter of time before you start using the second form.
Suppose you had defined the Char_At interface like this:

Then this would still work:

Would the second form work in this case?

Again, String::charAt is a function of two parameters, and is equivalent to: (String s, int t) -> s.charAt(t); In line 11 you neatly supply the two parameters that the String::charAt expects.
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I almost forgot:
You wrote:

Can you explain why this is different than the other Char_At? How many parameters do we have here?
 
Arpan Ghoshal
Ranch Hand
Posts: 52
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:
Would the second form work in this case?


It does not work and gives an error stating..  no suitable method found for charAt(int,String)

Piet Souris wrote:
Can you explain why this is different than the other Char_At? How many parameters do we have here?



Here we first pass the first argument that is the String when we write  Char_At ob="String"::charAt  and later we pass the second argument that is the index when we write ob.test(2).
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This version of Char_At describes just one input parameter (int a). So, your formulation of 'passing a String first, and an int later' is hard to place.

I would say. Can you write 'Char_At ob = <method reference>' in the form of  'Char_At ob = (parameters list) -> result'? And then format your question again?
 
reply
    Bookmark Topic Watch Topic
  • New Topic