# Klasse einer Methode übergeben und überprüfen



## sisko78 (8. Jun 2005)

Hallo,

ich will einer Methode eine Klasse als Parameter übergeben, also etwa so:

```
public void addResource(Class resource) {}
```
Diese Klasse soll dann automatisch instantiiert werden und vielleicht noch überprüft werden, ob ein bestimmtes Interface implementiert und/oder von Thread abgeleitet ist, zudem soll noch eine zeitliche Steuerung der Resourcen stattfinden.
Hab jetzt mal die Methode Class.newInstance() gesichtet, leider kann ich dem Konstruktor so keine Argumente übergeben. Desweiteren bin ich über Class.getConstructor(Class[] parameterTypes) und Contructor.newInstance(Object[]) gestolpert.
Aber vielleicht hat mir jemand einen Tip, wie man das am besten angeht, bevor ich mich hier in die total falsche Richtung bewege.
Danke schonmal

Gruß
sisko78


----------



## Wildcard (8. Jun 2005)

Um sinnvoll mit Reflection instanzieren zu können brauchst du einen sichtbaren Default-Konstruktor.


----------



## Bleiglanz (8. Jun 2005)

stimmt doch nicht? die methode mit dem Object[] ist schon ok


----------



## sisko78 (8. Jun 2005)

Danke, Reflection war das entscheidende Stichwort, hab jetzt auch weitergehende Literatur. Aber ich bin wohl auf dem richtigen Weg gewesen.


----------



## Wildcard (8. Jun 2005)

Bleiglanz hat gesagt.:
			
		

> stimmt doch nicht? die methode mit dem Object[] ist schon ok


natürlich geht das so, aber so wie sich das angehört hat werden recht beliebige Klassen übergeben.
Finde es einfach wesentlich sinnvoller dann einen paramterlosen-Konstruktor anzubieten, als irgendwelche Paramterlisten zu erzeugen
(wenn die Parameter direkt mitgeliefert werden oÄ ist das natürlich was anderes)


----------



## sisko78 (8. Jun 2005)

ja, würde ich auch lieber machen. Sind aber alles Klassen, die gleich aufgebaut sind (müssen ein bestimmtes Interface implementieren) und ein Suchargument bekommen sollen, nach dem in verschiedenen Resourcen (google, wordnet etc.) gesucht werden soll. Sonst müsste ich das irgendwo static hinterlegen.

Jetzt ist aber gerade eine neue Frage aufgekommen:
Ich würde in der addResourceKeywords Methode gerne darauf verzichten, erst die Methoden zu erfragen und dann per invoke aufzurufen.
Ich würde das Object gerne in den zugehörigen Klassentyp casten, um die jeweiligen Methoden ausführen zu können. Geht das irgendwie?  


```
import java.lang.reflect.Constructor;
import java.lang.reflect.*;
import java.util.Vector;


public class DefaultResourceControl {

  String query;
  Object resourceObject;
  Class resourceClass;

  public DefaultResourceControl(String query) {
    this.query = query;
  }
  public boolean isOnlineResource(Class resource) {
    return false;
  }
  /**
   * Checks if the Resource can run an own thread, i.e. if it extends Thread or
   * implements Runnable
   *
   * @return boolean
   */
  public boolean isValidResource() {
    boolean isValid;
    Class[] interfaces = resourceClass.getInterfaces();
    for (int i = 0; i < interfaces.length; i++) {
      if (interfaces[i].getName().equals("java.lang.Runnable")) {
        System.out.println("Class implements Interface Runnable");
        return true;
      }
    }
    if (resourceClass.getSuperclass().getName().equals("java.lang.Thread")) {
      System.out.println("Class extends Thread");
      return true;
    }

    return false;
  }

  /**
   * Here you can add your extern search resource. It has to be a class with a
   * contructor taking one argument of String type. There will be a
   * NoSuchMethodException otherwise. Additionally it has to implement the
   * SearchResource Interface and has to use an own thread, i.e. extend Thread
   * or implement Runnable.
   *
   * @param className String
   */
  public void addResource(String className) {

    try {
      Class resourceClass = Class.forName(className);
      System.out.println("try to add resource: " + resourceClass.getName());
      this.resourceClass = resourceClass;
      Class[] param = new Class[] {
          String.class};
      Constructor constructor =
          (resourceClass).getConstructor(param);
      Object[] arg = new Object[] {
          query};
      this.resourceObject = constructor.newInstance(arg);
      
    }
    catch (Exception e) {
      System.err.println(e.toString());
      System.exit(1);
    }
    if (!isValidResource()){
      return;      
    }
    addResourceKeywords();
  }

  public void addResourceKeywords() {    
    try {
      Method startThread = resourceClass.getMethod("start", null);
      Method join = resourceClass.getMethod("join", null);
      Method getVector = resourceClass.getMethod("getKeywordVector", null);
      startThread.invoke(resourceObject,null);      
      join.invoke(resourceObject,null);
      Vector v1 = (Vector)getVector.invoke(resourceObject,null);
      System.out.println(v1.get(0).toString());//test      
    }
    catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    }    
  }  
}
```


----------



## Wildcard (8. Jun 2005)

sisko78 hat gesagt.:
			
		

> ja, würde ich auch lieber machen. Sind aber alles Klassen, die gleich aufgebaut sind (müssen ein bestimmtes Interface implementieren) und ein Suchargument bekommen sollen, nach dem in verschiedenen Resourcen (google, wordnet etc.) gesucht werden soll.


Wenn die alle den gleichen simplen Konstruktor verwenden ist das ja kein Problem. Vergiss meinen Einwand :wink: 



			
				sisko78 hat gesagt.:
			
		

> Jetzt ist aber gerade eine neue Frage aufgekommen:
> Ich würde in der addResourceKeywords Methode gerne darauf verzichten, erst die Methoden zu erfragen und dann per invoke aufzurufen.
> Ich würde das Object gerne in den zugehörigen Klassentyp casten, um die jeweiligen Methoden ausführen zu können. Geht das irgendwie?



Implementier in allen Klassen ein Interface und caste auf das Interface hin...


----------



## sisko78 (8. Jun 2005)

Wildcard hat gesagt.:
			
		

> Implementier in allen Klassen ein Interface und caste auf das Interface hin...


Jupp, so gehts, danke!


----------

