About Question enthuware.ocpjp.v8.2.1871 :
Moderator: admin
-
- Posts: 197
- Joined: Mon Jun 20, 2016 5:06 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
Got it
process(fnames, t::eat); -> process( fnames, a -> t.eat(a));
process(fnames, t::calories); -> process( fnames, a -> t.calories(a));
process(fnames, TestClass::size); -> process( fnames, a -> TestClass.size(a));
Q1) So how to differentiate between var::instanceMethod or class:instanceMethod?
Q2) Lambda expression for var::instanceMethod and class:StaticMethod has the same syntax?
process(fnames, t::eat); -> process( fnames, a -> t.eat(a));
process(fnames, t::calories); -> process( fnames, a -> t.calories(a));
process(fnames, TestClass::size); -> process( fnames, a -> TestClass.size(a));
Q1) So how to differentiate between var::instanceMethod or class:instanceMethod?
Q2) Lambda expression for var::instanceMethod and class:StaticMethod has the same syntax?
-
- Site Admin
- Posts: 10043
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
Not sure what you mean by differentiation. var::instanceMethod uses the variable name, while class:instanceMethod uses the class name.johnlong wrote: Q1) So how to differentiate between var::instanceMethod or class:instanceMethod?
Q2) Lambda expression for var::instanceMethod and class:StaticMethod has the same syntax?
It is explained here is more detail: https://docs.oracle.com/javase/tutorial ... ences.html
If you like our products and services, please help us by posting your review here.
-
- Posts: 197
- Joined: Mon Jun 20, 2016 5:06 pm
- Contact:
-
- Posts: 124
- Joined: Wed Feb 12, 2014 2:44 am
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
Hello ,
I have the same above question as I still have problems understanding method and constructor reference
Could you please advise how can I substitute those method references with the lambda expressions?
process(fnames, t::eat);
process(fnames, t::calories);
process(fnames, TestClass::size);
I have the same above question as I still have problems understanding method and constructor reference
Could you please advise how can I substitute those method references with the lambda expressions?
process(fnames, t::eat);
process(fnames, t::calories);
process(fnames, TestClass::size);
-
- Site Admin
- Posts: 10043
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
Check out this article: http://enthuware.com/index.php/home/115
Now, look at the method eat, for example, and turn it into a lambda expression as described in above article.
Now, look at the method eat, for example, and turn it into a lambda expression as described in above article.
If you like our products and services, please help us by posting your review here.
-
- Posts: 56
- Joined: Tue Feb 21, 2017 4:24 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
I'm having trouble understanding the explanation for why last option (Tiger::eat) is wrong. I understand the situation with the static reference. However, the part
Thank you.
How DOES the context supply the instance of Tiger class in this situation? It's clear when the method reference is called on an instance variable (such as t::eat). But in case of Tiger::eat - how would the instance of Tiger class be supplied by the context. Could you, please, show an example?"Which meaning is implied depends on the context in which it is used. Here, the context does not supply any instance of Tiger class.
Thank you.
-
- Site Admin
- Posts: 10043
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
The object is supplied by the context if it is available in the context. For example,
(Ref: https://docs.oracle.com/javase/tutorial ... ences.html )
The compareToIgnoreCase method has to operate on the stringArray. So the context does have String objects in that array. Therefore, it can supply two strings from the array to call that method. There is no need for a separate String object for the method to be invoked.
In the last option of this question, process(fnames, Tiger::eat);, there is no Tiger object in the context.
HTH,
Paul.
Code: Select all
String[] stringArray = { "Barbara", "James", "Mary", "John",
"Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
The compareToIgnoreCase method has to operate on the stringArray. So the context does have String objects in that array. Therefore, it can supply two strings from the array to call that method. There is no need for a separate String object for the method to be invoked.
In the last option of this question, process(fnames, Tiger::eat);, there is no Tiger object in the context.
HTH,
Paul.
If you like our products and services, please help us by posting your review here.
-
- Posts: 3
- Joined: Wed Nov 12, 2014 3:03 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
Hi, I'm pretty sorry but I couldn't understand the answer at all.
How this line :
can call this method :
Since the method's waiting for 2 args : List<String> names and Carnivore c.
In fact I couldn't understand how we can pass t::calories to Carnivore c, since t:calories return a int.
Sorry about the question.
How this line :
Code: Select all
process(fnames, t::calories);
Code: Select all
public static void process(List<String> names, Carnivore c) {
c.eat(names);
}
In fact I couldn't understand how we can pass t::calories to Carnivore c, since t:calories return a int.
Sorry about the question.
-
- Site Admin
- Posts: 10043
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
Carnivore has only one abstract method "int eat(List<String> foods)".
To implement this interface using a lambda expression, you require a reference to a method with the same parameter and return types. t::calories refers to Carnivore's default method "int calories(List<String> food)", which satisfies this requirement. So there is no issue.
To implement this interface using a lambda expression, you require a reference to a method with the same parameter and return types. t::calories refers to Carnivore's default method "int calories(List<String> food)", which satisfies this requirement. So there is no issue.
If you like our products and services, please help us by posting your review here.
-
- Posts: 5
- Joined: Fri Jun 02, 2017 4:57 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
How would look like context where I could call Tiger::eat?Tiger::eat is a valid method reference that can mean to refer either to a static method eat of Tiger class or to an instance method of any arbitrary instance of Tiger class. Which meaning is implied depends on the context in which it is used. Here, the context does not supply any instance of Tiger class.
-
- Site Admin
- Posts: 10043
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
Let's say you have this interface:
You can then do the following in the main of TestClass:
Code: Select all
interface SomeI{
void m(Tiger t, List<String> list);
}
Code: Select all
class TestClass{
public static void main(String[] args) {
SomeI s = Tiger::eat;
}
}
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.1871 :
Have to say, this is very clever. I have been looking at it and having a play and it's quite something how it manages to work.Martyjee wrote: ↑Thu Oct 15, 2015 3:51 amHi Paul,
No, that is not true, you are implying that you want to use the code that is defined in the eat method of the type Tiger! The Oracle docs define 4 flavours of method references, and this flavour (the most confusing one) is what they call "Reference to an Instance Method of an Arbitrary Object of a Particular Type". Remember that we are dealing with lambda expressions and method references here, not actual method calls!As per the code that is given, if you use Tiger::eat, you are implying that you want to call eat method on Tiger class (as opposed to Tiger instance)
You don't need a Tiger instance, and the eat method does not have to be static to reference it as Tiger::eat.There is no context here that provides you a Tiger instance.
I will give a code example that I came up with (assume appropriate import statements):Could you please show with code what you mean?
As you can see at line //2 there is no instance needed to reference Knife::sliceCode: Select all
public class Example { public static void main(String[] args) { Mother mother = new Mother(); Child child = new Child(); mother.giveOrder(child::eat); //1 Reference to an instance method of a particular object mother.giveOrder(Knife::slice); //2 Reference to an instance method of an arbitrary object of a particular type mother.giveOrder(Knife::stab); //3 Reference to a static method } } [SNIP] } }
It compiles fine! The context is created at line //4 where the actual Knife object is first needed!
It looks like the "slice" method does not have the required parameters to be treated as an Eater, but actually it does, because the compiler inserts some arbitrary object reference to the parameter list as its first parameter! The program will even cause a compilation error at //2 if we rename the method "stab" to "slice", because their parameter lists are effectively the same when used as a lambda expression!!
HTH,
Martijn
I think it could be one of those things that once you used it a number of times you'd just see it as normal, but when you first come across it, it's a bit of a head scratcher. But thank you for putting together this example. I suggest people have a play with it themselves and reduce it down to just the interesting stuff ie the stuff pertinent to
Code: Select all
mother.giveOrder(Knife::slice);
-
- Posts: 125
- Joined: Thu Jul 05, 2018 6:44 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
After playing around with Martijn's code, I was able to hack the code in the question to get it to work with the Tiger::eat method reference; not to prove the question/answer wrong (it's not, as far as I can see) but just to try to get a handle on how Martijn's example works.
So FWIW here it is
The key thing it seems is that the interface method has to have as an (its first?) argument the class type of the instance that will be supplied at runtime. That type must have a method that takes the rest of the arguments defined in the interface's abstract method (here, just one extra argument). Then at runtime the invocation of the functional interface method will supply an instance
and that instance is what the instance method is invoked on.
It really is very clever.
Sorry if any of this is wrong; I'm just trying to understand it myself and thought it might help somebody.
So FWIW here it is
Code: Select all
import java.util.function.*;
import java.util.*;
interface Carnivore{
default int calories(List<String> food){
return food.size()*100;
}
int eat(Tiger t, List<String> foods);
}
class Tiger {
public int eat(List<String> foods){
System.out.println("Eating "+foods);
return foods.size()*200;
}
}
public class TestClass4 {
public static int size(List<String> names){
return names.size()*2;
}
public static void process(List<String> names, Carnivore c){
c.eat(new Tiger(), names);
}
public static void main(String[] args) {
List<String> fnames = Arrays.asList("a", "b", "c");
process(fnames, Tiger::eat);
}
}
Code: Select all
c.eat(new Tiger(), names);
It really is very clever.
Sorry if any of this is wrong; I'm just trying to understand it myself and thought it might help somebody.
-
- Posts: 6
- Joined: Sun Sep 01, 2019 9:33 am
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
Thank you for the example.
To make it even more understandable, in your example process(fnames, Tiger::eat) can be replaced with:
1) This equivalent lambda:
process(fnames, (a,b)->a.eat(b));
2) Or this equivalent anonymous class:
process(fnames, new Carnivore(){
@Override
public int eat(Tiger t, List<String> foods) {
return t.eat(foods);
}
});
It clearly works but I can't find any rule that explains why it works like this and how it works exactly. If anyone can figure out what the rule is about how exactly Java finds "context", would be helpful.
Admin said "The object is supplied by the context if it is available in the context." Sadly I don't quite understand this because the word context is too abstract for me... can anyone define "context" or is there a better way to describe this behavior please?
-
- Site Admin
- Posts: 10043
- Joined: Fri Sep 10, 2010 9:26 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
Exact and complete rules are given in Section 15.13 of JLS 11.
If you like our products and services, please help us by posting your review here.
-
- Posts: 5
- Joined: Fri Dec 15, 2023 4:00 pm
- Contact:
Re: About Question enthuware.ocpjp.v8.2.1871 :
I understood why the third option works - process(fnames, TestClass::size);
Due to the example below:
class Main {
public static void main(String[] args) {
I i1 = A::m;
}
@FunctionalInterface
interface I{
void method();
}
class A {
public static void m() {}
}
}
Due to the example below:
class Main {
public static void main(String[] args) {
I i1 = A::m;
}
@FunctionalInterface
interface I{
void method();
}
class A {
public static void m() {}
}
}
Who is online
Users browsing this forum: No registered users and 33 guests