2009-03-11 9 views
6

引数としてObjectを取り込み、それを任意の型にキャストし、失敗した場合はnullを返すメソッドを実装したいと思います。ここで私がこれまで持っているものです。 Javaジェネリック

public static void main(String[] args) { 
    MyClass a, b; 
    a = Main.<MyClass>staticCast(new String("B")); 
} 

public static class MyClass { 
} 

public static <T> T staticCast(Object arg) { 
    try { 
     if (arg == null) return null; 
     T result = (T) arg; 
     return result; 
    } catch (Throwable e) { 
     return null; 
    } 
} 

残念ながら、クラスキャスト例外がスローされることはありません/ staticCast()関数の本体でキャッチ。 Javaコンパイラは、 MyClassであることを明示的に言っていますが、 String result = (String) arg;の行を持つ String staticCast(Object arg)という関数を生成しているようです。どんな助け?ありがとう。

+0

ところで、あなたはcatchinする必要がありますg ThrowableではなくClassCastExceptionのみ。 Throwableをキャッチすると深刻な問題が発生する可能性があります。 –

答えて

10

ジェネリック型情報は実行時に消去されるため、ジェネリック型にキャストするための標準的な方法は、Classオブジェクトである:

public static <T> T staticCast(Object arg, Class<T> clazz) { 
    if (arg == null) return null; 
    if (!clazz.isInstance(arg)) 
     return null; 
    T result = clazz.cast(arg); 
    return result; 
} 

次に、このようにそれを呼び出す:私は同意

a = Main.staticCast("B", MyClass.class); 
+0

はより直接的です。 –

+0

hmm、clazz?それはガラスのようなものですか? –

+0

isInstanceは、オブジェクトがclazzのインスタンスである場合にのみ動作し、clazzのサブクラスではありません。 isAssignableFromは、サブクラスでさえ、キャスト可能なものであれば動作します。 –

6

少なくともあなたはこのようには望んでいないことはできません。コンパイラがすべての情報を削除したので、キャスト内のObjectである(T)を巻き上げると、それが機能します。

問題は、後でMyClass =(String)オブジェクトを実行していることです。それは許可されていません。

コンパイラのチェックをバイパスし、実行時に失敗しました。

だから、あなたは何をしようとしているのですか?なぜあなたがこれをしたいのかを教えてくれたら、おそらくJavaのやり方を教えてくれるはずです。 C++のテンプレート用のJavaジェネリックを間違えないでください

public class Main 
{ 
    public static void main(String[] args) 
    { 
     String a; 
     MyClass b; 
     a = staticCast(new String("B"), String.class); 
     b = staticCast(new String("B"), MyClass.class); 
     System.out.println(a); 
    } 

    public static class MyClass 
    { 
    } 

    public static <T> T staticCast(Object arg, final Class clazz) 
    { 
     // edit - oops forgot to deal with null... 
     if(arg == null) 
     { 
      return (null); 
     } 

     // the call to Class.cast, as mmeyer did, might be better... probably is better... 
     if(arg.getClass() != clazz) 
     { 
      // Given your answer to Ben S... 
      return (null); 

      // throw new ClassCastException("cannot cast a " + arg.getClass() + " to a " + clazz); 
     } 

     return ((T)arg); 
    } 
} 
+0

私はTがキャスト内のオブジェクトだから分かります。私は引数を(T)にキャストする各Tのための別個のメソッドを必要とし、それが失敗した場合は例外がキャッチされ、スローされません。Paul Tomblin(以下のポスト)によると、それは起こらないだろう。 – Budric

+0

私が編集で提供したコードは、あなたがしたいことをしなければならない – TofuBeer

1

:あなたのコメントを考えると

次のようなものを試してみてください。だけで、すべてのジェネリック医薬品を使用していない各T.

のための1つの、異なるタイプの消去と呼ばれています1つのstaticCast方法ではないだろう、私はそれをこのように書くでしょうがあります:

public static void main(String[] args) { 
    MyClass a, b; 
    a = (MyClass)Main.staticCast(new String("B"), MyClass.class); 
} 

public static class MyClass { 
} 

public static staticCast(Object arg, Class class) { 
     if (arg != null && class.isAssignableFrom(arg)) 
      return arg; 
     return null; 
} 

それとも別から盗みます答え、ジェネリックを使用:

public static <T> T staticCast(Object arg, Class<T> class) { 
     if (arg != null && class.isAssignableFrom(arg)) 
     { 
      T result = class.cast(arg); 
      return result; 
     } 
     return null; 
} 
+0

CCEがRuntimeExceptionであり、catchブロックを必要としなかったことを忘れていました。 –

+0

Javaコンパイラが関数を生成しない理由を詳しく説明できます MyClass staticCast(Object arg);私が明示的にタイプTをラインに指定すると:a = Main。 staticCast(新しい文字列( "B"));私は明示的にそれに言った...私は考えた いくつかの読書へのリンクは素晴らしいだろう。 – Budric

+0

@Budric:http://java.sun.com/docs/books/tutorial/java/generics/erasure.htmlを試してください。また、[java] [generics]というタグ付きの質問を検索してください。周りにはかなり興味深いものがあります。 –

4

Class<T>.cast(Object obj)のような意味ですか?以下のような

何か:

Class.forName("YourClass").cast(obj); 

はかなりあなたが欲しいものを行う必要があります。

これはかなり臭いですが、おそらくデザインが悪いことの兆候であることに注意してください。

+0

ありがとうございます。問題は、失敗した場合にクラスキャスト例外がスローされることです。これはコード:(YourClass)オブジェクトと同じですが、そのコード行を使用するたびにチェックする必要があるエラーで例外がスローされます。 catch()メソッド内でその例外をキャッチして非表示にしたいと思います。 – Budric

+0

asSubclassまたはgetConstructor()。newInstance()。castを使用しますか? Class.isInstanceを使用する –

1

ベンとは、私は次の表記が好きです:

MyClass.class.cast(obj);