About Question enthuware.ocpjp.v8.2.1789 :

Help and support on OCA OCP Java Programmer Certification Questions
1Z0-808, 1Z0-809, 1Z0-815, 1Z0-816, 1Z0-817

Moderator: admin

Post Reply
lucastomasini
Posts: 3
Joined: Tue Jun 20, 2017 3:10 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by lucastomasini »

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.

admin
Site Admin
Posts: 10065
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by admin »

Yes, that could also be a valid reason.
If you like our products and services, please help us by posting your review here.

__JJ__
Posts: 125
Joined: Thu Jul 05, 2018 6:44 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by __JJ__ »

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:

Code: Select all

       n.getList().forEach(String::toString);
but this doesn't

Code: Select all

      n.getList().forEach(Names::printNames);
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.

Javier
Posts: 66
Joined: Mon Feb 20, 2017 12:31 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by Javier »

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.

admin
Site Admin
Posts: 10065
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by admin »

Right.
If you like our products and services, please help us by posting your review here.

jme_chg
Posts: 29
Joined: Sun Feb 07, 2021 6:30 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by jme_chg »

When I change
printName(), getList(), list all to static rather than instance,

I thought that

Code: Select all

forEach(Names::printNames)
would now work as it gets interpreted as

Code: Select all

forEach(string -> Names.printNames())
but it does not
is there an explanation for this? :/

admin
Site Admin
Posts: 10065
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by admin »

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.

jme_chg
Posts: 29
Joined: Sun Feb 07, 2021 6:30 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by jme_chg »

Code:

(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);    
    }      
}  
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:

Code: Select all

forEach(Names::printNames)
with:

Code: Select all

forEach(string -> Names.printNames())
it works fine...
Aren't these the same thing?? :S
Any ideas?

admin
Site Admin
Posts: 10065
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by admin »

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.
If you like our products and services, please help us by posting your review here.

jme_chg
Posts: 29
Joined: Sun Feb 07, 2021 6:30 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1789 :

Post by jme_chg »

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?

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 87 guests