views:

309

answers:

4

I'm using Netbeans. When I run the program below, I get this as output [I@de6ced! How come?

import java.util.Arrays;
import java.util.Vector;

public class Test {

public static void main (String[] args) {
     int[] a = new int[1];
     a[0] = 5;
     Vector<Integer> a1 = new Vector(Arrays.asList(a));
     System.out.println(a1.elementAt(0));
 }
}

I also tried working around it but then I got a

Exception in thread "main" java.lang.ClassCastException: [I cannot be cast to java.lang.Integer at TopCoder.Test.main(Test.java:13) Java Result: 1

public static void main (String[] args) {
    int[] a = new int[1];
    a[0] = 5;
    Vector<Integer> a1 = new Vector(Arrays.asList(a));

    int b = a1.elementAt(0); /* EXCEPTION THROWN HERE */
    System.out.println(b);
}
A: 

It looks like the int's are becoming Integers using autoboxing so you are getting an object reference instead of the value. Still seems weird as it should call the correct toString and end up with "5".

Brendan Heywood
Wrong answer. The Integer class overrides toString() to give you the String form of the value. So you should see "5".
Stephen C
+5  A: 

[I@de6ced can be broken down as:
- [ an array
- I of integers
- de6ced with this reference hash-code (which, in Sun Java, is basically the reference)

toString() for Object returns somethine like ClassName@HashCode, which is exactly what you're seeing happen here just with the (rather wierd) primitive-array classes.

The problem is that the wrong type is being inferred by the <T> List<T> asList(T...) method. Change your code to use Integer[] instead of int[]. This is a consequence of int being primitive, but int[] is an object.

You can see this directly:

System.out.println(Arrays.asList(new int[]{5}));

=> [[I@some reference

System.out.println(Arrays.asList(new Integer[]{5}).get(0));

=> 5

Kevin Montrose
+1 for noticing that the code supplied does not match the reported behavior!
Stephen C
I'm sure I haven't left anything out. That's the output I get when I compile that program ...
There's something weird with generics/boxing going on there I think, I'll get back to you in a second.
Kevin Montrose
Thanks for helping me out !
+1  A: 
Integer[] a = new Integer[1];
a[0] = new Integer(5);
List list = Arrays.asList(a);
System.out.println(list.get(0));

The above works as you would expect.

So it looks like the "int" array is treated like an Object and not an array of Integers. In other words auto boxing doesn't seem to be applied to it?

camickr
Oh thanks ! It worked ! I changed int[] a = new int[1];to Integer[] a = new Integer[1];. Thank you !!!!
This is nasty. Autoboxing is nice when it works, but when it does not (as in this case) it makes for hard-to-understand behaviour (and SCJP trick questions). Probably a result of autoboxing (and varargs and generics) being added to the language fairly late. If it had been in Java from the beginning, these ambiguities could have been avoided.
Thilo
A: 

I think I have figured out what was happening:

 int[] a = new int[1];
 a[0] = 5;

We now have an array of int.

 Vector<Integer> a1 = new Vector(Arrays.asList(a));

The problem is in the way you are calling Arrays.asList.

The signature for asList is "public static <T> List<T> asList(T... a)". It does not apply with T == int because int is not an object type. And it cannot match with T == Integer because the base type of the array a is int not Integer. What is actually happening is that T is binding to int[], and Arrays.aslist(a) is returning a List<int[]> with one element that is the value of a!!!

Then you create a Vector from the List and get a Vector with one element ... the original int[] that was assigned to 'a'.

 System.out.println(a1.elementAt(0));

Finally, a1.elementAt(0) fetches the int[], and you end up calling the Object implementation of the toString() method.

A couple of important lesson to learn from this:

  • it is a bad idea to mix raw types and generic types as you do on the line that declares a1, and
  • it is a bad idea to ignore, or turn off the compiler's generic type-safety warnings
Stephen C
so if he had written "new Vector<Integer>(Arrays.asList(a))" it would have worked? Or at least failed to compile?
Thilo
@Thilo: it should have given compilation warning saying that the actual argument type doesn't match the constructor's parameter type.
Stephen C
@Thilo: indeed, there should have been a compiler warning for the original version as well, about assigning a raw type to a parameterized type.
Stephen C
Warnings are fine when the type declaration is missing, but when I go to the trouble to write "new Vector<Integer>", I would want it to either work (and no warnings) or detect the problem and refuse to compile.
Thilo
Just checked: There will be a compile error "The constructor Vector<Integer>(List<int[]>) is undefined". I am happy now.
Thilo