• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

OCP Doubt: Ambiguous Lambda expression for Callable vs Supplier

 
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
Another doubt from OCP book (Page Number 343) regarding the below snippet:

Here under main method, 1st statement is compiled and 2nd/3rd can't be compiled. For 3rd statement reason is "The use() method is overloaded to take both Callable and Supplier parameters. The compiler does not take into account the fact that the body of the lambda expression happens to throw an exception; therefore, it does not know how to tell them apart." means compiler not able to understand that this lambda expression is throwing checked exception so it is not able to decide which method to be mapped. Now for 2nd statement the reason is "does not compile, as Supplier does not support checked exceptions.".

Isn't 2nd statement's justification contrary to the justification for line 3rd. 3rd statement is not able to compile because compiler is not able to understand that lambda expression is throwing exception but for 2nd statement, compiler is able to understand that lambda expression is throwing checked exception. how?





Thanks,
Vicky
 
Ranch Hand
Posts: 491
23
Eclipse IDE Firefox Browser Spring VI Editor AngularJS Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Vicky Roy wrote:Here under main method, 1st statement is compiled and 2nd/3rd can't be compiled. For 3rd statement reason is "The use() method is overloaded to take both Callable and Supplier parameters. The compiler does not take into account the fact that the body of the lambda expression happens to throw an exception; therefore, it does not know how to tell them apart." means compiler not able to understand that this lambda expression is throwing checked exception so it is not able to decide which method to be mapped. Now for 2nd statement the reason is "does not compile, as Supplier does not support checked exceptions.".  
Isn't 2nd statement's justification contrary to the justification for line 3rd. 3rd statement is not able to compile because compiler is not able to understand that lambda expression is throwing exception but for 2nd statement, compiler is able to understand that lambda expression is throwing checked exception. how?

