2012-05-01 21 views
4

私は通常、C#の開発者です.Javaには新しく、ジェネリックスを使用していくつかのコードをセットアップしようとしています。XはTと一致する必要がありますが、XをTに変換できませんか?

// 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

既知の固定型を返す場合にジェネリックを使用する理由は何ですか? –

+0

@Oli実際の実装はより複雑で多くの型のうちの1つを返すことができるため(実際にはリフレクションによってインスタンス化されるクラスが必要です) –

答えて

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 
} 

それもキャストで、これは非常に悪いことだと明示的に提供さていない任意の型で呼び出されたときに簡単に実行時例外が発生することができ、それを注意することも重要です。これは、一般化された状況でなければならないものにおいて、非常に特定のタイプを特定することによってジェネリックスの概念に反するものです。

1

Java Genericsは、タイプセーフティを実現するために役立ちます。

私は並列に使用してみましょう:私たちはあなたが<T extends MyUIControl>を書いて、ある時点で、あなたはそれにMyButton sおよびどこか他のMyPanelの使用を前提としてみましょう - 安全にキャストすることはできません。

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

関連する問題