Java通用拼图

时间:2015-08-27 14:22:38

标签: java generics refactoring

我有Java类:

abstract class Parent {
    abstract void test(Object pObject, Map<String, Object> pData);
}

public class Test extends Parent {
    @Override
    void test(Object pObject, Map<String, Object> pData) {
    }
}

并希望将代码重构为:

abstract class Parent<T> {
    abstract void test(T pObject, Map<String, Object> pData);
}

public class Test extends Parent {
    @Override
    void test(Object pObject, Map<String, Object> pData) {
    }
}

Eclipse(4.4.2如果它的问题)告诉我Test类中的代码无效(编译时错误)并且正确的test()方法签名必须是:

@Override
void test(Object pObject, Map pData) {
}

我的问题是为什么!?

实际上,真实的故事有点长。我有很多孩子上课(比如测试)并且不想改变它们,而更喜欢使用泛型(即<T>类)来为父类的新孩子。在这两种情况下,test()方法的第二个参数必须为Map<String, Object>

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

  

我的问题是为什么!?

当您扩展{strong>原始版本的Parent时,该类中的所有通用信息都会被忽略。因此,您正在扩展Parent,如下所示:

abstract class Parent {
    abstract void test(Object pObject, Map pData);
}

为了保留 Map参数的类型参数,您只需指定您正在扩展Parent<Object>。现在这段代码编译得很好:

public class Test extends Parent<Object> {
    @Override
    void test(Object pObject, Map<String, Object> pData) {
    }
}

答案 1 :(得分:3)

在第一个例子中,Parent是一个普通的类,你以预期的方式对它进行了分类,一切都很好。

在第二个示例中,您没有扩展Parent<T>,而是扩展了通用的已擦除Parent,即使它们不涉及T,也会删除该类中的所有泛型。< / p>

public class Test extends Parent<Object> {
    @Override
    void test(Object pObject, Map<String, Object> pData) {
    }
}

答案 2 :(得分:2)

我看到达到你想要的唯一方法是保持Parent类不变,并引入另一个类,为你提供模板功能:

abstract class TemplatedParent<T> {
    abstract void test(T pObject, Map<String, Object> pData);
}

abstract class Parent extends TemplatedParent<Object> {}

这样您就可以保留旧代码,而需要模板功能的新代码必须直接扩展TemplatedParent