ArrayList Generic without Type

别来无恙 提交于 2019-12-17 16:26:26

问题


recently I read a piece of code which seems weird to me. As we know, we need to initialize the generic type in collections when we need to use them. Also, we know Collections can contain Collections as their elements.

The code:

public class Solution {
public static void main(String args[]) {
    ArrayList res = returnlist();
    System.out.print(res.get(0));
}
public static ArrayList<ArrayList<Integer>> returnlist() {
    ArrayList result = new ArrayList();
    ArrayList<Integer> content = new ArrayList<Integer>();
    content.add(1);
    result.add(content);
    return result;
}}

My question is

  • why can we use ArrayList result = new ArrayList(); to create an object, since we have not gave the collection the actual type of element.
  • why can we use result.add(content); to add a collection to a collection with collection "result" is just a plain collection. We have not defined it as a ArrayList of ArrayList

回答1:


Java generic collections are not stored with a type to ensure backwards compatibility with pre J2SE 5.0. Type information is removed when added to a generic collection. This is called Type Erasure.

This means that a generic collection can be assigned to a non generic reference and objects in a generic typed collection can be placed in an non generic, nontyped collection.

All Java generics really does is make sure you can't add the wrong type to a generic list and saves you from doing an explicit cast on retrieval; even though it is still done implicitly.

Further to this

  • the Java section of this answer goes a little deeper into what I just said
  • this article also covers basically what you were asking in a more complete way
  • other things to watch out for with Type Erasure



回答2:


Just adding up to provide summarized answer

Old way :

(A) ArrayList result = new ArrayList();

will create an Arraylist to hold "Object"


New Way :

ArrayList<Integer> content = new ArrayList<Integer>();

this represents an Arraylist which will hold "Integer" objects. This was introduced for compile-time type check purposes.


why ?

Consider the first case. Its input type is Object. We know that Object is the super class of all classes. We can pass in an Integer object, String object and so on. When fetching the data the developer has to perform proper type casting. Say if the developer initially thinks the code will accept Integer objects so he adds the following typecast while fetching the data

Integer integer=(Integer) content.get(0);

This is supposed to work. But if mistakenly he passes a String it will result in run-time error.

How it can be avoided ?

By introducing compile time checks


How it works ?

when we specify parameterized type only Integer objects can be added to the ArrayList collection. Else it will show error.

content.add(3); // will work
content.add("HARSHAD"); // error shown

If parameterized generic types are for type checking purposes how correct data can be retrieved from the list ?

The compiler implicitly performs type conversion. See the sample code

List<Integer> list=new ArrayList<Integer>();
list.add(1);
list.add(2);
Integer integer=list.get(0);
System.out.println(integer);

What the compiler actually does when you perform compilation ?

//perform type erasure
(B) List list=new ArrayList();
    list.add(1);
    list.add(2);

// the arraylist inturn accepts Object when you run the code 

//add casting 
Integer integer=(Integer)list.get(0);

Conclusion

If you see the codes (A) and (B) both are the same. Only difference is that in the second case the compiler implicitly does the same operation.

Finally to answer your question ...

ArrayList result = new ArrayList();

is allowed for backward compatibility purposes. Although this is not recommended.

Official link from Oracle docs explaining the same concept.




回答3:


It may be a remnant from before generics came along to java (Java 4 or 5 I think).




回答4:


Generics were added to Java only in Java 5. Before that, when you use a collection, it always meant collection of objects. The old syntax is left as is for backward compatibility. So ArrayList result = new ArrayList() is actually creating an ArrayList<Object>. Since ArrayList is also an object, you can add content to the variable result.




回答5:


why can we use ArrayList result = new ArrayList(); to create an object, since we have not give the collection the actual type of element.

Because java wants to it backward compatible. Generics is more of compiler feature for ensure type safety, collections can store any type of object at runtime.

Java compiler will not give you compiler error for this but it must have given you compiler warning that it is unsafe to use generic classes without type.



来源:https://stackoverflow.com/questions/25689673/arraylist-generic-without-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!