4

私は通常、Java を初めて使用する C# 開発者であり、Generics を使用していくつかのコードをセットアップしようとしています。私のデモコードは次のようになります。

// 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# でさえ機能しません。これも 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 Generics は、タイプ セーフの実現を支援したいと考えています。

<T extends MyUIControl>パラレルを使用させてください:あなたが書いたもので、ある時点MyButtonでそれと一緒に s を使用し、別の場所で s を使用すると仮定しましょうMyPanel- これは安全にキャストできません。

コンパイラは、コード内でそのような状況を認識しました。

于 2012-05-01T23:47:34.903 に答える