[ 
https://issues.apache.org/jira/browse/GROOVY-10099?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Eric Milles updated GROOVY-10099:
---------------------------------
    Labels: varargs  (was: )

> A single null argument to a varargs parameter is received as null
> -----------------------------------------------------------------
>
>                 Key: GROOVY-10099
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10099
>             Project: Groovy
>          Issue Type: Bug
>         Environment: Observed on Groovy 3.0.8 on macOS Big Sur (Intel), but I 
> don't think that's relevant; it'll be everywhere.
>            Reporter: Rachel Greenham
>            Priority: Major
>              Labels: varargs
>             Fix For: 4.x
>
>         Attachments: VarArgsTest.groovy, VarArgsTest.jsh
>
>          Time Spent: 3h 20m
>  Remaining Estimate: 0h
>
> (NB: I would set the priority to P2 default to be triaged, but I seem not to 
> have that option, so I left it at the default I was presented with.)
> When calling a method with a varargs parameter with a single value, that 
> value is wrapped into an array of length 1. This is the behaviour in Java, 
> and is the expected behaviour, and _most_ of the time is the behaviour in 
> Groovy too.
> But when that single value is null, Groovy will instead just pass the null 
> into the method. Java will not do this: You'll get an array with a single 
> null in it. Because Groovy's behaviour is unexpected, especially when 
> interfacing with Java code, NullPointerExceptions can often ensue.
> Adding to the inconsistencies, if the Groovy code calling the method is in a 
> {{@CompileStatic}} context, it behaves just like Java, and the method 
> (whether or not _it_ is statically compiled or a dynamic Groovy method) 
> receives an array with a null in it.
> So the behaviour in Groovy is inconsistent, both with itself in a 
> {{@CompileStatic}} situation, and with Java, and is requiring workarounds in 
> Java code to handle this normally-impossible eventuality. (Even if no varargs 
> parameter is given you get an empty array, as in fact you do in Groovy too.)
> This may be an "early instalment weirdness": There's an ancient ticket, from 
> not long after varargs were introduced into Java, which appears to have 
> argued - successfully at the time - that the normal behaviour is a bug: 
> https://issues.apache.org/jira/browse/GROOVY-1026 
> Further adding to the confusion may be that Groovy usually elides the 
> difference between an {{Object[]}} parameter and an {{Object...}} parameter: 
> They both behave the same.
> The offending code appears to be in 
> org.codehaus.groovy.reflection.ParameterTypes.java in method fitToVars, lines 
> 200-215 in master at the time of writing, which even includes a comment that 
> "if the last argument is null, then we don't have to do anything", with which 
> I respectfully disagree. :) That behaviour should be to return an array with 
> a single null in it (Handily, MetaClassHelper.ARRAY_WITH_NULL saves having to 
> make a new one.)
> In principle it's an easy fix (although I've left tagging to others as this 
> is my first issue here), but there'd be an obvious nervousness about changing 
> behaviour like this when there might be a lot of old code out there depending 
> on it behaving the way it does now. OTOH the way it behaves now is breaking 
> the expectations of those of us coming to Groovy from a lifetime of Java...
> Attachments:
> VarArgsTest.groovy - a script saved from, and runnable in, groovyConsole, 
> demonstrating the behaviour. The behaviour is the same regardless of whether 
> the console is launched with the -indy option. (The issue was initially 
> observed in indy.) The dynamic portion of the test, when run, ends in a 
> NullPointerException as Arrays.asList is not expecting a null varargs 
> parameter. Output seen (-indy or  not):
>  
> {code:java}
> name: the static name 1
> params is null? false
> params length is 1
> [blah]
> name: the static name 2
> params is null? false
> params length is 2
> [blah, blue]
> name: the static name 3 with blah=null
> params is null? false
> params length is 1
> [null]
> Arrays.asList(blah)? [null]
> name: the dynamic name 1
> params is null? false
> params length is 1
> [blah]
> name: the dynamic name 2
> params is null? false
> params length is 2
> [blah, blue]
> name: the dynamic name 3 with blah=null
> params is null? true
> Exception thrown
> java.lang.NullPointerException
> ...{code}
> (etc. stack trace not shown for formatting reasons.)
> VarArgsTest.jsh - a jshell script demonstrating Java's behaviour, very 
> similar to the groovy test, but omitting the dynamic portion of the test for 
> obvious reasons. (The statements in the Groovy script ending in semicolons 
> are left that way precisely to mark that they're identical to the Java test.) 
> Runnable with
>  
> {code:java}
> jshell PRINTING VarArgsTest.jsh
> {code}
> Output seen:
> {code:java}
> name: the static name 1
> params is null? false
> params length is 1
> [blah]
> name: the static name 2
> params is null? false
> params length is 2
> [blah, blue]
> name: the static name 3 with blah=null
> params is null? false
> params length is 1
> [null]
> Arrays.asList(blah)? [null]
> {code}



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to