About Question enthuware.ocpjp.v8.2.1857 :

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

Moderator: admin

Post Reply
rois_r
Posts: 2
Joined: Wed Apr 24, 2019 12:52 am
Contact:

About Question enthuware.ocpjp.v8.2.1857 :

Post by rois_r »

Code: Select all

class MyProcessor {
	Integer value;

	public MyProcessor(Integer value) {
		this.value = value;
	}

	public void process() {
		System.out.println(value + " ");
	}
}

public class TestClass {
	public static void main(String[] args) {         
		List<Integer> ls = Arrays.asList(1, 2, 3);                  
		//INSERT CODE HERE     
		}
	}
}
Solution: ls.stream().map(MyProcessor::new).forEach(MyProcessor::process);

Why this works if forEach needs a Consumer and process method does not take any argument?

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

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

Post by admin »

The argument is not passed to the process method. First, the map method converts each element of List<Integer> to List<MyProcessor> because of map(MyProcessor::new). Next, a Consumer object is created using the method reference MyProcessor::process, something like this:

Code: Select all

new Consumer(){
   void accept(MyProcessor mp){
     mp.process(); <---- No argument required here
   }
}
This consumer object is passed to forEach.
If you like our products and services, please help us by posting your review here.

rois_r
Posts: 2
Joined: Wed Apr 24, 2019 12:52 am
Contact:

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

Post by rois_r »

Thanks for the explanation!

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

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

Post by Javier »

Hi Paul!
Why the last two options are syntactically illegal?
What I see is that in both cases the method references doesn´t work on the body of the lambda expression.

Code: Select all

ls.stream().forEach((x)->process( MyProcessor::new ));//not compile

Code: Select all

ls.stream().forEach(x->{new MyProcessor(x).process();}); //compile

Code: Select all

ls.stream().forEach(x->MyProcessor::new);//not compile

Code: Select all

ls.stream().forEach(MyProcessor::new);//compile
Both options work when we don´t use method references.
I wrote this code in Eclipse and I don´t understand why the errors.

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

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

Post by admin »

Check out how lambda expressions are converted by the compiler into a class. How do you think they will be converted to a class with a method by the compiler?
If you like our products and services, please help us by posting your review here.

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

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

Post by Javier »

Hi Paul,
I don´t get it, I am not able to find the correct answer, but I saw one possible answer here:
https://stackoverflow.com/questions/168 ... e-compiled
"Java compiler will generate synthetic methods"
"Instead of creating a new object that will wrap the Lambda function, it uses the new INVOKEDYNAMIC instruction to dynamically link this call site to the actual Lambda function which is converted to private static synthetic lambda$0(Ljava/lang/String;)V which will accept string as a parameter."
I am very lost here, I don´t get it. :(

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

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

Post by admin »

What I meant was that lambda expressions are just syntactic sugar. The JVM doesn't understand lambda expressions. Conceptually, the compiler simply converts the given lambda expression into some class, instantiates it, and passes that object to the method. While doing so, it follows certain process and rules. It puts the part after -> as the method body.

Let's see this now:
1. ls.stream().forEach((x)->process( MyProcessor::new ));

forEach expects an object of a class that implements Consumer. So, the compiler uses the code given in the lambda expression and creates this class and an object of that class. For example, in this case, it will do:

Code: Select all

class SomeMadeUpClassName implements Consumer{
   public void accept(Integer x){
        process(new MyProcessor()); //this is illegal because you cannot invoke MyProcessor's process method like this.

   }
}
What you really want in the body of the above accept method is this line of code: new MyProcessor(x).process();

Please note that this is a long topic to discuss in a post but I have tried to explain it in brief. You need go through a good book to understand how lambdas and method references work.
If you like our products and services, please help us by posting your review here.

likejudo
Posts: 14
Joined: Sun Feb 18, 2024 7:21 pm
Contact:

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

Post by likejudo »

I liked the explanation in the solution. The explanation of method references. It was better than the textbook!

Post Reply

Who is online

Users browsing this forum: No registered users and 38 guests