Generics - warning: unchecked cast


#1

Moin,

ich hoffe ihr habt Weihnachten gut überstanden… :wink:

Ich möchte verschiedene Objekttypen in XML-Dateien ablegen und später wieder einlesen.
Dazu habe ich mir eine Klasse zum Serialisieren mit XML von JavaBeans geschrieben, die ich euch erstmal zeige:

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

class XMLStructureIO<T> {

    private final String filename;

    XMLStructureIO(String filename) {
        this.filename = filename;
    }

    void write(T obj) throws FileNotFoundException {
        XMLEncoder enc = new XMLEncoder(new BufferedOutputStream(
                new FileOutputStream(filename)));
        enc.writeObject(obj);
        enc.close();
    }

    T read() throws FileNotFoundException {
        XMLDecoder dec = new XMLDecoder(new BufferedInputStream(
                new FileInputStream(filename)));
        T obj = (T) dec.readObject();
        dec.close();
        return obj;
    }
}

Die Klasse funktioniert soweit. Das Problem hier ist aber, dass ich eine Warnung beim Kompilieren erhalte:

warning: [unchecked] unchecked cast
        T obj = (T) dec.readObject();
  required: T
  found:    Object
  where T is a type-variable:
    T extends Object declared in class XMLStructureIO

Jetzt wüsste ich gerne, wie man dieses Problem behebt. Danke für eure Zeit und Mühe


#2

Das wird nicht gehen.

Die Methode „readObject“ gibt ein object zurück. Wenn du das etwas zuweist, wird es immer eine Warnung geben.

Du könntest JaxB nehmen. Dies hat eine generische unmarshal Methode.

Du könntest reflection nutzen, um den cast durchzuführen. ;))


#3

Ja, da gibt es so direkt tatsächlich nichts. In manchen Fällen kann man an so einer Stelle (wie hier der read-Methode) dann ein Class<T> expectedType übergeben um mit Class#isInstance oder Class#cast rumzuhantieren, aber das wäre hier vermutlich kaum sinnvoll möglich.


#4

Außer JaxB fällt mir da auch nix zu ein. Wobei man dazu sagen muss, dass dort die unchecked cass auch nur durch dynamisch erzeugten Code/Casts kaschiert werden.


#5

Naja, die Methode für das unmarshall ist einfach generisch geschrieben. Es wird da nix dynamisch erzeugt.

Es gibt noch http://x-stream.github.io/tutorial.html da lässt es sich auch generisch machen.


#6

Ich kenne JAXB nur in dem Kontext bei dem Java-Objekte anhand der XML Schema dynamisch erzeugt werden.


#7

Also es ist nur ein Databinding zwischen XML und einem Java Objekt. Das passiert via Reflection dynamisch. Es wird aber kein Code generiert.


#8

Vielen Dank an alle!

Ich werde es dann wohl erst mal so lassen. Ist ja nun kein Beinbruch.


#9

Wenn dich die Warnung “nervt” kannst du die Methode noch mit @SuppressWarnings(“unchecked”) annotieren. Sprich wenn du weißt, dass dieser Stelle nichts schief geht (und das ist in deinem Fall so), kannst du damit die Warning unterdrücken.


#10

Hi ButAlive, danke für deinen Einwurf.

Das könnte ich machen, ja. Ich habe aber nach einer Lösung gesucht, das generische Objekt des übergebenen Typs zurück zu bekommen. Dass das in dem Fall offenbar nicht sauber mit “pure Generics” machbar scheint, war mit bis dahin nicht klar.