[ https://issues.apache.org/jira/browse/GROOVY-10099?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17583728#comment-17583728 ]
ASF GitHub Bot commented on GROOVY-10099: ----------------------------------------- eric-milles commented on PR #1601: URL: https://github.com/apache/groovy/pull/1601#issuecomment-1224298737 -1 for me I will look over your tests and see about adding them to the build at least to demonstrate GROOVY-10099. `InvocationWriter#loadArguments` already has significant checking/handling for variadic situations. And `null` is supposed to represent the array, not an array with one `null` element. I think the safe advice is to use `@CompileStatic` if you have a scenario that passes a single nullable argument for the array parameter and you don't want to wrap in your code. > 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.10#820010)