2

currenty I'm facing a problem with generic classes in Java.

I have something like this:

public class GenericClass<T> {
    T doSomething() {...}

    Collection<String> getCollection() {...}
}

Now I instantiate an object of that class without the type parameter, since I'm not intereseted in that or I don't know it.

GenericClass obj = new GenericClass();
for (String str : obj.getCollection() { // won't work
    ...
}

The problem is, that the compiler does not simply throw away the information about the type-parameter, but also about the type of the Collection (String), although that's independent from the parameter.

Am I doing something wrong, or is that a restriction of Java? If so, why is that a restriction?

chrert
  • 462
  • 2
  • 12

3 Answers3

4

You're doing something wrong.

When you don't know the T type, you should just use a wildcard: GenericClass<?>. You can't do this when you're instantiating a new GenericClass, though, so just use Object:

GenericClass<?> obj = new GenericClass<Object>();

For backwards-compatibility reasons, it is deliberate that a class without any generic information at all (GenericClass without any <>) loses all generic type safety so it can be used safely with pre-generic code.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • @LouisWasserman can you explain, why it doesn't work with the raw type? The return type of the method is `Collection`, which is independent from the generic type. – jlordo May 20 '13 at 17:35
  • @jlordo I'm not sure what answer I can give you, other than that "use of raw types eliminates _all_ generic type safety, because the JLS says so." – Louis Wasserman May 20 '13 at 17:49
  • @LouisWasserman: Ok, sounds reasonable. But then, why does the solution posted by Rahul Bobhate work without an error? – jlordo May 20 '13 at 17:52
  • @jlordo Because when calling `getCollection` on the raw type `GenericClass`, it returns raw `Collection`. Conversion from a raw type to a generic type will cause an unchecked conversion warning instead of an error. – Paul Bellora May 20 '13 at 18:25
  • Yup. I don't believe that Rahul's solution works without at least a warning. – Louis Wasserman May 20 '13 at 18:26
  • @PaulBellora: If you'd written that 2 minutes ago, I wouldn't have asked following question: [http://stackoverflow.com/questions/16655806/raw-types-with-generic-methods-independent-of-the-generic-type](http://stackoverflow.com/questions/16655806/raw-types-with-generic-methods-independent-of-the-generic-type). Now I understand and it makes sense. Post is an answer on my question, and I'll accept it. – jlordo May 20 '13 at 18:27
  • @jlordo: No, your other question is legitimately interesting independent of this. ;) – Louis Wasserman May 20 '13 at 18:32
  • 1
    @jlordo Looks like Louis took care of it. Ha, we have our own little economy going here :) – Paul Bellora May 20 '13 at 18:33
4

The following code works perfectly fine. Instead of directly extracting values from obj.getCollectionn(), it would be preferable to store it to some Collection variable and then access it.

GenericClass obj = new GenericClass();
Collection<String> c = obj.getCollection();
for (String string : c) 
{
    //Some complex Code
}
Rahul Bobhate
  • 4,892
  • 3
  • 25
  • 48
0

Creating an instance of a generic type without specifying the type parameter is a practice that should only ever be done by legacy code. Any new code that you are writing should not do this. This is called using a "raw type" and compromises all the compile-time type safety that you had written a generic class for in the first place.

Also, just a note that I hope you'll find helpful as well: if you plan to use your own value-based class instances in the Collection framework, you'll need to give some thought to providing a well-behaved implementation of equals() and hashcode(). Not doing this (and relying upon the default behavior of the Object class for equals() and hashcode()) may mean that your objects don't function well in your collections.

scottb
  • 9,908
  • 3
  • 40
  • 56