Understanding unexpected behaviors of varargs in Java
I was reading this answer, where it says
Note also that calling a generic vararg method with an explicit array parameter may silently produce different behaviour than expected:
public <T> void foo(T... params) ...
int arr = 1, 2, 3;
foo(arr); // passes an int array containing a single int element
Similar behavior is exaplained in this answer gotcha 3:
int myNumbers = 1, 2, 3 ;
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs only works with reference types. Autoboxing does not apply to array of primitives. The following works:
Integer myNumbers = 1, 2, 3 ;
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"
I tried simpler examples:
private static <T> void tVarargs(T ... s)
System.out.println("nntVarargs ==========");
System.out.println(s.getClass().getName());
System.out.println(s.length);
for(T i : s)
System.out.print(s + ",");
private static void objVarargs(Object ... a)
System.out.println("nnobjVarargs =========== ");
System.out.println(a.getClass().getName());
System.out.println(a.length);
for(Object i : a)
System.out.print(i + ",");
int intarr = 1,2,3;
Integer Intarr = 1,2,3;
objVarargs(intarr);
objVarargs(Intarr);
tVarargs(intarr);
tVarargs(Intarr);
This prints
objVarargs ===========
[Ljava.lang.Object;
1
[I@7852e922,
objVarargs ===========
[Ljava.lang.Integer;
3
1,2,3,
tVarargs ==========
[[I
1
[[I@4e25154f,
tVarargs ==========
[Ljava.lang.Integer;
3
[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,
- Notice passing
intarr
totVarargs
results in creation of single 2 dimensional array[[I
wit single element. However, what is the types of this array? - Also, passing
intarr
toobjVarargs()
results in creation of 1-D array[Ljava.lang.Object
containing single array element. - For rest, it creates 1-D array with as many elements as passed - the desired behavior.
Can someone shed more light on first two behaviors? Are these two different behaviors or same behaviors, I mean having different or same reason behind them. What are those reasons, in depth? Is there any other cases resulting in different unexpected behavior?
java
add a comment |
I was reading this answer, where it says
Note also that calling a generic vararg method with an explicit array parameter may silently produce different behaviour than expected:
public <T> void foo(T... params) ...
int arr = 1, 2, 3;
foo(arr); // passes an int array containing a single int element
Similar behavior is exaplained in this answer gotcha 3:
int myNumbers = 1, 2, 3 ;
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs only works with reference types. Autoboxing does not apply to array of primitives. The following works:
Integer myNumbers = 1, 2, 3 ;
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"
I tried simpler examples:
private static <T> void tVarargs(T ... s)
System.out.println("nntVarargs ==========");
System.out.println(s.getClass().getName());
System.out.println(s.length);
for(T i : s)
System.out.print(s + ",");
private static void objVarargs(Object ... a)
System.out.println("nnobjVarargs =========== ");
System.out.println(a.getClass().getName());
System.out.println(a.length);
for(Object i : a)
System.out.print(i + ",");
int intarr = 1,2,3;
Integer Intarr = 1,2,3;
objVarargs(intarr);
objVarargs(Intarr);
tVarargs(intarr);
tVarargs(Intarr);
This prints
objVarargs ===========
[Ljava.lang.Object;
1
[I@7852e922,
objVarargs ===========
[Ljava.lang.Integer;
3
1,2,3,
tVarargs ==========
[[I
1
[[I@4e25154f,
tVarargs ==========
[Ljava.lang.Integer;
3
[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,
- Notice passing
intarr
totVarargs
results in creation of single 2 dimensional array[[I
wit single element. However, what is the types of this array? - Also, passing
intarr
toobjVarargs()
results in creation of 1-D array[Ljava.lang.Object
containing single array element. - For rest, it creates 1-D array with as many elements as passed - the desired behavior.
Can someone shed more light on first two behaviors? Are these two different behaviors or same behaviors, I mean having different or same reason behind them. What are those reasons, in depth? Is there any other cases resulting in different unexpected behavior?
java
I am not sure what is confusing you here.Type...
is justType
but allows us to pass arguments ofType
as list instead of wrapping it into array manually.<T>
is limited to reference types only (it can't represent primitive type likeint
) which meansT...
asT
can't beint
. If you passint
array then most specific object type whichT
can use is array itself. So sinceT
is nowint
T...
is likeint...
which results inint
(that is what[[I
represents).Object...
is simplyObject
array and that is what you see in other method
– Pshemo
Nov 13 '18 at 14:05
add a comment |
I was reading this answer, where it says
Note also that calling a generic vararg method with an explicit array parameter may silently produce different behaviour than expected:
public <T> void foo(T... params) ...
int arr = 1, 2, 3;
foo(arr); // passes an int array containing a single int element
Similar behavior is exaplained in this answer gotcha 3:
int myNumbers = 1, 2, 3 ;
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs only works with reference types. Autoboxing does not apply to array of primitives. The following works:
Integer myNumbers = 1, 2, 3 ;
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"
I tried simpler examples:
private static <T> void tVarargs(T ... s)
System.out.println("nntVarargs ==========");
System.out.println(s.getClass().getName());
System.out.println(s.length);
for(T i : s)
System.out.print(s + ",");
private static void objVarargs(Object ... a)
System.out.println("nnobjVarargs =========== ");
System.out.println(a.getClass().getName());
System.out.println(a.length);
for(Object i : a)
System.out.print(i + ",");
int intarr = 1,2,3;
Integer Intarr = 1,2,3;
objVarargs(intarr);
objVarargs(Intarr);
tVarargs(intarr);
tVarargs(Intarr);
This prints
objVarargs ===========
[Ljava.lang.Object;
1
[I@7852e922,
objVarargs ===========
[Ljava.lang.Integer;
3
1,2,3,
tVarargs ==========
[[I
1
[[I@4e25154f,
tVarargs ==========
[Ljava.lang.Integer;
3
[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,
- Notice passing
intarr
totVarargs
results in creation of single 2 dimensional array[[I
wit single element. However, what is the types of this array? - Also, passing
intarr
toobjVarargs()
results in creation of 1-D array[Ljava.lang.Object
containing single array element. - For rest, it creates 1-D array with as many elements as passed - the desired behavior.
Can someone shed more light on first two behaviors? Are these two different behaviors or same behaviors, I mean having different or same reason behind them. What are those reasons, in depth? Is there any other cases resulting in different unexpected behavior?
java
I was reading this answer, where it says
Note also that calling a generic vararg method with an explicit array parameter may silently produce different behaviour than expected:
public <T> void foo(T... params) ...
int arr = 1, 2, 3;
foo(arr); // passes an int array containing a single int element
Similar behavior is exaplained in this answer gotcha 3:
int myNumbers = 1, 2, 3 ;
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs only works with reference types. Autoboxing does not apply to array of primitives. The following works:
Integer myNumbers = 1, 2, 3 ;
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"
I tried simpler examples:
private static <T> void tVarargs(T ... s)
System.out.println("nntVarargs ==========");
System.out.println(s.getClass().getName());
System.out.println(s.length);
for(T i : s)
System.out.print(s + ",");
private static void objVarargs(Object ... a)
System.out.println("nnobjVarargs =========== ");
System.out.println(a.getClass().getName());
System.out.println(a.length);
for(Object i : a)
System.out.print(i + ",");
int intarr = 1,2,3;
Integer Intarr = 1,2,3;
objVarargs(intarr);
objVarargs(Intarr);
tVarargs(intarr);
tVarargs(Intarr);
This prints
objVarargs ===========
[Ljava.lang.Object;
1
[I@7852e922,
objVarargs ===========
[Ljava.lang.Integer;
3
1,2,3,
tVarargs ==========
[[I
1
[[I@4e25154f,
tVarargs ==========
[Ljava.lang.Integer;
3
[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,[Ljava.lang.Integer;@70dea4e,
- Notice passing
intarr
totVarargs
results in creation of single 2 dimensional array[[I
wit single element. However, what is the types of this array? - Also, passing
intarr
toobjVarargs()
results in creation of 1-D array[Ljava.lang.Object
containing single array element. - For rest, it creates 1-D array with as many elements as passed - the desired behavior.
Can someone shed more light on first two behaviors? Are these two different behaviors or same behaviors, I mean having different or same reason behind them. What are those reasons, in depth? Is there any other cases resulting in different unexpected behavior?
java
java
asked Nov 13 '18 at 13:07
aniranir
423214
423214
I am not sure what is confusing you here.Type...
is justType
but allows us to pass arguments ofType
as list instead of wrapping it into array manually.<T>
is limited to reference types only (it can't represent primitive type likeint
) which meansT...
asT
can't beint
. If you passint
array then most specific object type whichT
can use is array itself. So sinceT
is nowint
T...
is likeint...
which results inint
(that is what[[I
represents).Object...
is simplyObject
array and that is what you see in other method
– Pshemo
Nov 13 '18 at 14:05
add a comment |
I am not sure what is confusing you here.Type...
is justType
but allows us to pass arguments ofType
as list instead of wrapping it into array manually.<T>
is limited to reference types only (it can't represent primitive type likeint
) which meansT...
asT
can't beint
. If you passint
array then most specific object type whichT
can use is array itself. So sinceT
is nowint
T...
is likeint...
which results inint
(that is what[[I
represents).Object...
is simplyObject
array and that is what you see in other method
– Pshemo
Nov 13 '18 at 14:05
I am not sure what is confusing you here.
Type...
is just Type
but allows us to pass arguments of Type
as list instead of wrapping it into array manually. <T>
is limited to reference types only (it can't represent primitive type like int
) which means T...
as T
can't be int
. If you pass int
array then most specific object type which T
can use is array itself. So since T
is now int
T...
is like int...
which results in int
(that is what [[I
represents). Object...
is simply Object
array and that is what you see in other method– Pshemo
Nov 13 '18 at 14:05
I am not sure what is confusing you here.
Type...
is just Type
but allows us to pass arguments of Type
as list instead of wrapping it into array manually. <T>
is limited to reference types only (it can't represent primitive type like int
) which means T...
as T
can't be int
. If you pass int
array then most specific object type which T
can use is array itself. So since T
is now int
T...
is like int...
which results in int
(that is what [[I
represents). Object...
is simply Object
array and that is what you see in other method– Pshemo
Nov 13 '18 at 14:05
add a comment |
1 Answer
1
active
oldest
votes
These two behaviors result from the same issue - both generic type parameters and Object
variables can only hold reference types. A primitive (such as int
) is not a reference type, so passing an int
array to a varargs method (and it doesn't matter if it's Object ... a
or T ... s
) results in the method accepting an array having a single element, and that single element is the int
array.
Therefore you can consider it as a 2 dimensional int
array (i.e. int
) containing a single row.
Note that you have a typo in tVarargs(T ... s)
which results in confusing output. It should be System.out.print(i + ",");
, not System.out.print(s + ",");
Once you fix that, both methods produce the same output for the Integer
input:
[Ljava.lang.Integer;
3
1,2,3,
The difference in the outputs for the int
input results from the fact that in objVarargs(Object ... a)
, the type of the varargs array is Object
, and in tVarargs(T ... s)
it's T
(and when T
is an int
, the type of the array is an int
).
BTW, [[I
is the class name of a two dimensional int
array (i.e. int
).
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53281688%2funderstanding-unexpected-behaviors-of-varargs-in-java%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
These two behaviors result from the same issue - both generic type parameters and Object
variables can only hold reference types. A primitive (such as int
) is not a reference type, so passing an int
array to a varargs method (and it doesn't matter if it's Object ... a
or T ... s
) results in the method accepting an array having a single element, and that single element is the int
array.
Therefore you can consider it as a 2 dimensional int
array (i.e. int
) containing a single row.
Note that you have a typo in tVarargs(T ... s)
which results in confusing output. It should be System.out.print(i + ",");
, not System.out.print(s + ",");
Once you fix that, both methods produce the same output for the Integer
input:
[Ljava.lang.Integer;
3
1,2,3,
The difference in the outputs for the int
input results from the fact that in objVarargs(Object ... a)
, the type of the varargs array is Object
, and in tVarargs(T ... s)
it's T
(and when T
is an int
, the type of the array is an int
).
BTW, [[I
is the class name of a two dimensional int
array (i.e. int
).
add a comment |
These two behaviors result from the same issue - both generic type parameters and Object
variables can only hold reference types. A primitive (such as int
) is not a reference type, so passing an int
array to a varargs method (and it doesn't matter if it's Object ... a
or T ... s
) results in the method accepting an array having a single element, and that single element is the int
array.
Therefore you can consider it as a 2 dimensional int
array (i.e. int
) containing a single row.
Note that you have a typo in tVarargs(T ... s)
which results in confusing output. It should be System.out.print(i + ",");
, not System.out.print(s + ",");
Once you fix that, both methods produce the same output for the Integer
input:
[Ljava.lang.Integer;
3
1,2,3,
The difference in the outputs for the int
input results from the fact that in objVarargs(Object ... a)
, the type of the varargs array is Object
, and in tVarargs(T ... s)
it's T
(and when T
is an int
, the type of the array is an int
).
BTW, [[I
is the class name of a two dimensional int
array (i.e. int
).
add a comment |
These two behaviors result from the same issue - both generic type parameters and Object
variables can only hold reference types. A primitive (such as int
) is not a reference type, so passing an int
array to a varargs method (and it doesn't matter if it's Object ... a
or T ... s
) results in the method accepting an array having a single element, and that single element is the int
array.
Therefore you can consider it as a 2 dimensional int
array (i.e. int
) containing a single row.
Note that you have a typo in tVarargs(T ... s)
which results in confusing output. It should be System.out.print(i + ",");
, not System.out.print(s + ",");
Once you fix that, both methods produce the same output for the Integer
input:
[Ljava.lang.Integer;
3
1,2,3,
The difference in the outputs for the int
input results from the fact that in objVarargs(Object ... a)
, the type of the varargs array is Object
, and in tVarargs(T ... s)
it's T
(and when T
is an int
, the type of the array is an int
).
BTW, [[I
is the class name of a two dimensional int
array (i.e. int
).
These two behaviors result from the same issue - both generic type parameters and Object
variables can only hold reference types. A primitive (such as int
) is not a reference type, so passing an int
array to a varargs method (and it doesn't matter if it's Object ... a
or T ... s
) results in the method accepting an array having a single element, and that single element is the int
array.
Therefore you can consider it as a 2 dimensional int
array (i.e. int
) containing a single row.
Note that you have a typo in tVarargs(T ... s)
which results in confusing output. It should be System.out.print(i + ",");
, not System.out.print(s + ",");
Once you fix that, both methods produce the same output for the Integer
input:
[Ljava.lang.Integer;
3
1,2,3,
The difference in the outputs for the int
input results from the fact that in objVarargs(Object ... a)
, the type of the varargs array is Object
, and in tVarargs(T ... s)
it's T
(and when T
is an int
, the type of the array is an int
).
BTW, [[I
is the class name of a two dimensional int
array (i.e. int
).
edited Nov 13 '18 at 13:35
answered Nov 13 '18 at 13:14
EranEran
285k37463551
285k37463551
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53281688%2funderstanding-unexpected-behaviors-of-varargs-in-java%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I am not sure what is confusing you here.
Type...
is justType
but allows us to pass arguments ofType
as list instead of wrapping it into array manually.<T>
is limited to reference types only (it can't represent primitive type likeint
) which meansT...
asT
can't beint
. If you passint
array then most specific object type whichT
can use is array itself. So sinceT
is nowint
T...
is likeint...
which results inint
(that is what[[I
represents).Object...
is simplyObject
array and that is what you see in other method– Pshemo
Nov 13 '18 at 14:05