4

我通常是 C# 开发人员,刚接触 Java,我正在尝试使用泛型设置一些代码。我的演示代码如下所示:

// Main.java
public static void main(String[] args) {
    MyBase my = getMeStuff();
    System.out.println(my.getSomething());
}

private static <T extends MyBase> T getMeStuff(){
     return new MyDerived(123);
}

// MyBase/MyDerived.java
public class MyBase {
    private final int something;

    protected MyBase(int something) { this.something = something; }

    public int getSomething() { return something; }
}

public class MyDerived extends MyBase {
    public MyDerived(int something) { super(something); }
}

这无法编译:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
Type mismatch: cannot convert from x.MyDerived to T

at x.Main.getMeStuff(Main.java:14)
at x.Main.main(Main.java:9)

如前所述,我通常是 C# 开发人员,因此代码乍一看还不错。我可以通过更改 getMeStuff 以向 (T) 添加强制转换来“解决”这个错误,但是这种强制转换真的有必要吗?有点味道,好像忘记了什么?

4

2 回答 2

5

问题是返回类型可以是从 MyBase 派生的任何内容,并且您已专门将其键入到 MyDerived,这在没有强制转换的情况下甚至在 C# 中都不起作用。调用者可以指定 SomeOtherDerived,它也派生自 MyBase,但与 MyDerived 无关。

public class MyBase{}
public class MyDerived extends MyBase{}
public class SomeOtherDerived extends MyBase{}
public static <T extends MyBase> T getAnything(){ return (T)new MyDerived(); }

public static void main(String[] args) {
    SomeOtherDerived instance = getAnything(); //This is legal and bad
}

同样重要的是要注意,即使使用强制转换,这也是一件非常糟糕的事情,并且在使用任何未显式提供的类型调用时很容易导致运行时异常。这也违反了泛型的概念,因为它在应该是一般化的情况下确定了非常具体的类型。

于 2012-05-01T23:07:42.050 回答
1

Java 泛型希望帮助您实现类型安全。

让我用一个平行线:让我们假设你写了<T extends MyUIControl>,并且在某一时刻你使用MyButtons 和它在其他地方使用MyPanels - 这不能安全地转换。

编译器在代码中识别出这种情况。

于 2012-05-01T23:47:34.903 回答