views:

2671

answers:

4

The following code

public class GenericsTest2 {

    public static void main(String[] args) throws Exception {
        Integer i = readObject(args[0]);
        System.out.println(i);
    }

    public static <T> T readObject(String file) throws Exception {
        return readObject(new ObjectInputStream(new FileInputStream(file)));
        // closing the stream in finally removed to get a small example
    }

    @SuppressWarnings("unchecked")
    public static <T> T readObject(ObjectInputStream stream) throws Exception {
        return (T)stream.readObject();
    }
}

compiles in eclipse, but not with javac (type parameters of T cannot be determined; no unique maximal instance exists for type variable T with upper bounds T,java.lang.Object).

When I change readObject(String file) to

    @SuppressWarnings("unchecked")
    public static <T> T readObject(String file) throws Exception {
        return (T)readObject(new ObjectInputStream(new FileInputStream(file)));
    }

it compiles in eclipse and with javac. Who is correct, the eclipse compiler or javac?

A: 

have you checked, whether eclipse and the command line support the same java-version (javac -version)? maybe your command-line is older?

Peter Miehle
both have source and target 1.6
Tobias Schulte
+1  A: 

That could be a result of the Error/Warnings settings of your project (or of eclipse)

If Java Compiler / Error/warnings / Generic types settings are on ignore, it will compile on eclipse, but not with javac.

That would be because eclipse would call its own java compiler with a -Xlint:none or a -nowarn option.

The recommendation when this happen is to open a bug in JDT section of eclipse bugzilla.

But your case seems to look like bug 6302954 (it is not the same though), meaning the eclipse compiler is not affected by this Sun bug which is actually still broken in javac 1.6.0_07.

VonC
Eclipse does not use javac, it has it's own compiler. When I enable all generic errors in Eclipse, I get an error in readObject(ObjectInputStream stream), not in the other method.
Tobias Schulte
+6  A: 

In this case, I'd say your code is wrong (and the Sun compiler is right). There is nothing in your input arguments to readObject to actually infer the type T. In that case, you're better off to let it return Object, and let clients manually cast the result type.

This should work (though I haven't tested it):

public static <T> T readObject(String file) throws Exception {
    return <T>readObject(new ObjectInputStream(new FileInputStream(file)));
}
Chris Jester-Young
return GenericsTest2.<T>readObject(new ObjectInputStream(new FileInputStream(file))); does work. Thanks!
Tobias Schulte
I disagree, it looks more like the bug related below. The compiler should trust an explicit cast without type inference - the following compiles fine @SuppressWarnings("unchecked") public static <T> T createT(String className) throws Exception { return (T) Class.forName(className).newInstance(); }
Duncan McGregor
+4  A: 

I'd say it's the bug in the Sun compiler reported here and here, because if you change your line to the one below it works with both, which seems to be exactly what is described in the bug reports.

return GenericsTest2.<T>readObject(new ObjectInputStream(new FileInputStream(file)));
Fabian Steeg