I java 6 i can declare the arraylist as follows
Way1: using generics i.e <Integer> on right hand side too
List<Integer> p = new ArrayList<Integer>();
Way2: using the diamond operator
List<Integer> p = new ArrayList<>();
Way3: using generic only at left side
List<Integer> p = new ArrayList();
I prefer to use way 3 as its brief. Is there any difference between these ways? Which one we should prefer and why?
Update:- I know in java 7 second way is recommended but my question is in context of java 6. Which one is preferable?
To me, way 3 also says p is an arraylist of integers (same conveyed by way1). So I find no difference except the fact IDE displays warning message:
ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized
As has been pointed out, Way 2 isn't valid in 1.6. So the question is, is there any difference between Way 1 and Way 3. Apart from readability, no.
Take this code:
import java.util.*;
class G {
public static void main(String [] args){
List<Integer> listOne = new ArrayList<Integer>();
listOne.add(1);
int one = listOne.get(0);
List<Integer> listTwo = new ArrayList();
listTwo.add(1);
int two = listTwo.get(0);
}
}
Compile it and look at the bytecode using javap -c
public static void main(java.lang.String[]);
Code:
// FOR listOne
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: iconst_1
10: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
13: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
18: pop
19: aload_1
20: iconst_0
21: invokeinterface #6, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
26: checkcast #7 // class java/lang/Integer
29: invokevirtual #8 // Method java/lang/Integer.intValue:()I
32: istore_2
// FOR listTwo
33: new #2 // class java/util/ArrayList
36: dup
37: invokespecial #3 // Method java/util/ArrayList."<init>":()V
40: astore_3
41: aload_3
42: iconst_1
43: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
46: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
51: pop
52: aload_3
53: iconst_0
54: invokeinterface #6, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
59: checkcast #7 // class java/lang/Integer
62: invokevirtual #8 // Method java/lang/Integer.intValue:()I
65: istore 4
67: return
}
We can see that the exact same bytecode is produced in both cases. Note that as Generics aren't baked in the compiler throws away the information after checking it at compile time and adds in checkcast instructions to make sure the casts it does when retrieving objects are safe.
The second way is not possible in Java 6. It is the new way of inferring Generic instance in Java 7.
There is no difference, if you are using java 7 prefer the second method, but is it not available in java 6. It is a new addition to java 7.
Both are same but way2 is available from java 7
Both are same .But there are version difference in both of this.
But second way is not possible in java 6.In Java 7 if we not declare type in right side then by default it will take same type as left side.
http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html
So as per your updates, if you have to use Java 6,then you should use way1.
Way 3 uses raw types. You should never use raw types. They should only be used in legacy code.
Way 3 is not good. Mixing Generics and raw types is naughty, as you are making an assumption for runtime about types, and can run into ClassCastExceptions like the following code:
ArrayList b = new ArrayList();
b.add(5);
ArrayList<String> a = new ArrayList(b);
System.out.println(a.get(0));
So for Java 6, always use way 1
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.
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?
I am wondering if anyone could give me an answer as to which one of these statements would perform better in java using StringBuilder object:
Using
.append(string1 + string 2)
vs
.append(string1).append(string2)
The second option will almost certainly be superior (assuming there is any noticeable performance difference at all). When you write something like
string1 + string2
it is internally translated to
new StringBuilder(string1).append(string2).toString()
i.e. a new StringBuilder is created to concatenate the strings. Your second variant circumvents this issue since it appends directly to the existing StringBuilder, avoiding the creation of a new one.
We can take a look at the bytecode for each option:
public class Concat {
private static String s1 = "foo";
private static String s2 = "bar";
public static String good() {
StringBuilder b = new StringBuilder();
b.append(s1).append(s2);
return b.toString();
}
public static String bad() {
StringBuilder b = new StringBuilder();
b.append(s1 + s2);
return b.toString();
}
}
$javap -c Concat.class
public static java.lang.String good();
Code:
0: new #2 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
7: astore_0
8: aload_0
9: getstatic #4 // Field s1:Ljava/lang/String;
12: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: getstatic #6 // Field s2:Ljava/lang/String;
18: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: pop
22: aload_0
23: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
26: areturn
public static java.lang.String bad();
Code:
0: new #2 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
7: astore_0
8: aload_0
9: new #2 // class java/lang/StringBuilder
12: dup
13: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
16: getstatic #4 // Field s1:Ljava/lang/String;
19: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: getstatic #6 // Field s2:Ljava/lang/String;
25: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: pop
35: aload_0
36: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
39: areturn
Your first option actually becomes append(new StringBuilder().append(s1).append(s2).toString()).
The first one is quicker to type and in many situations easier to read.
The second one may perform marginally better (as per Jeffrey's bytecode and arshajii's explanation).
However, this kind string concatenation is very unlikely to be the bottleneck in your system! If performance is a problem, you need to profile. Compilers differ. And improving algorithms generally has much, much more impact than this kind of micro-optimization.
Don't optimize earlier than necessary! Really! It's so tempting and such a waste of time.
It may be reasonably expected that a future improvement in the compiler will make both alternatives generate the same code.
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.