【发布时间】:2020-07-14 18:12:20
【问题描述】:
我对 java 中的泛型和继承有疑问。
我想从“createManager”方法中实例化一个“ObjectManager”类,该方法可以从给定类型创建实例。这个“ObjectManager”有一些实用方法(例如:“getDescription”)。
此方法允许我从一个类型实例化一个“ObjectManager”,然后获取例如它的描述(此处为哈希)。
如果输入类型可分配给类型“Foo”,我还想为“FooManager”专门化“ObjectManager”,以便我可以覆盖“getDescription”方法。因此,我在“createManager”方法中测试输入的类型,以了解我是创建“ObjectManager”还是“FooManager”。
代码有效,但我不知道对应于“new FooManager(type)”的输出的通用类型。在我看来,对于 Eclipse 快速修复,类型应该是
Bound mismatch:类型 T 不是 FooManager
类型的有界参数的有效替代品
我的代码:
import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
public class GenericBug {
private GenericBug() {}
public static void main(String[] args) {
ObjectManager<Foo> objectManager1 = createManager(Foo.class);
System.out.println(objectManager1.getDescription());
ObjectManager<Object> objectManager2 = createManager(Object.class);
System.out.println(objectManager2.getDescription());
}
private static <T> ObjectManager<T> createManager(Class<T> type) {
if(Foo.class.isAssignableFrom(type))
return new FooManager<T>(type); //Error: Bound mismatch
return new ObjectManager<T>(type);
}
}
class ObjectManager<T>{
public T val;
public ObjectManager(Class<T> type) {
try {
val = type.getConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
public String getDescription() {
return "Hash: " + Objects.hash(val);
}
}
class FooManager<T extends Foo> extends ObjectManager<T>{
public FooManager(Class<T> type) {
super(type);
}
@Override
public String getDescription() {
return super.getDescription() + " value: " + val.getVal();
}
}
class Foo{
private double val = Math.random();
public Foo() {}
public double getVal() {
return val;
}
}
所以我的问题是:为什么会出现这个错误?如何在没有警告的情况下修复它?而且,作为奖励,为什么 Eclipse 提供了一个无法编译的解决方案?这是 Eclipse 错误吗?
提前感谢您的回答。
【问题讨论】:
-
您会收到此错误,因为
FooManager需要一个扩展Foo的类型,但createFooManager()中的T并没有“明确地”这样做,检查并不重要对于isAssignableFrom(),从编译器的角度来看,createFooManager()中的T仅扩展了Object,因此会出现错误。 -
我学到的关于 OO 的第一件事就是,当你发现自己使用
if语句来确定要使用哪个对象时,你就知道自己做错了。实例化。 -
您的应用程序是否只会创建
Foo和FooManager类型的实例?Bar类型的对象在语义上是Foos呢?那你不是需要一个对应的BarManager吗?然后,您必须在if检查中添加另一个分支。对?对我来说,将一个名为createFooManager()的方法投入使用以创建 语义 没有 的东西有点粗略。 >Foo- 关于他们。 -
首先,感谢您的回复。我想我理解了这个警告,这是最初的目标。关于方法“createFooManager”的名称,这是我在创建此示例时的错误……正如 Eugene 建议的那样,它应该被称为“createManager”。我会在我的例子中更正它。
-
我还指出,我做了这个极简主义的例子来说明我的问题。实际上,它与 RMI 上下文中的任务委派问题有关。在我的情况下,我不仅有一个 if,而是一个根据类类型注册管理器的映射,并且我的解决方案的用户可以动态添加其他管理器。所以我需要一种独特的方法来创建它。在我看来,这会使重复数据删除器提案无效,但他无法从我的示例中推断出来......我的错......请注意:有时我也可以在不使用此方法的情况下创建管理器,如果我知道我想要哪个管理器使用。
标签: java generics inheritance