About Question enthuware.ocpjp.v8.2.1789 :
Moderator: admin
-
- Posts: 3
- Joined: Tue Jun 20, 2017 3:10 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
If I add any argument to the printNames method, for example:
public void printNames(String hola){
System.out.println(getList());
}
It still doesn't compile because the compiler can't infer from the context what instance of printNames to use (printNames is not a static method). I got the error:
error: incompatible types: invalid method reference
n.getList().forEach(Names::printNames);
cannot find symbol
symbol: method printNames(String)
location: class Names
But if I change the last sentence to: n.getList().forEach(n::printNames);
then it does compile.
So the reason why it doesn't compile is not only that the forEach method requires a method that takes an argument. Correct me if I am wrong.
public void printNames(String hola){
System.out.println(getList());
}
It still doesn't compile because the compiler can't infer from the context what instance of printNames to use (printNames is not a static method). I got the error:
error: incompatible types: invalid method reference
n.getList().forEach(Names::printNames);
cannot find symbol
symbol: method printNames(String)
location: class Names
But if I change the last sentence to: n.getList().forEach(n::printNames);
then it does compile.
So the reason why it doesn't compile is not only that the forEach method requires a method that takes an argument. Correct me if I am wrong.
-
- Site Admin
- Posts: 10065
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
Yes, that could also be a valid reason.
If you like our products and services, please help us by posting your review here.
-
- Posts: 125
- Joined: Thu Jul 05, 2018 6:44 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
I think this is quite an important concept.
We have learnt from other questions that you can supply a INSTANCE method reference of the form X::foo, where foo takes no parameters, as an argument to a method (call it bar) that expects a method that takes a parameter, and the compiler is smart enough to recognise that an instance of X will be the required parameter, but it only works if what's going into bar is the same type as X.
That sounds a bit like gobbledegook but I can see now why this works:
but this doesn't
ie it's because getList supplies a String; so you can either supply any method reference X::xyz where xyz takes a String or you can supply a reference to a no-arg instance method of String in which String becomes the required argument corresponding to apply(T t).
Of course you could supply any one-arg static method that takes a String also.
We have learnt from other questions that you can supply a INSTANCE method reference of the form X::foo, where foo takes no parameters, as an argument to a method (call it bar) that expects a method that takes a parameter, and the compiler is smart enough to recognise that an instance of X will be the required parameter, but it only works if what's going into bar is the same type as X.
That sounds a bit like gobbledegook but I can see now why this works:
Code: Select all
n.getList().forEach(String::toString);
Code: Select all
n.getList().forEach(Names::printNames);
Of course you could supply any one-arg static method that takes a String also.
-
- Posts: 66
- Joined: Mon Feb 20, 2017 12:31 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
I think in this last paragraph there is a little mistake:
"String becomes the required argument corresponding to apply(T t)."
Instead of apply (T t) should be accept (T t), because the interface to implement in forEach is Consumer.
"String becomes the required argument corresponding to apply(T t)."
Instead of apply (T t) should be accept (T t), because the interface to implement in forEach is Consumer.
-
- Site Admin
- Posts: 10065
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
Right.
If you like our products and services, please help us by posting your review here.
-
- Posts: 29
- Joined: Sun Feb 07, 2021 6:30 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
When I change
printName(), getList(), list all to static rather than instance,
I thought thatwould now work as it gets interpreted as
but it does not
is there an explanation for this? :/
printName(), getList(), list all to static rather than instance,
I thought that
Code: Select all
forEach(Names::printNames)
Code: Select all
forEach(string -> Names.printNames())
is there an explanation for this? :/
-
- Site Admin
- Posts: 10065
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
What error message do you get when you compile it?
If you like our products and services, please help us by posting your review here.
-
- Posts: 29
- Joined: Sun Feb 07, 2021 6:30 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
Code:
(using https://www.onlinegdb.com/online_java_compiler - so had to rename class for Names to Main)
Output:
Main.java:22: error: incompatible types: invalid method reference
n.getList().forEach(Main::printNames);
^
method printNames in class Main cannot be applied to given types
required: no arguments
found: String
reason: actual and formal argument lists differ in length
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
But if I replace:
with:
it works fine...
Aren't these the same thing?? :S
Any ideas?
(using https://www.onlinegdb.com/online_java_compiler - so had to rename class for Names to Main)
Code: Select all
import java.util.*;
import java.util.stream.*;
public class Main{
private static List<String> list;
public static List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public static void printNames(){
System.out.println(getList());
}
public static void main(String[] args) {
List<String> list = Arrays.asList(
"Bob Hope",
"Bob Dole",
"Bob Brown"
);
Main n = new Main();
n.setList(list.stream().collect(Collectors.toList()));
n.getList().forEach(Main::printNames);
}
}
Main.java:22: error: incompatible types: invalid method reference
n.getList().forEach(Main::printNames);
^
method printNames in class Main cannot be applied to given types
required: no arguments
found: String
reason: actual and formal argument lists differ in length
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
But if I replace:
Code: Select all
forEach(Names::printNames)
Code: Select all
forEach(string -> Names.printNames())
Aren't these the same thing?? :S
Any ideas?
-
- Site Admin
- Posts: 10065
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
No, they are not the same!
forEach(Names::printNames) implies this:
forEach( new Consumer(){
public void accept(String s){
Names.printNames(s); //this will not compile because there is no such method in Names
}
} );
forEach(string -> Names.printNames()) implies this:
forEach( new Consumer(){
public void accept(String string){
Names.printNames(); //this is ok. the string variable is ignored/not used
}
} );
You will need to go through some book or tutorial that explains how a method reference is used by the compiler to generate an implementation of the functional interface and how a lambda expression is used. Both are different.
forEach(Names::printNames) implies this:
forEach( new Consumer(){
public void accept(String s){
Names.printNames(s); //this will not compile because there is no such method in Names
}
} );
forEach(string -> Names.printNames()) implies this:
forEach( new Consumer(){
public void accept(String string){
Names.printNames(); //this is ok. the string variable is ignored/not used
}
} );
You will need to go through some book or tutorial that explains how a method reference is used by the compiler to generate an implementation of the functional interface and how a lambda expression is used. Both are different.
If you like our products and services, please help us by posting your review here.
-
- Posts: 29
- Joined: Sun Feb 07, 2021 6:30 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1789 :
I think I understand...
I played around with some code and it seems like:
When converting method reference to lambda,
All the parameters on the LHS of the lambda need to also be used in the RHS...
Is this correct?
I played around with some code and it seems like:
When converting method reference to lambda,
All the parameters on the LHS of the lambda need to also be used in the RHS...
Is this correct?
Who is online
Users browsing this forum: No registered users and 130 guests