the question,lambda expression(inside it's body) can throw checked exception or not,it solely depends on the implementation policy of lambda expression i.e.how really are you using or implementing lambda in code,in your case you have used the lambda expression as a method arguments,now see

here lambda is a Callable,this part will compile because call method of Callable is allowed to throw Exception,if needed,mentioned well in Callable API.

here the lambda is a Supplier,and it has "get" method where it is not allowed to throw any Exception,though you can handle them inside the lambda body by using try-catch block.mentioned well in Supplier API you can see inside API,in the signature of get method,it is not allowed to throw Exception.

lambda is undefined here so the compiler will get confused to opt b/w the overload method "use",as compiler will fail during parsing the target type of lambda expression(whether it is Callable or Supplier type) used as a method argument.

so finally compiler can understand well that lambda is throwing exception but deny for it if lambda tries to break the policy(for,it is used as).
Hope this will help!

Kind Regards,
Praveen.
 
Vicky Roy
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


here the lambda is a Supplier,and it has "get" method where it is not allowed to throw any Exception,though you can handle them inside the lambda body by using try-catch block.mentioned well in Supplier API you can see inside API,in the signature of get method,it is not allowed to throw Exception.

lambda is undefined here so the compiler will get confused to opt b/w the overload method "use",as compiler will fail during parsing the target type of lambda expression(whether it is Callable or Supplier type) used as a method argument.

so finally compiler can understand well that lambda is throwing exception but deny for it if lambda tries to break the policy(for,it is used as).
Hope this will help!

Kind Regards,
Praveen.



Here how you can say that lambda is Supplier in case of use() method? It can be Callable or Supplier as defined for 1st and 2nd statement. And it should be mapped with Callable statement once compiler sees that it is throwing exception!!! That's what my understanding is
 
praveen kumaar
Ranch Hand
Posts: 491
23
Eclipse IDE Firefox Browser Spring VI Editor AngularJS Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
vicky,please read the explanation accordingly with the code.i had written a code line first and then explained it,so please read it with this order.
the line lambda is a supplier is for 2nd code snippet i.e., useSupplier() method.

Kind Regards,
Praveen.
 
Vicky Roy
Ranch Hand
Posts: 66
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

praveen kumaar wrote:vicky,please read the explanation accordingly with the code.i had written a code line first and then explained it,so please read it with this order.
the line lambda is a supplier is for 2nd code snippet i.e., useSupplier() method.

Kind Regards,
Praveen.




Sorry for misunderstanding. Here my question is rephrased. Why lambda is undefined here? Earlier compiler was easily to map it with Supplier/Callable but why not now?

use(()->throw new IOException;)

lambda is undefined here so the compiler will get confused to opt b/w the overload method "use",as compiler will fail during parsing the target type of lambda expression(whether it is Callable or Supplier type) used as a method argument.

 
Rancher
Posts: 4801
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The compiler uses the signature of the methods to decide on the method.

After it has found the method in question, it will then check the code is valid.

The use() lambda fails because it cannot determine which method you mean...the one in Callable or the one in Supplier, so it doesn't even get to checking the code.
 
praveen kumaar
Ranch Hand
Posts: 491
23
Eclipse IDE Firefox Browser Spring VI Editor AngularJS Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Vicky Roy wrote:Sorry for misunderstanding. Here my question is rephrased. Why lambda is undefined here? Earlier compiler was easily to map it with Supplier/Callable but why not now?

Because the previous two methods are not overloaded and compiler will easily finds what is the type of lambda from the method signature where you declared them.
But in the last case the method "use" is overloaded with 2 types of argument(Callable,Supplier) and both of them returns a void.lambda cannot express its type on its own,compiler interprets its type from the term "target typing",and compiler deduct it from the context in which it is used.please read the item target-typing here in this Target Typing in lambda From Oracle..

Vicky Roy wrote:Sorry for misunderstanding.

No worries,it's ok.

hope this will help!

kind regards
 
Vicky Roy
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Still I would argue. In case of Use() when compiler checks that it is showing exception, then it should map this call with the method expecting Callable since it only supports checked exceptions!!! That's what happened in case of 1st statement.

 
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Vicky Roy wrote:Still I would argue. In case of Use() when compiler checks that it is showing exception, then it should map this call with the method expecting Callable since it only supports checked exceptions!!! That's what happened in case of 1st statement.



The compiler doesn't check for exceptions as part of the signature. And you can't really argue with the compiler -- it will fail to compile every time...

As for the case of the first statement, there was only one option. The compiler did not have to disambiguate the method call.

Henry
 
Vicky Roy
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Henry Wong wrote:

Vicky Roy wrote:Still I would argue. In case of Use() when compiler checks that it is showing exception, then it should map this call with the method expecting Callable since it only supports checked exceptions!!! That's what happened in case of 1st statement.



The compiler doesn't check for exceptions as part of the signature. And you can't really argue with the compiler -- it will fail to compile every time...

As for the case of the first statement, there was only one option. The compiler did not have to disambiguate the method call.

Henry



Fine. Then lets say I agree what you are saying that compiler doesn't understand the exception and it can't decide appropriate method. But then why useSupplier() is not compiling? Since compiler can't understand the exception, it should easily map and error may come at runtime!!!
 
Henry Wong
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Vicky Roy wrote:
Fine. Then lets say I agree what you are saying that compiler doesn't understand the exception and it can't decide appropriate method. But then why useSupplier() is not compiling? Since compiler can't understand the exception, it should easily map and error may come at runtime!!!



The compiler does not use the checked exception to resolve overloaded methods. However, once a method is resolved, then it makes sure that checked exceptions are either caught or declared as throws.

Henry
 
Vicky Roy
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Henry Wong wrote:

Vicky Roy wrote:
Fine. Then lets say I agree what you are saying that compiler doesn't understand the exception and it can't decide appropriate method. But then why useSupplier() is not compiling? Since compiler can't understand the exception, it should easily map and error may come at runtime!!!



The compiler does not use the checked exception to resolve overloaded methods. However, once a method is resolved, then it makes sure that checked exceptions are either caught or declared as throws.

Henry



ok Thanks. Now I think I can co-relate this statement with the output.
 
Saloon Keeper
Posts: 15727
368
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The method signature determines what the return type of the lambda expression should be, and not the other way around. With useSupplier(), the compiler knows that the lambda expression should return a Supplier<Integer>. After it's done that, it checks that the lambda expression indeed returns such a type. It does not, because Supplier<Integer> is not allowed to throw an exception.

The compiler can only use the left hand side of the lambda expression (the parameter list) to determine which overloaded version of the method to call, but it can only do that if you explicitly state the type of the parameters:
 
Talk sense to a fool and he calls you foolish. -Euripides A foolish tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic