4

Using Java's Generics features I created a List object and on the left hand side I am using the raw type List where on the right hand side I am using the generic type ArrayList< String >.

List myList=new ArrayList<String>();

And I added one int value into the list object.

myList.add(101);

I was hoping that I will get some compilation error but this program is running fine.But if I use generic type List< String > on the left hand side and raw type ArrayList on the right hand side and try to add an int value into the list, I am getting compilation error as expected.

List<String> myList=new ArrayList();
myList.add(101);//The method add(int, String) in the type List<String> is not applicable for the arguments (int)

Why in Java generics right hand side type of the collection does not have any effect? And why Java allowing us to do so when it does not have any effect.I am using Java 1.6. Please explain.

Bacteria
  • 8,406
  • 10
  • 50
  • 67
  • 2
    Have a read about [type erasure](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html) – npe Apr 30 '15 at 20:42
  • possible duplicate of [How do generics of generics work?](http://stackoverflow.com/questions/16449799/how-do-generics-of-generics-work) – ControlAltDel Apr 30 '15 at 20:44
  • Thanks for ur reply but my main concern is I am declaring List myList=new ArrayList(); At a glance it looks like myList can only store String because I mentioned the type String in the right hand side. But myList can store any kind of object. Why Java is allowing us to mention the type in the right hand side? Isn’t confusing? Probably, that why they introduced the Diamond operator in java 7. – Bacteria Apr 30 '15 at 22:02

4 Answers4

4

If you don't supply a generic type parameter on the left-hand side, the List is declared as a raw type. This means the compiler doesn't know what is legal or not to store in that list, and is relying on the programmer to perform appropriate instanceof checks and casts.

Raw types also have the effect of obliterating all generic type information in the class they appear in.

The JLS provides a much more detailed look at raw types. You should be seeing a warning in your IDE or from the compiler about the assignment to a raw type as well:

To make sure that potential violations of the typing rules are always flagged, some accesses to members of a raw type will result in compile-time unchecked warnings. The rules for compile-time unchecked warnings when accessing members or constructors of raw types are as follows:

At an assignment to a field: if the type of the left-hand operand is a raw type, then a compile-time unchecked warning occurs if erasure changes the field's type.

At an invocation of a method or constructor: if the type of the class or interface to search (§15.12.1) is a raw type, then a compile-time unchecked warning occurs if erasure changes any of the formal parameter types of the method or constructor.

No compile-time unchecked warning occurs for a method call when the formal parameter types do not change under erasure (even if the result type and/or throws clause changes), for reading from a field, or for a class instance creation of a raw type.

Thorn G
  • 12,620
  • 2
  • 44
  • 56
1

Tom G's answer is nice and explains things in detail, but I get the feeling that you already know at least some of that stuff, because you said this:

I was hoping that I will get some compilation error

So, let me address precisely that part.

The reason you are not getting any compilation error is because generics were added as an afterthought in java, and for this reason many generics-related issues which ought to be errors have instead been demoted to warnings in order to not break existing code.

And what is most probably happening is that these warnings are turned off in your development environment.

Steps to correct the problem:

  1. Go to the options of your IDE

  2. Find the "warnings" section.

  3. Enable EVERYTHING.

  4. Pick your jaw from the floor after you have seen the enormous number of warnings you get.

  5. Disable all the warnings that do not make any sense, like "hard-coded string" or "member access was not qualified with this", keep everything else. Be sure that the one which says something like "Raw use of parameterized class" is among the ones you keep.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
1

At a glance it looks like myList can only store String

At a glance, perhaps. But it's really important to realize that there is no such thing as "a list that can only store Strings", at least in the standard APIs.

There is only List, and you have to include the right instructions to the compiler to berate you if you try to add something that's not a String to it, i.e. by declaring it as List<String> myList.

If you declare it as "plain old List", the compiler has no instructions as to what to allow or disallow you to put into it, so you can store anything within the type bounds of the backing array, namely, any Object.

The fact that you say new ArrayList<String>() on the RHS of the assignment is irrelevant: Java doesn't attempt to track the value assigned to a variable. The type of a variable is the type you declare.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
0

"... generics right hand side of type of the collection does not have any effect" is mostly true. When the "var" keyword is substituted for "List", the right hand side generic does have an effect. The code below creates an ArrayList of Strings.

var myList = new ArrayList<String>();
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
Andre
  • 1
  • 1