getConstructor พ่น NoSuchMethodException ใน Java

Oct 15 2020

ฉันยังใหม่กับ Java มากดังนั้นนี่อาจเป็นคำถามที่โง่ แต่ฉันกำลังพยายามทำความเข้าใจวิธีสร้างอินสแตนซ์ใหม่ของคลาสโดยรับคลาสจากอินสแตนซ์ที่มีอยู่ (ฉันคิดว่าสิ่งนี้เรียกว่าการสะท้อน)

ตอนนี้ฉันมีคลาสซุปเปอร์และคลาสย่อยหลายคลาส

public abstract class SuperClazz {...}

public class SubClazz1 extends SuperClazz {...}

public class SubClazz2 extends SuperClazz {...}

ฉันมีอินสแตนซ์ของคลาสย่อยเหล่านี้อยู่แล้ว (ประกาศว่าเป็นสมาชิกของคลาสระดับสูงเท่านั้นเนื่องจากฉันยังไม่รู้ว่าจะเป็นคลาสย่อยใด) ฉันกำลังพยายามหาว่าอินสแตนซ์ที่มีอยู่นี้เป็นของคลาสย่อยใดและสร้างอินสแตนซ์ใหม่ของคลาสย่อยเดียวกันนั้น

นี่คือการตั้งค่าของฉัน:

private SuperClazz oldSubInstance;
private SuperClazz newSubInstance;

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

ซึ่งพ่น NoSuchMethodException

ฉันสับสนเพราะฉันรู้ว่า SuperClazz มีคอนสตรัคเตอร์ที่รับพารามิเตอร์สามตัวคือสตริงอักขระและ int ฉันได้ดูคำตอบที่นี่และที่นี่แต่พบว่าการใช้การแก้ไขที่แนะนำไม่ได้ผลหรือปัญหาของพวกเขาใช้ไม่ได้กับสถานการณ์ของฉัน

ฉันเข้าใจผิดอย่างสิ้นเชิงว่า getConstructor ทำงานอย่างไร

คำตอบ

AlexRudenko Oct 15 2020 at 20:04

คุณต้องตรวจสอบให้แน่ใจว่าตัวสร้างออลอาร์กมีอยู่ในคลาสเด็ก

ตัวอย่างต่อไปนี้สร้าง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);

เอาท์พุท ( toStringแทนที่ที่ระดับคลาสพื้นฐาน):

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