views:

160

answers:

6

Hello

Does anyone know why the following code does not compile and during compilation I get incompatible types exception ?

public class Test<T> {

public static void main(String[] args)
{
    // using Test<?> solves the compilation error
    Test test = new Test();

    // getting error incompatible types:
    // found   : java.lang.Object
    // required: java.lang.Integer
    Integer number = test.getDays().get(0);
}


private List<Integer> getDays() {
    return new ArrayList<Integer>();
}

}

and why using Test with the unbounded wildcard solves this ? I'm using java version 1.6.0_12

+1  A: 

Try this:

public class Test<T> {

public static void main(String[] args)
{
    // using Test<?> solves the compilation error
    Test<Integer> test = new Test<Integer>();

    // getting error incompatible types:
    // found   : java.lang.Object
    // required: java.lang.Integer
    Integer number = test.getDays().get(0);
}


private List<Integer> getDays() {
    return new ArrayList<Integer>();
}

} 
Adel Hazzah
The point is: The generic type shouldn't bother the compiler here, as getDays states that it will return a List of Integers (no matter what Type T is set to)
das_weezul
+3  A: 

Slight difference from Adel's answer, but did you mean this?

public class Test<T> {

public static void main(String[] args)
{
    Test<Integer> test = new Test<Integer>();

    Integer number = test.getDays().get(0);
}


private List<T> getDays() {
    return new ArrayList<T>();
}

} 
Dean J
A: 

The compiler can't determine the actual type for Test since you specified it as generic and then used the raw type. Adding the ? wildcard make the compiler aware that the actual class can only be determined at runtime; it won't check the class type.

You can also solve the compilation by either making the Test class non-generic or by making getDays() return a List.

AngerClown
+1  A: 

Hi! I tried to compile it and I have the same issues. I don't think the OP wants an explanation on how to use generics. Try it for yourself ... the odd thing is that it "should" work, because the generic type T isn't being used at all, as the declaration of getDate states that it will return a reference to a List of Integers.

You could instantiate test like this:

Test<JFrame> test = new Test();

... and it compiles! (of course you can use any existing Type here ...) Odd thing ...

If you remove the generic declaration it also works (of course).

das_weezul
+7  A: 

I am interpreting the question as why doesn't test.getDays() return List<Integer> when the return type is not dependent on the type parameter, T?

When you create a variable that is a raw reference to an instance of Test the compiler drops all generics for access via that variable (for backwards compatibility).

Because test doesn't have its type <T> specified this also means that the <Integer> for getDays is discarded.

mikej
Thanks for that!Can you give an example for a backward compatibility issue which this behavior solves ?
The issue that before Java 1.5 you couldn't use `List<Something>` you had to use `List`. So if you drop the `<T>` in your class, the compiler will assume you want to use it in pre-generics mode, and drop all other `<Something>` as well.
Andrei Fierbinteanu
A: 

When you declare a variable or field as a raw type, all usages of that field or variable lose all generic information, not just the generic information related to the type variable dropped by the raw type. That means your call to test.getDays() returned a List rather than a List<Integer>, even though Integer is unrelated to T.

ILMTitan