[
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)