0

What if I want to have a variable, say a List, which can be instantiated with any Type?

So, given:

List list;

I could do any of these:

list = new ArrayList<String>();
list = new Vector<Integer>();
list = new LinkedList<HashMap>();

Edit: Alternatively, I may be using a library that returns a raw List. For example, in Hibernate:

List result = session.createQuery( "from Event" ).list();

Eclipse gives me this warning when I want to use List list:

List is a raw type. References to generic type List<E> should be parameterized

Why should this be avoided?

etech
  • 2,548
  • 1
  • 27
  • 24

6 Answers6

4

Eclipse gives me this error when I want to do the above:

I believe eclipse gives you a warning (yellow underlining), not an error (red underlining).

List is a raw type. References to generic type List should be parameterized

Why should this be avoided?

References to generic types should be parameterized because they provide stronger typing. This will help you detect at compile time some problems that otherwise would only be detected at execution time.

For instance:

List myIntegerList = new ArrayList();
myIntegerList.add(1);
myIntegerList.add("bad bad String");

Will compile without problems; but will give you an error at execution time. On the other side:

List<Integer> myIntegerList = new ArrayList<Integer>();
myIntegerList.add(1);
myIntegerList.add("bad bad String"); // compiler will show an error here

Will never compile, as it will show a clear error when trying to add a String to a Integer's List.

Community
  • 1
  • 1
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
2

It is not an error according to Java language, your eclipse is probably configured to flag it as an error. Now, can you identify a usecase where you would want a same variable to hold sometimes Strings and sometimes Integer? As to why this error, anything you get out of it has to be downcasted to the correct type, with the risk of runtime error:

List list = new ArrayList<Integer>();
list.add("string"); // no error from compiler
Map m = (Map) list.get(0); // no error from compiler, but runtime error

compare this to

List<Integer> list = new ArrayList<Integer>();
list.add("string"); // compile error
Map m = (Map) list.get(0); // compile error 
Miserable Variable
  • 28,432
  • 15
  • 72
  • 133
  • I'm using Hibernate, and a call to the Query method `list()` returns a raw List (no Type). Is this an example of when it's "okay" to use a non-parameterized generic type? No matter if I leave it raw `List list` or define a type for list `List list` with a cast `(List)query.list()` I get some kind of unchecked cast or unchecked conversion warning. – etech Apr 12 '13 at 04:35
  • @etech In that case you should assign it to `List>` - that will avoid raw type warnings. `List>` is the generics way of saying "a list with some unknown type". – Paul Bellora Apr 12 '13 at 04:56
  • @PaulBellora Ok, but Eclipse still gives the `should be parameterized` warning with `List>`. I guess just a limitation of IDEs? Adding `@SuppressWarnings("rawtypes")` as suggested by Eclipse also had no effect. Edit: actually, the warning turns to a gray warning sign with no underline. I guess it's 'hidden' now. – etech Apr 12 '13 at 05:17
  • @etech Hmmm, that shouldn't happen. Make sure there aren't other raw types on the same line is all I can suggest. **Edit:** oh, okay - that means it's fixed. – Paul Bellora Apr 12 '13 at 05:23
  • 1
    Note that you cannot add anything to a `List>`, which is a **good thing** – Miserable Variable Apr 12 '13 at 18:04
1

Just because you can do something does not mean it is wise to do. Under what circumstances would you have an object that could be an ArrayList<String>, a Vector<Integer> and a LinkedList<HashMap> at different times? Objects of different types have different purposes. You would probably want a class with a List<String> instance variable, a List<Integer> instance variable, and a List<Map<K, V>> instance variable. Then the problem goes away.

Doing what you suggest will be a great and unpleasant surprise to your coworkers. Keep them happy; do not annoy them to demonstrate your good memory. And, six months from now, do you expect to understand the code you wrote today? Google or look up on this site IOCCC. Those programs were written to be clever, not to be paradigms of best practices.

Eric Jablow
  • 7,874
  • 2
  • 22
  • 29
  • Could be that your solution is the reason Hibernate suggests using separate DAOs with an EntityManager to manage entity instances. One EntityManager per entity means you always know what Type you are dealing with. – etech Apr 12 '13 at 05:59
0

You are getting this warning because you have parametrized the arraylist only and not the list object. So a mixture of generic and non-generic. This can lead to runtime casting exceptions, failing the purpose of generic.

List<String> list = new ArrayList<>();  //If JDK7, not back comptible

List<String> list = new ArrayList<String>();  //If <=JDK7, back compatible

e.g.

List<Integer> list1 = new ArrayList<>();
List list2 = new ArrayList<Integer>();

Just when you try to do an add function of both the lists, you can see the difference,

list1.add("sdfsdfd"); //Takes only integer inputs, compilation error
list2.add(obj); //Takes object type, since obj is not integer type, so will throw classcastexception
Himanshu Bhardwaj
  • 4,038
  • 3
  • 17
  • 36
  • What if I'm using a library that has a method returning a raw List? No mixing of generic and non-generic then, right? – etech Apr 12 '13 at 04:58
  • What that list is supposed to return? If you are unsure you can use, List>, to avoid the warnings. – Himanshu Bhardwaj Apr 12 '13 at 05:06
  • @'Himanshu' Just a raw list: http://docs.jboss.org/hibernate/orm/3.5/javadoc/org/hibernate/Query.html#list%28%29 – etech Apr 12 '13 at 05:09
  • 1
    http://stackoverflow.com/questions/115692/how-to-avoid-type-safety-warnings-with-hibernate-hql-results/118976#118976 Here's your answer – Himanshu Bhardwaj Apr 12 '13 at 07:47
0

try this one it will accept anything which extends Object into your list.

List<? extends Object> list;
list = new ArrayList<String>();
list = new Vector<Integer>();
list = new LinkedList<Map>();
Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Brijesh
  • 191
  • 1
  • 5
  • 11
-1

Below code should be fine:

List<?> list; or

List<? extends Object> list;

For usage of question mark(?) in java, you can refer to Wildcard (Java).

Vincent Jia
  • 592
  • 6
  • 14
  • Doing this causes the same warning message in Eclipse, though interestingly the icon has changed from a lighbulb+warning sign to just a gray warning sign :) – etech Apr 12 '13 at 04:44
  • @etech The gray warning sign is not a warning actually, it marks that "The value of the local variable list is not used.", because you haven't used the variable. You can see the info when move your cursor onto the sign. It'll get disappeared once it's called, for instance, list.add(null); – Vincent Jia Apr 12 '13 at 06:35
  • @'Vincent Jia' Actually, I think it's like a "ghost" icon that just shows the error that was just removed. I've noticed it other places now, and it seems to go away when you continue coding/typing. Thanks for the answer. – etech Apr 12 '13 at 07:44