Liste von Klassen die ein Interface implementieren speichern

Status
Nicht offen für weitere Antworten.

Progman

Mitglied
Hallo

Ich versuche aus einem Verzeichniss alle Klassen auszulesen die ein bestimmtes Interface implementieren in eine Liste zu speichern. Hierbei geht es um das Interface "MapGenerator". Ich hab dann erstmal eine Liste erstellt bzw. in meinem Fall eine Map.
Code:
Map<String, Class<? extends MapGenerator>> foobar;

Nun durchlaufe ich mein Verzeichnis mit File.listFiles() und so und lasse mir mit ClassLoader.loadFrom(...) die Klasse laden und zurückgeben. Von diesem Objekt ruf ich Class.getInterfaces() auf und gucke ob mein Interface dabei ist. Wenn ja will ich diese Klasse in meine Map speichern. Jedoch klappt das nicht ohne eine Warnung.
Code:
net/sourceforge/structor/MapFactory.java:83: warning: [unchecked] unchecked cast
found   : java.lang.Class
required: java.lang.Class<? extends net.sourceforge.structor.MapGenerator>
                System.out.println((Class<? extends MapGenerator>)tmp);
                                                                  ^
net/sourceforge/structor/MapFactory.java:84: warning: [unchecked] unchecked conversion
found   : java.lang.Class
required: java.lang.Class<? extends net.sourceforge.structor.MapGenerator>
                this.generators.put("foobar", tmp);
Wobei "tmp" das Class-Objekt von ClassLoader.loadFrom(). Je nach dem wie ich es versuche zu casten, entweder direkt oder ich lasse die Map.put() Methode casten, erhalte ich diese Warnung. Wie krieg ich nun sauber die Variable tmp nach Class<? extends MapGenerator> gecastet? Ich bin dabei auf Class.cast() gestoßen, jedoch weiß ich nicht wie ich ein Objekt vom Typ Class<? extends MapGenerator> erstelle. Oder gibt es vielleicht einen eleganteren weg?

Hier mein bisheriger Code
Code:
    public MapFactory() {
        this.generators = new HashMap<String, Class<? extends MapGenerator>>();
        File f = new File("net/sourceforge/structor");
        if (!f.exists() || !f.isDirectory()) {
            throw new RuntimeException("directory net/sourceforge/structor/ doesn't exists.");
        }
        File[] files = f.listFiles();
        for (int i=0; i<files.length; i++) {
            if (!files[i].canRead()) {
                continue;
            }
            if (!files[i].getName().endsWith(".java")) {
                continue;
            }
            String classname = files[i].getName().replaceAll("\\.java$", "");
            Class  tmp = null;
            try {
                // tmp can be every class
                tmp = ClassLoader.getSystemClassLoader().loadClass("net.sourceforge.structor."+classname);
            } catch (ClassNotFoundException e) {
                System.out.println(e);
                System.exit(16);
            }
            Class[] interfaces = tmp.getInterfaces();
            boolean found = false;
            for (int j=0; j<interfaces.length; j++) {
                if (interfaces[j].equals(MapGenerator.class)) {
                    found = true;
                    break;
                }
            }
            if (found) {
                // "tmp" is a valid class of MapGenerator, save it.
                System.out.println("loaded Map Generator "+tmp);
                System.out.println(tmp);
                System.out.println(tmp.getClass());
                System.out.println("-: "+MapGenerator.class);
                //System.out.println((MapGenerator.class).cast(tmp));
                System.out.println((Class<? extends MapGenerator>)tmp);
                this.generators.put("foobar", tmp);
                // this.generators.put(((MapGenerator)tmp.newInstance()).getType(), tmp);
            }
        }
    }
 
Ignorier die Warnung oder mach @SuppressWarnings("unchecked") über die Methode und fertig.
Du weißt ja das der Typ passt, insofern ist es nicht wirklich "unchecked".
 
statt @SupressWarnings kann ich auch ohne -Xlint:unchecked kompilieren, aber das will ich ja grad nicht. Ich will sauber casten und dachte da an Class.cast() (was auch eine ClassCastException werfen kann). Jedoch klappen Ausdrucke wie
Code:
Class<? extends MapGenerator>.cast(tmp);
bzw.
Code:
(Class<? extends MapGenerator>).cast(tmp);
nicht (parse error)
 
Code:
try{
  ((Class<? extends MapGenerator>)tmp)
}catch(ClassCastException cce){}
hilft dir das?
 
Ob ich da ein try-catch Block drum mache oder nicht, es bleibt der selbe cast und ich krieg somit auch die Warnung "net/sourceforge/structor/MapFactory.java:85: warning: [unchecked] unchecked cast"
 
Es gibt wohl keine Möglichkeit ein Object vom Typ Class nach Class<? extends MapGenerator> zu casten ohne das eine Warnung erzeugt wird. Somit gebe ich auf und benutze @SupressWarning(). 🙁
 
Progman hat gesagt.:
Es gibt wohl keine Möglichkeit ein Object vom Typ Class nach Class<? extends MapGenerator> zu casten ohne das eine Warnung erzeugt wird. Somit gebe ich auf und benutze @SupressWarning(). 🙁
So ist es. Die Warnung ist ja dazu da, auf potentielle Fehlerquellen hinzuweisen.
Wenn man weiss, dass der betreffende Code korrekt ist, kann man die Warnung
unterdrücken.
 
Lass doch einfach diesen ganzen Generic-Overhead weg und mach stattdessen:
Code:
  HashMap<String, Class> generators;

Da brauchste auch kein @SuppressWarnings...
 
wenn ich die Klassen aus der Map auslese und diese "nur" als 'Map<String, Class> generators' speicher dann muss ich später bei newInstance() nach (MapGenerator) casten. Dann hab ich das selbe Problem nur woanders. Die Map soll ja nur spezielle Class-Objekte enthalten, nicht allgemein irgendwelche Class-Objekte (auch wenn ich weiß dass dort nur Class-Objekte reinkommen die MapGenerator implementieren).
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben