2008-11-24 6 views
74

Der folgende CodeBug in Eclipse-Compiler oder in Javac

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(); 
    } 
} 

kompiliert in Eclipse, aber nicht mit Javac (Typ-Parameter von T nicht bestimmt werden kann ("Typ-Parameter von T nicht bestimmt werden kann"); keine eindeutige Die maximale Instanz existiert für die Typvariable T mit den oberen Grenzen T, java.lang.Object).

Wenn ich readObject- (String-Datei)

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

ändern kompiliert es in Eclipse und mit javac. Wer ist richtig, der Eclipse-Compiler oder Javac?

Antwort

66

Ich würde sagen, es ist der Fehler in der Sun-Compiler here und here berichtet, denn wenn Sie Ihre Linie auf die unter einem ändern Es funktioniert mit beiden, was genau zu sein scheint, was in den Fehlerberichten beschrieben wird.

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

In diesem Fall würde ich sagen, dass Ihr Code falsch ist (und der Sun-Compiler hat Recht). Es gibt in Ihren Eingabeargumenten zu readObject nichts, um tatsächlich auf den Typ T zu schließen. In diesem Fall empfiehlt es sich, Object zurückgeben zu lassen und Clients den Ergebnistyp manuell zu übertragen.

Dies sollte funktionieren (obwohl ich es nicht getestet):

public static <T> T readObject(String file) throws Exception { 
    return GenericsTest2.<T>readObject(new ObjectInputStream(new FileInputStream(file))); 
} 
+1

return GenericsTest2. readObject (neuer ObjectInputStream (neuer FileInputStream (Datei))); funktioniert. Vielen Dank! –

+1

Ich stimme nicht zu, es sieht eher aus wie der unten beschriebene Fehler. Der Compiler sollte eine explizite Umwandlung ohne Typinferenz vertrauen - die folgenden kompiliert feinen @SuppressWarnings ("ungeprüft") public static T createT (String classname) throws Exception { return (T) Class.forName (classname) .newInstance(); } –

3

Oracle JDK6 u22 sollte korrekt sein, aber ich habe dieses Problem mit JDK6 u24 zu

Dies ist ein Fehler von Eclipse bug 98379.

Dies wurde nicht korrigiert, aber das Problem wird über Abhilfe wie zB in Eclipse Bugs (siehe Link)

0

aufgelöst Wenn Sie Ihre Methode readObject- ändern können transparent zu arbeiten, wenn sie aufgerufen, können Sie auch folgende Zwecke verwenden:

public static <T> T readObject(String file, Class<T> type) throws Exception { 
    return type.cast(readObject(new ObjectInputStream(new FileInputStream(file)))); 
} 

Auf diese Weise muss der Aufrufer den Typ des Ergebnisses angeben und der Compiler weiß, wie das Ergebnis umgesetzt wird.

1

Ich habe dieses Problem in der Java-Version "1.6.0_22" gefunden. Es verschwand, als ich auf Java-Version "1.6.0_32" aktualisierte, wie es in Update 25 behoben wurde.