通过反射创建Java对象后无法访问子类自定义方法如何解决
问题根源
Java是静态强类型语言,方法的存在性校验在编译阶段完成。你写的createObject方法虽然定义了泛型<T extends Base>,但调用时只传入了类名字符串,编译器无法自动推断泛型T的实际类型,默认只会将返回值识别为Base类型,自然无法访问Test1、Test2等子类独有的自定义方法。
解决方案
场景1:编译期已知字符串对应的具体子类
如果你在写代码的时候已经明确知道当前传入的类名对应哪个子类,有两种写法可以实现子类方法调用:
- 写法1:调用时显式指定泛型类型
// 调用Test1的fillTest1方法 Main.<Test1>createObject("reflection.Test1").fillTest1("参数值"); // 调用Test2的fillTest2方法 Main.<Test2>createObject("reflection.Test2").fillTest2("参数值");
- 写法2:将返回值强转为对应子类后调用
Test1 test1 = (Test1) createObject("reflection.Test1"); test1.fillTest1("参数值"); Test2 test2 = (Test2) createObject("reflection.Test2"); test2.fillTest2("参数值");
注意:你提供的示例调用里
fillTest1()没有传参,但是Test1类中定义的fillTest1需要入参,这也是编译报错的原因之一,调用时要补充对应参数。
场景2:编译期完全不知道返回的子类类型
如果类全限定名完全来自外部动态输入,编译期无法预判具体类型,有两种处理方案:
- 方案1:用多态统一方法签名
在父类Base中定义公共抽象方法,所有子类重写该方法,直接调用父类的公共方法即可:
// 修改Base类为抽象类,定义公共抽象方法 public abstract class Base { public void setBase(){ System.out.println("Base method"); } // 定义公共填充方法 public abstract void fill(String value); } // Test1子类重写 public class Test1 extends Base{ private String name; @Override public void fill(String name){ this.name = name; } } // Test2子类重写 public class Test2 extends Base{ private String test2; @Override public void fill(String test2){ this.test2 = test2; } } // 调用时无需感知子类类型 createObject("reflection.Test1").fill("参数值"); createObject("reflection.Test2").fill("参数值");
- 方案2:反射调用子类方法
如果无法修改父类和子类的结构,可以继续用反射调用目标方法:
Object obj = createObject("reflection.Test1"); // 反射调用fillTest1方法 Method method = obj.getClass().getMethod("fillTest1", String.class); method.invoke(obj, "参数值");
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

