generics - ClassCastException in Java foreach loop -


in circumstances can classcastexception occur in code below:

import java.util.arrays; import java.util.list;  public class generics {      static list getobjects() {         return arrays.aslist(1, 2, 3);     }      public static void main(string[] args) {         list<string> list = getobjects();         (object o : list) { // classcastexception?             system.out.println(o);         }     } } 

we had similar case in production environment (bad practice, know) , customer provided log classcastexception @ line comment can't seem reproduce it. thoughts?

i know jvm creates iterator in background when using foreach, can create raw iterator in cases , parametrized 1 in other cases?

update:i had @ bytecode generated , on windows, using jdk 1.6.0_21-b07 no checkcast made. interesting :)

here main method:

 public static void main(java.lang.string[]);   code:    0:   invokestatic    #34; //method getobjects:()ljava/util/list;    3:   astore_1    4:   aload_1    5:   invokeinterface #36,  1; //interfacemethod java/util/list.iterator:()ljava/util/iterator;    10:  astore_3    11:  goto    28    14:  aload_3    15:  invokeinterface #42,  1; //interfacemethod java/util/iterator.next:()ljava/lang/object;    20:  astore_2    21:  getstatic   #48; //field java/lang/system.out:ljava/io/printstream;    24:  aload_2    25:  invokevirtual   #54; //method java/io/printstream.println:(ljava/lang/object;)v    28:  aload_3    29:  invokeinterface #60,  1; //interfacemethod java/util/iterator.hasnext:()z    34:  ifne    14    37:  return 

thanks answers!

update 2: got mislead eclipse ide uses own compiler bytecode above it's 1 generated using eclipse compiler. here how manually compile code eclipse. in conclusion eclipse compiler generates different byte-code sun compiler in cases, regardless of platform, case described here being one.

shouldn't code always throw classcastexception? me using sun java 6 compiler , runtime (on linux). you're casting integers strings. iterator created iterator<string>, tries access first element, integer, , fails.

this gets clearer if change array so:

return arrays.aslist("one", 2, 3); 

now loop works first element, because first element string , see output; iterator<string> fails on second one, because isn't string.

your code works if use generic list instead of specific one:

list list = getobjects(); (object o : list) {     system.out.println(o); } 

...or, of course, if use list<integer>, since contents integers. you're doing triggers compiler warning — note: generics.java uses unchecked or unsafe operations. — , reason.

this modification works:

for (object o : (list)list) 

...presumably because @ point you're dealing iterator, not iterator<string>.

bozho has said doesn't see error on windows xp (didn't mention compiler , runtime, i'm guessing sun's), , you're not seeing (or not reliably), there's implementation sensitivity here, bottom line is: don't use list<string> interact list of integers. :-)

here's file i'm compiling:

import java.util.arrays; import java.util.list;  public class generics {      static list getobjects() {         return arrays.aslist("one", 2, 3);     }      public static void main(string[] args) {         list<string> list = getobjects();         (object o : list) { // classcastexception?             system.out.println(o);         }     } } 

here's compilation:

tjc@forge:~/temp$ javac generics.java  note: generics.java uses unchecked or unsafe operations. note: recompile -xlint:unchecked details.

here's run:

tjc@forge:~/temp$ java generics  1 exception in thread "main" java.lang.classcastexception: java.lang.integer cannot cast java.lang.string     @ generics.main(generics.java:12)

line 12 for statement. note did output first element, because changed string. didn't output others. (and before made change, failed immediately.)

here's compiler i'm using:

tjc@forge:~/temp$ javac /usr/bin/javac tjc@forge:~/temp$ ll /usr/bin/javac lrwxrwxrwx 1 root root 23 2010-09-30 16:37 /usr/bin/javac -> /etc/alternatives/javac* tjc@forge:~/temp$ ll /etc/alternatives/javac lrwxrwxrwx 1 root root 33 2010-09-30 16:37 /etc/alternatives/javac -> /usr/lib/jvm/java-6-sun/bin/javac*

here's disassembly, shows checkcast:

tjc@forge:~/temp$ javap -c generics compiled "generics.java" public class generics extends java.lang.object{ public generics();   code:    0:   aload_0    1:   invokespecial   #1; //method java/lang/object."":()v    4:   return  static java.util.list getobjects();   code:    0:   iconst_3    1:   anewarray   #2; //class java/io/serializable    4:   dup    5:   iconst_0    6:   ldc #3; //string 1    8:   aastore    9:   dup    10:  iconst_1    11:  iconst_2    12:  invokestatic    #4; //method java/lang/integer.valueof:(i)ljava/lang/integer;    15:  aastore    16:  dup    17:  iconst_2    18:  iconst_3    19:  invokestatic    #4; //method java/lang/integer.valueof:(i)ljava/lang/integer;    22:  aastore    23:  invokestatic    #5; //method java/util/arrays.aslist:([ljava/lang/object;)ljava/util/list;    26:  areturn  public static void main(java.lang.string[]);   code:    0:   invokestatic    #6; //method getobjects:()ljava/util/list;    3:   astore_1    4:   aload_1    5:   invokeinterface #7,  1; //interfacemethod java/util/list.iterator:()ljava/util/iterator;    10:  astore_2    11:  aload_2    12:  invokeinterface #8,  1; //interfacemethod java/util/iterator.hasnext:()z    17:  ifeq    40    20:  aload_2    21:  invokeinterface #9,  1; //interfacemethod java/util/iterator.next:()ljava/lang/object;    26:  checkcast   #10; //class java/lang/string    29:  astore_3    30:  getstatic   #11; //field java/lang/system.out:ljava/io/printstream;    33:  aload_3    34:  invokevirtual   #12; //method java/io/printstream.println:(ljava/lang/object;)v    37:  goto    11    40:  return  }

again, though, bottom line has be: don't use list<string> interact list contains things aren't strings. :-)


Comments

Popular posts from this blog

ASP.NET/SQL find the element ID and update database -

jquery - appear modal windows bottom -

c++ - Compiling static TagLib 1.6.3 libraries for Windows -