getConstructor lanza NoSuchMethodException en Java

Oct 15 2020

Soy muy nuevo en Java, por lo que esta puede ser una pregunta tonta, pero estoy tratando de entender cómo crear una nueva instancia de una clase obteniendo la clase de una instancia existente (creo que esto se llama reflexión).

Actualmente tengo una superclase y varias subclases de ella.

public abstract class SuperClazz {...}

public class SubClazz1 extends SuperClazz {...}

public class SubClazz2 extends SuperClazz {...}

Tengo una instancia existente de una de estas subclases (declarada solo como miembro de la superclase, ya que aún no sé a qué subclase pertenecerá). Estoy tratando de obtener la subclase a la que pertenece esta instancia existente y hacer una nueva instancia de esa misma subclase.

Esta es mi configuración:

private SuperClazz oldSubInstance;
private SuperClazz newSubInstance;

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

Lo que arroja NoSuchMethodException.

Estoy confundido porque sé que SuperClazz tiene un constructor que toma tres parámetros, un String, un char y un int. He visto las respuestas aquí y aquí, pero he descubierto que implementar las correcciones sugeridas no funciona, o que sus problemas no se aplican a mi situación.

¿Estoy entendiendo completamente mal cómo funciona getConstructor?

Respuestas

AlexRudenko Oct 15 2020 at 20:04

Debe asegurarse de que el constructor all-args exista en las clases secundarias.

El siguiente ejemplo crea un 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);

salida ( toStringanulado en el nivel de clase base):

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