Page 1 of 1
About Question enthuware.ocpjp.v8.2.1889 :
Posted: Sat Feb 03, 2018 10:12 am
by javasaur
Hi there,
as I skimmed the question I marked this line as a potential compile-error and marked option E,
Code: Select all
ToDoubleFunction<Item> priceF = Item::getPrice; //1
since I assumed that the default class construction implies non-static getters and setters and no static method is provided to the interface. But the question seems to have an assumed part like this:
Code: Select all
public static double getPrice(Item i) {
return i.getPrice();
}
public double getPrice() {
return price;
}
Did I get it right? If yes, is it something I should expect on the exam or did you assume it by yourself?
Thanks
Re: About Question enthuware.ocpjp.v8.2.1889 :
Posted: Sat Feb 03, 2018 12:03 pm
by admin
It code does assume the existing of accessor methods i.e. getXXX and setXXX for each of the three properties of Item class. It contains this line in the code: //accessors not shown
This implies that the accessor methods are there but are not shown here in the code listing.
But the static getter that you've mentioned is not a valid getter method for the price field and is not required to answer the question either.
HTH,
Paul.
Re: About Question enthuware.ocpjp.v8.2.1889 :
Posted: Sat Feb 03, 2018 1:09 pm
by javasaur
I copied the code, added the getters and the code compiled.
I've built the function with full syntax and tried to reduce part by part
Code: Select all
ToDoubleFunction<Item> priceF = (Item i) -> {return i.getPrice();};
became
Code: Select all
ToDoubleFunction<Item> priceF = Item -> Item.getPrice();
which eventually became
Code: Select all
ToDoubleFunction<Item> priceF = Item::getPrice;
All options compile and result in the same output, but I am still confused. How Java does allow to invoke an instance method on
Item? It's a class name. I thought it would check for a static method getPrice() and result in compiler error since it's not found.
Could you clarify this aspect?
Re: About Question enthuware.ocpjp.v8.2.1889 :
Posted: Sun Feb 04, 2018 3:41 am
by admin
Your understanding about Item::getPrice; is incorrect. Item::getPrice is not an actual call to any method. It is just a reference to the getPrice method of Item class. That this method is static or not has nothing to do with what Item::getPrice means. That is why no instance is required to refer to the getPrice method. Again, you are not calling the getPrice method at this point. You are merely saying that you are going to use the getPrice method of Item class later.
Now, when you say, ToDoubleFunction<Item> priceF = Item::getPrice; you are saying that you will use Item class's getPrice method to implement the ToDoubleFunction<Item> interface. Again, you are not calling the getPrice method yet. Only declaring that the applyAsDouble function (which is what ToDoubleFunction requires you to implement) will use Item class's getPrice method in its body.
Finally, the place when the method is actually invoked is when collect(Collectors.averagingDouble(priceF)). Here, you actually need an object of class Item on which getPrice method can be invoked. This Item object is supplied by the stream which you are iterating over in that call. So when the compiler generates the byte code for this collect call, it knows how to implement the ToDoubleFunction's applyAsDouble method. At this time, it will make use of the fact that getPrice method of Item class is an instance method and it will check whether there is an Item instance available in the context at that time. Indeed, while looping through a collection of Items, every iteration does have a reference to an Item object. Thus, the compiler will generate the body of this function with code that invokes the getPrice method on the reference to the Item object that the loop is currently iterating over.
HTH,
Paul.
Re: About Question enthuware.ocpjp.v8.2.1889 :
Posted: Sun Feb 04, 2018 4:27 am
by javasaur
Thanks, Paul.
You made it clear.
Re: About Question enthuware.ocpjp.v8.2.1889 :
Posted: Thu Mar 29, 2018 2:09 pm
by yassine
From the java doc I read that forEach takes a
Consumer not a
BiConsumer:
Code: Select all
forEach([b]Consumer[/b]<? super T> action)
Performs an action for each element of this stream.
so how is that :
.forEach((a, b)->{
double av = b.stream().collect(Collectors.averagingDouble(priceF)); //3
System.out.println(a+" : "+av);
});
Re: About Question enthuware.ocpjp.v8.2.1889 :
Posted: Thu Mar 29, 2018 11:01 pm
by admin
Actually, collect(Collectors.groupingBy(Item::getCategory)) returns a Map and Map's forEach takes a BiConsumer.