# getConstructor() wirft NoSuchMethodException .



## Tobias (15. Apr 2008)

Hi,

ich habe folgende Situation:


```
interface IFactory { }
```


```
class Factory implements IFactory { }
```


```
class C {

    public C(IFactory a) {
    }

}
```

Klasse Factory möchte nun Instanzen von C erzeugen. Um den Konstruktor zu suchen, nutze ich folgenden Code:


```
C.class.getConstructor(Factory.class);
```

Leider wirft das eine NoSuchMethodException, obwohl doch Factory doch ein IFactory ist. Ich verstehe das nicht so recht. Könnt ihr helfen?

mpG
Tobias


----------



## Marco13 (15. Apr 2008)

Versuch' mal http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getDeclaredConstructor(java.lang.Class...)


----------



## Tobias (15. Apr 2008)

Mein Testprogramm wirft damit weiterhin eine NoSuchMethodException.

mpG
Tobias


----------



## Marco13 (15. Apr 2008)

Oha, da war ich etwas vorschnell, sorry.   

Offenbar braucht man _genau_ den richtigen Typ. Man kann das gewünschte Verhalten aber durch eine Utility-Funktion nachbauen, die sich alle Konstruktoren holt, und bei allen die Parametertype checkt, ob der gewünschte Parameter den gegeben Typen zuweisbar ist...

```
import java.lang.reflect.*;

interface IFactory { }

class Factory implements IFactory { }
class Factory2 {}

class C
{
    public C(IFactory a)
    {
    }

}

class ReflectionConstructorTest
{
    public static void main(String args[])
    {
        try
        {
            Constructor a = getConstructor(C.class, Factory.class);
            //Constructor a = getConstructor(C.class, Factory2.class);

            System.out.println(a);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public static <T> Constructor<T> getConstructor(Class<T> c, Class... desiredParameterTypes)
        throws NoSuchMethodException
    {
        Constructor constructors[] = c.getConstructors();
        for (int i=0; i<constructors.length; i++)
        {
            Class<?> parameterTypes[] = constructors[i].getParameterTypes();
            boolean isCompatible = false;
            if (parameterTypes.length == desiredParameterTypes.length)
            {
                isCompatible = true;
                for (int j=0; j<desiredParameterTypes.length; j++)
                {
                    Class<?> type = parameterTypes[i];
                    Class<?> desiredType = desiredParameterTypes[i];
                    if (!type.isAssignableFrom(desiredType))
                    {
                        isCompatible = false;
                        break;
                    }
                }
            }
            if (isCompatible)
            {
                //System.out.println("Matching: "+constructors[i]);
                return constructors[i];
            }
        }
        throw new NoSuchMethodException("No matching constructor found");
    }


}
```

Ist nur kurz getetest, schau auf jeden fall nochmal drüber, ob das auch passt und in allen anderen Fällen funktioniert. 

Eigentlich müßte man auch noch sicherstellen, dass immer der _spezifischte_ Typ genommen wird - an eine Methode
void foo(Object x)
können natürlich Objekte ALLER Klassen übergeben werden. Wenn es aber eine Methode
void foo(C c)
gibt, dann muss bei einem Aufruf wie
foo(someC);
auch die foo(C) aufgerufen werden, und nicht foo(Object).


----------



## Tobias (15. Apr 2008)

Mh, schade, dass getConstructor() das nicht schon von sich macht. Aber danke für die hübsche Funktion, darauf kann ich aufbauen !

mpG
Tobias


----------



## quippy (16. Apr 2008)

Tobias hat gesagt.:
			
		

> Klasse Factory möchte nun Instanzen von C erzeugen. Um den Konstruktor zu suchen, nutze ich folgenden Code:



Warum suchst Du den Konstruktor nicht wie üblich mit den Parametertypen?!


```
public static Object instanciate(Class theClass, Class[] paramTypes, Object[] param)
	{
		try
		{
			// Instanzierung via Constructor
			java.lang.reflect.Constructor constructor = theClass.getConstructor(paramTypes);
			return constructor.newInstance(param);
		}
		catch (InvocationTargetException ite)
		{
			throw new ClassMapperTargetException(ite.getMessage(), ite.getTargetException());
		}
		catch (Throwable ex)
		{
			throw new ClassMapperException("instantiation failed: " + ex.getMessage(), ex);
		}
	}
```

So habe ich mir das mal gebaut...


----------



## SlaterB (16. Apr 2008)

> Warum suchst Du den Konstruktor nicht wie üblich mit den Parametertypen?! 


genau das hat Tobias doch 1 Zeile nach der von dir gequoteten gemacht?!
darum gehts doch in dem ganzen Thread?


----------



## quippy (16. Apr 2008)

OKOKOK - das habe ich dann wohl nicht richtig gelesen.

Er hätte C.class.getConstructor(*I*Factory.class); machen müssen - daher die umfangreiche Methode mit dem "isAssignable" und eigener Iteration.

Jaja.


----------

