getConstructor lança NoSuchMethodException em Java

Oct 15 2020

Sou muito novo em Java, então essa pode ser uma pergunta idiota, mas estou tentando entender como criar uma nova instância de uma classe obtendo a classe de uma instância existente (acho que isso se chama reflexão).

Atualmente tenho uma superclasse e várias subclasses dela.

public abstract class SuperClazz {...}

public class SubClazz1 extends SuperClazz {...}

public class SubClazz2 extends SuperClazz {...}

Eu tenho uma instância existente de uma dessas subclasses (declarada apenas como membro da superclasse, pois ainda não sei a qual subclasse ela pertencerá). Estou tentando obter qualquer subclasse a que pertence esta instância existente e fazer uma nova instância dessa mesma subclasse.

Esta é a minha configuração:

private SuperClazz oldSubInstance;
private SuperClazz newSubInstance;

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

Que lança NoSuchMethodException.

Estou confuso porque sei que o SuperClazz tem um construtor que leva em três parâmetros, um String, um char e um int. Eu vi as respostas aqui e aqui, mas descobri que implementar as correções sugeridas não funciona ou que seus problemas não se aplicam à minha situação.

Estou totalmente mal entendido como getConstructor funciona?

Respostas

AlexRudenko Oct 15 2020 at 20:04

Você precisa ter certeza de que o construtor all-args existe na (s) classe (s) filha.

O exemplo a seguir cria um 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);

saída ( toStringsubstituído no nível da classe base):

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