getConstructor löst eine NoSuchMethodException in Java aus

Oct 15 2020

Ich bin sehr neu in Java, daher mag dies eine dumme Frage sein, aber ich versuche zu verstehen, wie eine neue Instanz einer Klasse erstellt wird, indem die Klasse von einer vorhandenen Instanz abgerufen wird (ich denke, dies wird als Reflexion bezeichnet).

Derzeit habe ich eine Superklasse und mehrere Unterklassen davon.

public abstract class SuperClazz {...}

public class SubClazz1 extends SuperClazz {...}

public class SubClazz2 extends SuperClazz {...}

Ich habe eine vorhandene Instanz einer dieser Unterklassen (nur als Mitglied der Superklasse deklariert, da ich noch nicht weiß, zu welcher Unterklasse sie gehören wird). Ich versuche, die Unterklasse zu ermitteln, zu der diese vorhandene Instanz gehört, und eine neue Instanz derselben Unterklasse zu erstellen.

Dies ist mein Setup:

private SuperClazz oldSubInstance;
private SuperClazz newSubInstance;

newSubInstance = oldSubInstance.getClass().getConstructor(String.class, char.class, int.class).newInstance("abc", 'e', 6);

Was NoSuchMethodException auslöst.

Ich bin verwirrt, weil ich weiß, dass SuperClazz einen Konstruktor hat, der drei Parameter akzeptiert, einen String, ein Zeichen und ein Int. Ich habe hier und hier Antworten angesehen , aber festgestellt, dass die Implementierung der vorgeschlagenen Korrekturen nicht funktioniert oder dass ihre Probleme nicht auf meine Situation zutreffen.

Verstehe ich völlig falsch, wie getConstructor funktioniert?

Antworten

AlexRudenko Oct 15 2020 at 20:04

Sie müssen sicherstellen, dass der Konstruktor all-args in den untergeordneten Klassen vorhanden ist.

Das folgende Beispiel erstellt ein newSubInstance:

// using Lombok annotations for brevity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
abstract class SuperClazz {
    private String str;
    private char chr;
    private int x;

    // getters/setters/default and all-args constructors provided by Lombok
}


class SubClazz1 extends SuperClazz {
    public SubClazz1(String str, char c, int i) { // providing constructor in the child class
        super(str, c, i);
    }
}

// test
SuperClazz oldSubInstance = new SubClazz1("def", 'g', 10);
SuperClazz newSubInstance;

newSubInstance = oldSubInstance.getClass()
                               .getConstructor(String.class, char.class, int.class)
                               .newInstance("abc", 'e', 6);

System.out.println(newSubInstance);

Ausgabe ( toStringauf Basisklassenebene überschrieben):

SuperClazz(str=abc, chr=e, x=6)