Will Java create a new object each time a foreach loop is entered?
I'm not talking about each iteration, but if you have a foreach loop that is used multiple times, is it creating objects each time?
Simple Example:
for(Object o : Objects)
{
for(Object p : Objects2)
{
}
}
Would there only be one p per execution, or would p be instantiated for each Object o?
Does the Garbage Collector have to recover an object from the foreach loop each time it is exited?
More specifically, I'm writing some Android based game code. It will iterate over all the game objects at a given rate per second, or as fast as it can depending on the circumstances.
It may be a case of premature optimization, but if using an explicit for or while loop can guarantee me that I won't have excess garbage collection from my loops, then I can establish that as a coding standard for the project.
More specifically:
public void update()
{
for(GameObject gObj : gameObjects)
{
gObj.update();
}
}
With update() being called from a thread designed to make the calls based on the timing I described before.
Update:
I am asking if there is a new Reference p being created for each o in Objects. Not if it copies the objects in Objects2. So does the VM have to create a new Reference p, and then does it collect that reference between iterations of the outter loop? And more specifically in my case, does it collect the reference between method calls?
Update:
From comments on Matt Ball's answer.
Which would create less Garbage Collection work?
//Loop just to have it run a number of times
//Could be running the inner foreach numerous time for any reason
for(int i = 0; i < 1000; i++)
{
for(Object o : Objects)
{
o.update();
}
}
vs.
Iterator<Object> iter;
//Loop just to have it run a number of times
//Could be running the inner foreach numerous time for any reason
for(int i = 0; i < 1000; i++)
{
iter = Objects.iterator();
while(iter.hasNext());
{
iter.getNext().update();
}
}
Update:
Comparing scopes:
import java.util.ArrayList;
import java.util.Iterator;
public class TestLoops
{
public static Iterator<Object> it;
public static ArrayList<Object> objects;
public static void main(String... args)
{
objects = new ArrayList<Object>();
it = objects.iterator();
it = objects.iterator();
//Every time we start a foreach loop, does it creates a new reference?
Iterator<Object> newIt1 = objects.iterator();
Iterator<Object> newIt2 = objects.iterator();
}
}
Produces this Bytecode:
public class TestLoops {
public static java.util.Iterator<java.lang.Object> it;
public static java.util.ArrayList<java.lang.Object> objects;
public TestLoops();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String...);
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: putstatic #4 // Field objects:Ljava/util/ArrayList;
10: getstatic #4 // Field objects:Ljava/util/ArrayList;
13: invokevirtual #5 // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
16: putstatic #6 // Field it:Ljava/util/Iterator;
19: getstatic #4 // Field objects:Ljava/util/ArrayList;
22: invokevirtual #5 // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
25: putstatic #6 // Field it:Ljava/util/Iterator;
28: getstatic #4 // Field objects:Ljava/util/ArrayList;
31: invokevirtual #5 // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
34: astore_1
35: getstatic #4 // Field objects:Ljava/util/ArrayList;
38: invokevirtual #5 // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
41: astore_2
42: return
}
There is no magical object construction that happens with a for-each loop. This syntax:
for(Object o : Objects)
{
for(Object p : Objects2)
{
}
}
is only shorthand for this:
for(Iterator<Object> iter = Objects.iterator(); iter.hasNext();)
{
Object o = iter.next();
for(Iterator<Object> iter2 = Objects2.iterator(); iter2.hasNext();)
{
Object p = iter2.next();
}
}
If would there be an iter2 reference created for every object I had in Objects?
That depends on where Objects2 comes from. Does it come from o? It also depends on how Objects2.iterator() is implemented. Iterable#iterator() is expected to return independent iterators, which means that Objects2.iterator() would almost certainly return a new Iterator for each invocation. But that does not say anything about whether or not iterating through the objects in Objects2 (using iter2) creates other new objects.
This sounds like premature optimization, overall.
Which would create less Garbage Collection work?
Neither. The enhanced for loop (aka for-each loop) is simply syntactic sugar. The bytecode produced by the compiler is identical. Complete example:
package com.stackoverflow;
import java.util.Iterator;
public class Question14640184
{
public void enhancedForLoop(Iterable<Object> objects1, Iterable<Object> objects2)
{
for(Object o1 : objects1)
{
for(Object o2 : objects2)
{
// do something
}
}
}
public void iteratorForLoop(Iterable<Object> objects1, Iterable<Object> objects2)
{
for(Iterator<Object> iter1 = objects1.iterator(); iter1.hasNext();)
{
Object o1 = iter1.next();
for(Iterator<Object> iter2 = objects2.iterator(); iter2.hasNext();)
{
Object o2 = iter2.next();
}
}
}
}
Compile:
✗ javac Question14640184.java
✗ javap -c Question14640184
Compiled from "Question14640184.java"
public class com.stackoverflow.Question14640184 extends java.lang.Object{
public com.stackoverflow.Question14640184();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public void enhancedForLoop(java.lang.Iterable, java.lang.Iterable);
Code:
0: aload_1
1: invokeinterface #2, 1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
6: astore_3
7: aload_3
8: invokeinterface #3, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
13: ifeq 57
16: aload_3
17: invokeinterface #4, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
22: astore 4
24: aload_2
25: invokeinterface #2, 1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
30: astore 5
32: aload 5
34: invokeinterface #3, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
39: ifeq 54
42: aload 5
44: invokeinterface #4, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
49: astore 6
51: goto 32
54: goto 7
57: return
public void iteratorForLoop(java.lang.Iterable, java.lang.Iterable);
Code:
0: aload_1
1: invokeinterface #2, 1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
6: astore_3
7: aload_3
8: invokeinterface #3, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
13: ifeq 57
16: aload_3
17: invokeinterface #4, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
22: astore 4
24: aload_2
25: invokeinterface #2, 1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
30: astore 5
32: aload 5
34: invokeinterface #3, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
39:
So like I said, the for-each loop is only syntactic sugar.
it's something I'm just fixated on.
Move on, friendo.
It depends entirely on what the Iterable returns. If it creates a new object, so be it. If not, not. In the case of an array, for example, the elements already exist, so no object is created. Same applies to most Collections.
The one case where it almost certainly creates a new object is where the Iterable itself is the result of a function call, for example:
for (Object o : xyz.getIterable())
But this isn't a property of the for-each loop but of the function call.
Related
This question already has answers here:
Java "for" statement implementation prevents garbage collecting
(6 answers)
Closed 4 years ago.
The following example describes the generation of the following lines of code until Java 9.
List data = new ArrayList<>();for (String b : data);
public class Test
{
public Test() {}
public static void main(String[] paramArrayOfString) throws IOException {
ArrayList localArrayList = new ArrayList();
String str;
for (Iterator localIterator = localArrayList.iterator(); localIterator.hasNext(); str = (String)localIterator.next()) {}
}
In Java 10, iterator variables are declared outside for loops and initialized to the null value immediately once the operation is over, so GC can get rid of unused memory.
{
Iterator iterator = data.iterator();
for (; iterator.hasNext();)
{
String b = (String)iterator.next();
}
b = null;
iterator = null;
}
How is setting reference null explicitly better than reference going out of scope by the end of the for loop.
Source: https://dzone.com/articles/features-in-java-10
Also, adding link from the comments : https://bugs.openjdk.java.net/browse/JDK-8192858
Edit: There already exists a related question: Java "for" statement implementation prevents garbage collecting that provides more information.
After reading through the bug-reports (https://bugs.openjdk.java.net/browse/JDK-8192858 and https://bugs.openjdk.java.net/browse/JDK-8175883) the reason for this change can be summarised as the following:
There was an issue in the bytecode produced by javac which resulted in a reference to an array / iterable being kept after the completion of the loop.
As a result, even if an array / iterable is explicitly nullified, there is still a reference to the array / iterable which means that the array / iterable was not eligible for garbage collection until leaving the scope of the method.
With large arrays / iterables (as per the example below) this could result in an OutOfMemoryError.
This is demonstrated by this use case here (taken from the bug report):
public class IteratorInOneScope {
private static final int HALF_OF_MEMORY = (int) (Runtime.getRuntime().maxMemory() * 0.5);
public static void main(String[] args) {
byte[] data = new byte[HALF_OF_MEMORY];
for (byte b : data); // <-- if you comment this line - the application finished successfully
data = null; // this expects to discard reference -> allow to release the memory
byte[] data2 = new byte[HALF_OF_MEMORY]; // the memory can't be allocated second time, if the "for" loop statement above is used
System.out.println("Success");
}
}
Which compiled to the following bytecode:
0: getstatic #2 // Field HALF_OF_MEMORY:I
3: newarray byte
5: astore_0 <==== array ref in slot #0
6: aload_0
7: astore_1 <==== array ref in slot #1
8: aload_1
9: arraylength
10: istore_2
11: iconst_0
12: istore_3
13: iload_3
14: iload_2
15: if_icmpge 29
18: aload_1
19: iload_3
20: baload
21: istore 4
23: iinc 3, 1
26: goto 13
29: aconst_null
30: astore_0 <== nulls slot #0
31: getstatic #2 // Field HALF_OF_MEMORY:I
34: newarray byte
36: astore_1
37: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
40: ldc #4 // String Success
42: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
45: return
There is no update to JLS 14.14.2, for this reason:
JLS 14.14.2 is only concerned with semantics of the statement, not
garbage collection behavior. Compilers are free to generate whatever
bytecode they want that produces the specified behavior. So, if javac
wants to set some unused locals to null, it's free to do so. No spec
change necessary, and it would be a mistake to include it in the spec,
because it doesn't impact the statement's semantics.
I need to convert an ordinal int value to an enum value in Java. Which is simple:
MyEnumType value = MyEnumType.values()[ordinal];
The values() method is implicit, and I cannot locate the source code for it, hence the question.
Does the MyEnumType.values() allocate a new array or not? And if it does, should I cache the array when first called? Suppose that the conversion will be called quite often.
Yes.
Java doesn't have mechanism which lets us create unmodifiable array. So if values() would return same mutable array, we risk that someone could change its content for everyone.
So until unmodifiable arrays will be introduced to Java, for safety values() must return new/separate array holding all values.
We can test it with == operator:
MyEnumType[] arr1 = MyEnumType.values();
MyEnumType[] arr2 = MyEnumType.values();
System.out.println(arr1 == arr2); //false
If you want to avoid recreating this array you can simply store it and reuse result of values() later. There are few ways to do it, like.
you can create private array and allow access to its content only via getter method like
private static final MyEnumType[] VALUES = values();// to avoid recreating array
MyEnumType getByOrdinal(int){
return VALUES[int];
}
you can store result of values() in unmodifiable collection like List to ensure that its content will not be changed (now such list can be public).
public static final List<MyEnumType> VALUES = Collections.unmodifiableList(Arrays.asList(values()));
Theoretically, the values() method must return a new array every time, since Java doesn't have immutable arrays. If it always returned the same array it could not prevent callers muddling each other up by modifying the array.
I cannot locate the source code for it
The values() method has no ordinary source code, being compiler-generated. For javac, the code that generates the values() method is in com.sun.tools.javac.comp.Lower.visitEnumDef. For ECJ (Eclipse's compiler), the code is in org.eclipse.jdt.internal.compiler.codegen.CodeStream.generateSyntheticBodyForEnumValues.
An easier way to find the implementation of the values() method is by disassembling a compiled enum. First create some silly enum:
enum MyEnumType {
A, B, C;
public static void main(String[] args) {
System.out.println(values()[0]);
}
}
Then compile it, and disassemble it using the javap tool included in the JDK:
javac MyEnumType.java && javap -c -p MyEnumType
Visible in the output are all the compiler-generated implicit members of the enum, including (1) a static final field for each enum constant, (2) a hidden $VALUES array containing all the constants, (3) a static initializer block that instantiates each constant and assigns each one to its named field and to the array, and (4) the values() method that works by calling .clone() on the $VALUES array and returning the result:
final class MyEnumType extends java.lang.Enum<MyEnumType> {
public static final MyEnumType A;
public static final MyEnumType B;
public static final MyEnumType C;
private static final MyEnumType[] $VALUES;
public static MyEnumType[] values();
Code:
0: getstatic #1 // Field $VALUES:[LMyEnumType;
3: invokevirtual #2 // Method "[LMyEnumType;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LMyEnumType;"
9: areturn
public static MyEnumType valueOf(java.lang.String);
Code:
0: ldc #4 // class MyEnumType
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class MyEnumType
9: areturn
private MyEnumType(java.lang.String, int);
Code:
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #6 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
6: return
public static void main(java.lang.String[]);
Code:
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #8 // Method values:()[LMyEnumType;
6: iconst_0
7: aaload
8: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
11: return
static {};
Code:
0: new #4 // class MyEnumType
3: dup
4: ldc #10 // String A
6: iconst_0
7: invokespecial #11 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #12 // Field A:LMyEnumType;
13: new #4 // class MyEnumType
16: dup
17: ldc #13 // String B
19: iconst_1
20: invokespecial #11 // Method "<init>":(Ljava/lang/String;I)V
23: putstatic #14 // Field B:LMyEnumType;
26: new #4 // class MyEnumType
29: dup
30: ldc #15 // String C
32: iconst_2
33: invokespecial #11 // Method "<init>":(Ljava/lang/String;I)V
36: putstatic #16 // Field C:LMyEnumType;
39: iconst_3
40: anewarray #4 // class MyEnumType
43: dup
44: iconst_0
45: getstatic #12 // Field A:LMyEnumType;
48: aastore
49: dup
50: iconst_1
51: getstatic #14 // Field B:LMyEnumType;
54: aastore
55: dup
56: iconst_2
57: getstatic #16 // Field C:LMyEnumType;
60: aastore
61: putstatic #1 // Field $VALUES:[LMyEnumType;
64: return
}
However, the fact that the values() method has to return a new array, doesn't mean the compiler has to use the method. Potentially a compiler could detect use of MyEnumType.values()[ordinal] and, seeing that the array is not modified, it could bypass the method and use the underlying $VALUES array. The above disassembly of the main method shows that javac does not make such an optimization.
I also tested ECJ. The disassembly shows ECJ also initializes a hidden array to store the constants (although the Java langspec doesn't require that), but interestingly its values() method prefers to create a blank array then fill it with System.arraycopy, rather than calling .clone(). Either way, values() returns a new array every time. Like javac, it doesn't attempt to optimize the ordinal lookup:
final class MyEnumType extends java.lang.Enum<MyEnumType> {
public static final MyEnumType A;
public static final MyEnumType B;
public static final MyEnumType C;
private static final MyEnumType[] ENUM$VALUES;
static {};
Code:
0: new #1 // class MyEnumType
3: dup
4: ldc #14 // String A
6: iconst_0
7: invokespecial #15 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #19 // Field A:LMyEnumType;
13: new #1 // class MyEnumType
16: dup
17: ldc #21 // String B
19: iconst_1
20: invokespecial #15 // Method "<init>":(Ljava/lang/String;I)V
23: putstatic #22 // Field B:LMyEnumType;
26: new #1 // class MyEnumType
29: dup
30: ldc #24 // String C
32: iconst_2
33: invokespecial #15 // Method "<init>":(Ljava/lang/String;I)V
36: putstatic #25 // Field C:LMyEnumType;
39: iconst_3
40: anewarray #1 // class MyEnumType
43: dup
44: iconst_0
45: getstatic #19 // Field A:LMyEnumType;
48: aastore
49: dup
50: iconst_1
51: getstatic #22 // Field B:LMyEnumType;
54: aastore
55: dup
56: iconst_2
57: getstatic #25 // Field C:LMyEnumType;
60: aastore
61: putstatic #27 // Field ENUM$VALUES:[LMyEnumType;
64: return
private MyEnumType(java.lang.String, int);
Code:
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #31 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
6: return
public static void main(java.lang.String[]);
Code:
0: getstatic #35 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #41 // Method values:()[LMyEnumType;
6: iconst_0
7: aaload
8: invokevirtual #45 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
11: return
public static MyEnumType[] values();
Code:
0: getstatic #27 // Field ENUM$VALUES:[LMyEnumType;
3: dup
4: astore_0
5: iconst_0
6: aload_0
7: arraylength
8: dup
9: istore_1
10: anewarray #1 // class MyEnumType
13: dup
14: astore_2
15: iconst_0
16: iload_1
17: invokestatic #53 // Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
20: aload_2
21: areturn
public static MyEnumType valueOf(java.lang.String);
Code:
0: ldc #1 // class MyEnumType
2: aload_0
3: invokestatic #59 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #1 // class MyEnumType
9: areturn
}
However, it's still potentially possible that the JVM could have an optimization that detects the fact that the array is copied and then thrown away, and avoids it. To test that, I ran the following pair of benchmark programs that test ordinal lookup in a loop, one which calls values() each time and the other that uses a private copy of the array. The result of the ordinal lookup is assigned to a volatile field to prevent it being optimized away:
enum MyEnumType1 {
A, B, C;
public static void main(String[] args) {
long t = System.nanoTime();
for (int n = 0; n < 100_000_000; n++) {
for (int i = 0; i < 3; i++) {
dummy = values()[i];
}
}
System.out.printf("Done in %.2f seconds.\n", (System.nanoTime() - t) / 1e9);
}
public static volatile Object dummy;
}
enum MyEnumType2 {
A, B, C;
public static void main(String[] args) {
long t = System.nanoTime();
for (int n = 0; n < 100_000_000; n++) {
for (int i = 0; i < 3; i++) {
dummy = values[i];
}
}
System.out.printf("Done in %.2f seconds.\n", (System.nanoTime() - t) / 1e9);
}
public static volatile Object dummy;
private static final MyEnumType2[] values = values();
}
I ran this on Java 8u60, on the Server VM. Each test using the values() method took around 10 seconds, while each test using the private array took around 2 seconds. Using the -verbose:gc JVM argument showed there was significant garbage collection activity when the values() method was used, and none when using the private array. Running the same tests on the Client VM, the private array was still fast, but the values() method became even slower, taking over a minute to finish. Calling values() also took longer the more enum constants were defined. All this indicates that the values() method really does allocate a new array each time, and that avoiding it can be advantageous.
Note that both java.util.EnumSet and java.util.EnumMap need to use the array of enum constants. For performance they call JRE proprietary code that caches the result of values() in a shared array stored in java.lang.Class. You can get access to that shared array yourself by calling sun.misc.SharedSecrets.getJavaLangAccess().getEnumConstantsShared(MyEnumType.class), but it is unsafe to depend on it as such APIs are not part of any spec and can be changed or removed in any Java update.
Conclusion:
The enum values() method has to behave as if it always allocates a new array, in case callers modify it.
Compilers or VMs could potentially optimize that allocation away in some cases, but apparently they don't.
In performance-critical code, it is well worth taking your own copy of the array.
Could anybode exlain why generic <Object[]> causes a ClassCastException (RuntimeException!)
I know that all generics removing while compilation phase and do not have any effect to the bytecode. But it seems it has some nuance.
Here my example (simplified for this post):
public class CastTest {
public static void main(String[] args) {
List a = new ArrayList();
a.add(new Object());
List<Object[]> b = a;
b.get(0).toString();
}
}
this code returns:
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to [Ljava.lang.Object;
at CastTest.main(CastTest.java:9)
I do not understand what is wrong with this code. Could anybody explain this behavior?
You are telling the compiler that you want to call Object[].toString(). That's why the compiler generates a cast (checkcast):
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: new #4 // class java/lang/Object
12: dup
13: invokespecial #1 // Method java/lang/Object."<init>":()V
16: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
21: pop
22: aload_1
23: astore_2
24: aload_2
25: iconst_0
26: invokeinterface #6, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
31: checkcast #7 // class "[Ljava/lang/Object;"
34: invokevirtual #8 // Method java/lang/Object.toString:()Ljava/lang/String;
37: pop
38: return
You can prevent the bytecode cast by adding a cast yourself in the Java code:
public static void main(String[] args) {
List a = new ArrayList();
a.add(new Object());
List<Object[]> b = a;
((Object) b.get(0)).toString();
}
Now the compiler sees that a cast to Object[] is not needed since you only want an Object reference. The checkcast opcode is omitted:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: new #4 // class java/lang/Object
12: dup
13: invokespecial #1 // Method java/lang/Object."<init>":()V
16: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
21: pop
22: aload_1
23: astore_2
24: aload_2
25: iconst_0
26: invokeinterface #6, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
31: invokevirtual #7 // Method java/lang/Object.toString:()Ljava/lang/String;
34: pop
35: return
Maybe it's clearer if you look at it like this:
import java.util.ArrayList;
import java.util.List;
class Dog { }
class Cat { }
public class CastTest {
public static void main(String[] args) {
List a = new ArrayList();
a.add(new Dog());
List<Cat> b = a;
Cat c = b.get(0);
}
}
$ java CastTest
Exception in thread "main" java.lang.ClassCastException: Dog cannot be cast to Cat
at CastTest.main(CastTest.java:12)
If fact it's not true that generics don't affect the byte code. If you use javap to see the byte code for the above, you can see that a cast is generated to make sure the object is really a Cat before doing the assignment:
...
26: invokeinterface #7, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
31: checkcast #8 // class Cat
34: astore_3
35: return
If you really want it to be a List of Object arrays, you have to add an Object array:
import java.util.ArrayList;
import java.util.List;
public class CastTest {
public static void main(String[] args) {
List a = new ArrayList();
a.add(new Object[]{});
List<Object[]> b = a;
System.out.println(b.get(0).toString());
}
}
$ java CastTest
[Ljava.lang.Object;#65685e30
As others have said, because the Object is not Object[]
There is hint in the phrase java.lang.Object cannot be cast to [Ljava.lang.Object
According to JNI types and Data Structures, [Ljava.lang.Object means:
[ - an array
L - a Class
So java.lang.Object cannot be cast to [Ljava.lang.Object can be read as Object cannot be cast to Array of Object
Why are you casting it in list of Object array.
Try List of Object and it will work.
import java.util.ArrayList;
import java.util.List;
public class CastTest {
public static void main(String[] args) {
List a = new ArrayList();
a.add(new Object());
List<Object> b = a;
b.get(0).toString();
}
}
This is because the compiler breaks
b.get(0).toString();
down into
Object[] temp = b.get(0);
temp.toString();
which has a cast to Object[] when erased.
Now arguably, the compiler could also choose to break it down into
Object temp = b.get(0);
temp.toString();
since the reference is only used to call .toString() which is declared on Object. And if it did that it would avoid the cast. However, why would the compiler put in that extra analysis effort to do something in a different way, when it will only matter if you use the wrong types anyway?
This question already has answers here:
Which is more efficient, a for-each loop, or an iterator?
(7 answers)
Closed 9 years ago.
for(Element e : elementList)
for (Iterator<Element> itr = elementList.iterator(); itr.hasNext();)
First one is much simpler. Are there any advantages or reasons that I want to do the second one?
Internally both of them use iterator, the only difference is that code is more clear and shorter when you used enhanced for loop. Here is what javadoc says about both:
Iterating over a collection is uglier than it needs to be. Consider the following method, which takes a collection of timer tasks and cancels them:
void cancelAll(Collection<TimerTask> c) {
for (Iterator<TimerTask> i = c.iterator(); i.hasNext(); )
i.next().cancel();
}
The iterator is just clutter. Furthermore, it is an opportunity for error. The iterator variable occurs three times in each loop: that is two chances to get it wrong. The for-each construct gets rid of the clutter and the opportunity for error. Here is how the example looks with the for-each construct:
void cancelAll(Collection<TimerTask> c) {
for (TimerTask t : c)
t.cancel();
}
When you see the colon (:) read it as “in.” The loop above reads as “for each TimerTask t in c.” As you can see, the for-each construct combines beautifully with generics. It preserves all of the type safety, while removing the remaining clutter. Because you don't have to declare the iterator, you don't have to provide a generic declaration for it. (The compiler does this for you behind your back, but you need not concern yourself with it.)
For complete description about why we should use for-each loop and not iterator, read this:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
The first form was introduced in Java 5, and the second form is mostly found in legacy code from earlier versions of the language. Nonetheless, there are a few situations where you still need to use the second form; for example, if the loop needs to be able to remove some (or all) of the elements as they're iterated over, then you need to have itr so you can call its remove method.
Iterator can remove() the element from the collection , which cannot be done using for each loop
There is No performance difference. But by using iterator you will have more functionalities to be used. For example you can reference the Iterator in your loop. This allows you to do things like remove collection items getting a ConcurrentModificationException.
You can use following
for (Iterator<Element> itr = elementList.iterator(); itr.hasNext();){
if(o meets some condition){
itr.remove();
}
}
but not this
for(Element e : elementList){
if(o meets some condition){
elementList.remove(e);
}
}
But if this difference doesn't bother you then you can use the one that comforts your.
similar so question
They are very much the same. Consider this code
import java.util.Iterator;
import java.util.ArrayList;
public class IteratorTest {
public static void main(String[] args){
ArrayList<Object> list = new ArrayList();
list.add(new Object());
list.add(new Object());
for(Object o : list)
System.out.println(o);
for(Iterator<Object> itr = list.iterator();itr.hasNext();)
System.out.println(itr.next());
}
}
We then compile it and disassemble it using
javap -c IteratorTest
and get the following bytecode for the main method
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: new #4 // class java/lang/Object
12: dup
13: invokespecial #1 // Method java/lang/Object."<init>":()V
16: invokevirtual #5 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
19: pop
20: aload_1
21: new #4 // class java/lang/Object
24: dup
25: invokespecial #1 // Method java/lang/Object."<init>":()V
28: invokevirtual #5 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
31: pop
32: aload_1
33: invokevirtual #6 // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
36: astore_2
37: aload_2
38: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
43: ifeq 63
46: aload_2
47: invokeinterface #8, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
52: astore_3
53: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
56: aload_3
57: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
60: goto 37
63: aload_1
64: invokevirtual #11 // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
67: astore_2
68: aload_2
69: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
74: ifeq 92
77: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
80: aload_2
81: invokeinterface #8, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
86: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
89: goto 68
92: return
}
Lines 32 to 60 are the first loop and lines 63 to 89 are the second loop. You will notice that they're pretty much the same - just with the names of some locals changed and slight reordering.
Therefore, as the compiler produces the same bytecode for the two expressions they are the same.
When initialising an instance of a Generic class in Java is there any benefit to specifying the Type on both sides of the statement?
Or to put it another way, what's the difference between these two valid statements:
ArrayList<String> test = new ArrayList<String>();
and:
ArrayList<String> test = new ArrayList();
(It seems second statement is not equivalent to:
ArrayList<String> test = new ArrayList<Object>();
as the third statement in invalid and causes an incompatible types compile error.)
The second statement winds up being more or less equivalent to the first, but only because generics are erased at runtime. You'll get an "unchecked conversion" warning, which is why I don't like it.
A better way is to have a static generic method like this:
public static <T> List<T> newList() {
return new ArrayList<T>();
}
and then do
List<String> test = newList();
This is what Google Collections does.
(And you should almost always be declaring your lists as List, not as ArrayList. Makes it easy to switch the implementation later.)
Edit: dribeas asked in the comments what the exact difference is between the two declarations, and why I said they are "more or less equivalent". Because of type erasure, the only difference between them is the warning. Here's a small piece of code comparing them:
import java.util.*;
class GenericDeclarationTest {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("");
String s1 = list1.get(0);
List<String> list2 = new ArrayList();
list2.add("");
String s2 = list2.get(0);
}
}
And here's the generated bytecode (as printed by javap -c GenericDeclarationTest):
Compiled from "GenericDeclarationTest.java"
class GenericDeclarationTest extends java.lang.Object{
GenericDeclarationTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #4; //String
11: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: aload_1
18: iconst_0
19: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
24: checkcast #7; //class java/lang/String
27: astore_2
28: new #2; //class java/util/ArrayList
31: dup
32: invokespecial #3; //Method java/util/ArrayList."<init>":()V
35: astore_3
36: aload_3
37: ldc #4; //String
39: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
44: pop
45: aload_3
46: iconst_0
47: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
52: checkcast #7; //class java/lang/String
55: astore 4
57: return
}
As you can see (if you have the patience), the two are identical.
Incidentally, this may become easier in Java 7. There is a proposal in Project Coin for "Improved Type Inference for Generic Instance Creation". If it makes the final cut, the syntax will be:
List<String> test = new ArrayList<>();
// or
Map<String, Object> test2 = new HashMap<>();
Not too hard to type, is it?
That redundancy is annoying. You may wish to look at Google Collections that have factory methods which create Lists like this:
List<Double> doubleList = Lists.newLinkedList();
Also note that Java Generics are not covariant.