[ 
https://issues.apache.org/jira/browse/GROOVY-7933?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15494474#comment-15494474
 ] 

Jochen Theodorou commented on GROOVY-7933:
------------------------------------------

Actually I think I made a mistake once more in misunderstanding some of the 
comments here, plus mixing up plans and what is done.. the code part I was 
thinking of does actually not activate for overloaded methods at all.. I am 
sorry for causing confusion here.

Ok, let us first assess again what we have:
{code:Java}
def types = [
  ["int" , "Integer", "1"], ["byte", "Byte", "1"],
  ["boolean", "Boolean", "true"],  ["short","Short", "1"],
  ["long", "Long", "1"], ["char", "Character", "'c'"],
  ["double", "Double", "1"], ["float", "Float", "1"]
]

types.each {
  def code = """
     public int a(${it[0]} a) { 0 }
     public int a(${it[1]} a) { 1 }
     ${it[0]} val = ${it[2]}
     assert a(val) == 1
  """
  println code
  Eval.me code
}
{code}
this will test all primitives (unless I forgot one) against an overloaded a 
method with on version taking the primitive and the other the wrapper. In all 
cases the wrapper version will chosen. This is regardless of if the call is 
done from the same class or not. That this codes must behave like this, is 
because of the arguments being wrapped at one point before doing the method 
selection. And while consistent, it is not what Java would do. @CompileStatic 
orientates itself more on Java here, since it does not support multi methods of 
any kind and differs from normal Groovy.

Now, the more interesting part is that of primitive vs. Object. Now in the 
method selection algorithm we calculate the distance between argument and 
parameter type. Let us say going one level in inheritance is a distance of 2, 
then going from the wrapper to the primitive or from the primitive to the 
wrapper only 1.  So a call a(1), will be done using an Integer, but the 
distance to Object is 2, while the distance to int is only 1, resulting in 
a(int) to be chosen over a(Object).

And yes, boolean and char behave different, and yes, I consider that wrong. I 
assume we overlooked them because the code responsible for the half steps is 
actually only considering widening related types and char and boolean are not 
taking part in widening. So [~jwagenleitner] was absolutely right with 
{{Integer > int > long > Long > BigInteger > float > Float > double > Double > 
BigDecimal > Number > Object}} though for a call with int, what is supposed to 
be used is actually {{int > Integer > long > Long > BigInteger > float > Float 
> double > Double > BigDecimal > Number > Object}} and the first chain only 
applies because of boxing. Since there are no calls with int, but only with 
Integer, this case actually never happens.

So, yes, boolean and char behaviour should be fixed


> Incorrect boxing of boolean primitive types
> -------------------------------------------
>
>                 Key: GROOVY-7933
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7933
>             Project: Groovy
>          Issue Type: Bug
>          Components: groovy-runtime
>    Affects Versions: 2.4.7
>            Reporter: Henri Tremblay
>
> A boolean primitive type seems to be boxed for no apparent reason. See the 
> example below. The problem disappear when using @CompileStatic or if 
> explicitly casting to (boolean).
> {code:java}
> public class Demo {
>    public void a(boolean a){
>        System.out.println("boolean was called");
>    }
>    public void a(Object a){
>        System.out.println("Object was called");
>    }
> }
> class Groovy {
>    static void main(String[] args) {
>        def demo = new Demo()
>        demo.a(true)
>    }
> }
> {code}
> *Output:*
> Object was called



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to