Java泛型继承问题:子类BPage为何使用APageData而非BPageData?
分析Java泛型中BPage使用APageData而非BPageData的问题
嘿,我来帮你捋捋这个泛型问题哈!首先得还原下大概率的代码场景(毕竟你没贴代码,但这个问题在泛型里太常见了),然后咱们一步步拆解原因:
先看错误代码的典型场景
假设你的代码大概是这样的:
// 父类数据类 class APageData { public String getId() { return "//*[@id=\"id_1\"]"; } } // 子类数据类,重写了getId方法 class BPageData extends APageData { @Override public String getId() { return "//*[@id=\"id_2\"]"; } } // 父类页面类 class APage { private APageData data = new APageData(); public APageData getData() { return data; } } // 子类页面类 class BPage extends APage { private BPageData data = new BPageData(); }
当你调用new BPage().getData().getId()时,结果会是//*[@id="id_1"],而不是预期的//*[@id="id_2"]——这就是你遇到的问题。
问题根源
核心原因是子类的data成员和父类的data是完全独立的两个变量,而且父类的getData()方法只会返回自己的APageData实例:
- 你在
BPage里定义了自己的BPageData data,但这只是子类新增的成员,并没有覆盖父类的data变量; - 当调用
getData()时,因为你没在BPage里重写这个方法,所以会调用父类APage的getData(),返回的自然是父类里初始化的APageData对象,它的getId()就会输出id_1。
如果是用了泛型但没写对,比如父类泛型声明了但没用到成员上,也会出现同样的问题:
// 错误的泛型用法 class APage<T extends APageData> { private APageData data = new APageData(); // 这里没使用泛型T,还是硬编码APageData public APageData getData() { return data; } } class BPage extends APage<BPageData> { private BPageData data = new BPageData(); }
这种情况下泛型相当于白声明了,父类的getData()依然返回APageData,和子类的data没关系。
正确的解决方式
要让BPage能返回自己的BPageData,得让父类用泛型约束数据类型,并且把成员变量和方法返回值都绑定到泛型上:
class APage<T extends APageData> { protected T data; // 通过构造方法传入具体的子类数据实例 public APage(T data) { this.data = data; } // 返回值是泛型T,子类继承后会自动对应具体类型 public T getData() { return data; } } class BPage extends APage<BPageData> { public BPage() { // 给父类传入BPageData实例 super(new BPageData()); } }
这样当你调用new BPage().getData().getId()时,就会返回//*[@id="id_2"]了——因为此时getData()返回的是BPageData实例,调用的是它重写后的getId()方法。
关于你的运行结果
你看到两次输出//*[@id="id_1"],说明两次调用的都是父类APageData的getId()方法,要么是直接调用了父类的getData(),要么是子类的泛型/成员变量没正确覆盖父类的逻辑,导致始终用的是父类的数据实例。
内容的提问来源于stack exchange,提问作者Alan Menken
相关产品推荐
相关产品推荐

