Anzeige:
Ergebnis 1 bis 7 von 7

Thema: Alle Klassen finden die ein Interface implementieren

  1. #1
    Registrierter Benutzer
    Registriert seit
    02.12.2002
    Ort
    Darmstadt
    Beiträge
    615

    Alle Klassen finden die ein Interface implementieren

    Hallo,

    ich bin auf der Suche nach einer Möglichkeit, zur Laufzeit alle Klassen im CP zu bestimmen, die ein bestimmtes Interface A implementieren. Kennt jemand ein Problem dies zu lösen? Geht das mit Hilfe der Reflection API, oder ist das eher nicht möglich?
    Seine Rätselhaftigkeit wird nur durch seine Macht übertroffen!

  2. #2
    Registrierter Benutzer Avatar von fs111
    Registriert seit
    23.03.2002
    Beiträge
    594
    Hmm, das ist ein interessantes Problem, erstmal müsstest Du ja dafür sorgen, dass auch alle Klassen im CP geladen werden mit den Classloader. Das kann natürlich bei vielen Klassen ruck zuck zu Problemen mit der Perm-Generation führen, wenn Du viele Klassen laden willst. Was ist denn die genaue Anforderung, gibt es evtl. einen anderen Weg das Problem zu lösen?

    fs111
    ....::::Mein Blag::::....

  3. #3
    Registrierter Benutzer
    Registriert seit
    02.12.2002
    Ort
    Darmstadt
    Beiträge
    615
    Es geht um eine Anwendung die sogenannte Policies beinhaltet um eine Simulation zu steuern. Diese sind durch ein Interface Policy definiert. In einem Konfigurationsdialog möchte ich alle verfügbaren Policyklassen anzeigen und auswählbar machen. Eine dynamische Liste dieser Klassen wäre da ein nettes Feature gewesen. Man könnte natürlich in einer Konfigurationsdatei die existierenden Policy Klassen angeben - ich suche aber nach einer Möglichkeit das möglichst dynamisch zu realisieren (also am insbesondere um für eine neue Implementierung die Konfiguration ändern zu müssen).
    Seine Rätselhaftigkeit wird nur durch seine Macht übertroffen!

  4. #4
    Registrierter Benutzer Avatar von Waxolunist
    Registriert seit
    19.06.2006
    Ort
    Wien
    Beiträge
    485
    Bei mir tut das folgender Code:

    Code:
    import java.io.IOException;
    import java.util.Hashtable;
    import java.util.Iterator;
    import java.util.Set;
    
    import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.ClassPathLoader;
    
    public class GetInterfaces {
    
    	public static void main(String[] args) {
    		ClassPathLoader cpl = new ClassPathLoader(".");
    		try {
    			Hashtable ht = cpl.getClasses();
    			Set s = ht.keySet();
    			Iterator iter = s.iterator();
    			String fullName = null;
    			while(iter.hasNext()) {
    				try {
    					fullName = (String) iter.next();
    					Class c = Class.forName(fullName);
    					Class[] interfaces = c.getInterfaces();
    					for(int i = 0; i < interfaces.length; i++) {
    						if(interfaces[i].getName().equals("java.io.Serializable")) {
    							System.out.println(fullName);
    						}
    					}
    				} catch (ClassNotFoundException cnfe) {
    					System.err.println("Found not class " + fullName);
    				} catch (UnsupportedClassVersionError ucve) {
    					System.err.println(ucve);
    				}
    			}
    		} catch (IOException ioe) {
    			ioe.printStackTrace();
    		}
    	}
    }
    Ich habe dafür die libs ant-trax.jar und ant-nodeps.jar aus dem Ant-Build 1.6.5 verwendet.

    Dem ClassPathLoader solltest du einen anderen ClassPath statt . wahrscheinlich übergeben (siehe ClassPathLoader). Ansonsten funktioniert das für mich und ich bekomme hier alle Klassen, die Serializable in meinem ClassPath enthalten.

    mfg, Christian
    Spezialitäten heute: PLSQL, TSQL, Java (alles mit Webanwendungen), Groovy, Grails, ASP.NET, Javascript, Python, Django
    Straight through, ohne Umwege ans Ziel

  5. #5
    Registrierter Benutzer
    Registriert seit
    02.12.2002
    Ort
    Darmstadt
    Beiträge
    615
    Dank dir. Konnte den Code verwenden und hab ihn entsprechend angepasst, so dass er auch mit abstrakten Klassen was anfangen kann.
    Seine Rätselhaftigkeit wird nur durch seine Macht übertroffen!

  6. #6
    Registrierter Benutzer Avatar von Waxolunist
    Registriert seit
    19.06.2006
    Ort
    Wien
    Beiträge
    485
    Cool. Könntest du den dann bitte wieder anderen, ganz im Sinne von OpenSource wieder zur Verfügung stellen?
    Spezialitäten heute: PLSQL, TSQL, Java (alles mit Webanwendungen), Groovy, Grails, ASP.NET, Javascript, Python, Django
    Straight through, ohne Umwege ans Ziel

  7. #7
    Registrierter Benutzer
    Registriert seit
    02.12.2002
    Ort
    Darmstadt
    Beiträge
    615
    Klar. Der Code macht einige Annahmen, die im Projekt selbst erfüllt sind, im Allgemeinen aber nicht.
    Die Methode gibt nicht die Klassennamen zurück, sondern direkt Instanzen dieser Klassen.
    • Die Klassen, die die durch "classname" angegebene Klasse implementieren, einfach instanziieren kann (sprich mit Default Konstruktor).
    • Das class Objekte von einigen Klassen nicht erzeugt werden können (auf Grund fehlender Bibliotheken im CP beispielsweise), wird einfach ignoriert, da diese Klassen in unserem Projekt eh irrelevant sind. Ein Beispiel wäre eine Testklasse in irgendeinem JAR für welche dann JUnit im CP benötigt würde.
    • Da die Methode Class.isAssignableFrom(Class) nicht ausschließt das die Klasse abstrakt ist, muss auch hier die Instanziierung gefangen werden. In unserem Projekt wird einfach eine Warnung erstellt.
    • Unser Projekt fängt noch die Ausgabe von getClasses() ab und arbeitet generell mit log4j, aber das ist hier ja eher irrelevant, sorgt aber dafür, das die verschiedenen try Blöcke nicht zusammengefasst worden sind, sondern einzeln dastehen.


    Code:
    	public List loadInstances(String classname) {
    
    		ClassPathLoader cpl = new ClassPathLoader(System.getProperty("java.class.path", "."));
    		List list = new LinkedList();
    		try {
    			Class superClass = Class.forName(classname);
    			Hashtable ht = cpl.getClasses();
    
    			for (String fullName : (Set<String>) ht.keySet()) {
    				Class c = null;
    				try {
    					c = Class.forName(fullName);
    				} catch (NoClassDefFoundError e) {
    					continue;
    				} catch (UnsatisfiedLinkError e) {
    					continue;
    				}
    
    				if (superClass.isAssignableFrom(c)) {
    					try {
    						list.add(c.newInstance());
    					} catch (InstantiationException e) {
    						System.err.println("Could not instantiate object for class " + c.getCanonicalName());
    					} catch (IllegalAccessException e) {
    						System.err.println("Could not instantiate object for class " + c.getCanonicalName());
    					}
    				}
    			}
    		} catch (IOException ioe) {
    			System.err.println("I/O Exception while searching for " + classname + "!");
    		} catch (ClassNotFoundException e) {
    			System.err.println("Class not found while searching for " + classname + "!");
    		}
    
    		return list;
    	}
    Seine Rätselhaftigkeit wird nur durch seine Macht übertroffen!

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •