14

私は現在、AP Java で高校生を指導していて、彼女から「ダブル キャスティング」について質問されました。私はこれまでこの用語について聞いたことがありませんでしたが、どうやら彼女の先生は、彼女が次の決勝戦でそれを知っていることを期待しているようです.

彼女の先生が提供した例は、整数を文字列にキャストしたい場合、コンパイラ エラーが発生しないように次のことを行う必要があるというものでした。

Integer i = new Integer(5);
String s = (String)(Object) i;

問題は、これを実生活でいつやりたいかということです。

教師は、実行時エラーになる例のみを提供しました。また、これに用語があることを本当に知りませんでしたが、2 つの型に互換性がない場合にのみエラーが発生するため、これを行うのは悪い考えのように思えます。

ありがとう!

4

10 に答える 10

8

「二重キャスト」は確かに一般的な用語ではなく、参照のいかなる種類のキャストにもあまり見えないはずですが、何が起こるかを知っておく必要があります (a ClassCastException)。

完全を期すために、CCE にならないケースがいくつかあります。

  • 値が実際にnull.
  • プリミティブに関するもの。(えー、Objectto Integer[unboxing]intまたはintto [lossy] byteto [positive] char)
  • ジェネリック型引数を変更します。List<String>へ。Object_List<Integer>
于 2013-01-21T03:19:55.653 に答える
7

ええ、私はそれが問題ではないと確信しています。二重キャストが必要になる理由はありません - 安全でないキャストに関するコンパイル警告を取り除く可能性があります (その場合、おそらく間違っています) が、それ以外の場合は正しくありません。

つまり、自動toString呼び出し egprintln("" + i)がありますが、それでも最初にオブジェクトにキャストする必要はありません...

編集:トムの答えを読んだ後、私は突然この答えについて確信が持てなくなりました-プリミティブと(特に)ジェネリックは実際にこれを使用できます。私は今のところ何もテストする能力がありませんが、この回答を読んでいる人は誰でも間違いなく彼を見てください(そしておそらくそれを支持してください)。

ただし、これを行う正当な理由がない (または少なくとも非常に少ないか、またはその中間にある) という行に固執するつもりであり、提供された例は確かにそれとは何の関係もありません。

于 2013-01-21T02:56:45.110 に答える
0

確かに、これはコンパイラ エラーを回避するだけですが、実行時エラーは必ず発生します。また、2 つのクラスが継承階層にある場合、基本クラスにダウンキャストして再度アップキャストする必要はありません。

上記の質問でも、オブジェクトを変換するための API メソッドが最終的に必要になります。

于 2013-01-21T02:56:41.473 に答える
0

実際の使用例は次のとおりです。

static class Y extends X<Date> {
//some code
}

List<Y> n = new ArrayList<>();

someMethod((List<X<Date>>)(List<?>) n);

どこ

void someMethod(List<X<Date>>){
//some code
}
于 2018-02-16T14:29:43.523 に答える
0

はい、消去されたジェネリックと型トークンの共通部分を処理する必要がある場合。

コンパイル時と実行時の両方でタイプ セーフなジェネリック関数が必要だとします。したがって、型トークンで宣言します。

public static <T> T getT(
    ExampleDataSource exampleDataSource,
    String key,
    Class<T> typeToken) {

    // code goes here...
}

これは、データ ソースから非ジェネリック型のみを取得しようとする限り、うまく機能します。例えば:

String string = getT(source, "some-string", String.class);
int integer = getT(source, "some-integer", Integer.class);
DateTime dateTime = getT(source, "some-datetime", DateTime.class);

List<String>しかし、データ ソースからデータを取得したい場合はどうなるでしょうか? まあ、その構文はかなり醜いダブルキャストです。また、キャストにもかかわらず、実行時に型トークンに存在しないため、消去された型をデータソースが独自に把握できる必要があります。

List<String> listOfString = getT(
    source,
    "some-list-of-strings",
    (Class<List<String>>) (Class) List.class
);

Java がList.class(架空の) 型への 1 つのステップでの直接のキャストを許可しない理由Class<List<String>>は、私にはわかりませんでした。将来のある時点で、Java がジェネリック型を具体化することを願っています。次にList<String>.class、有効な型トークンになり、キャストは必要ありません。生から偽のジェネリックへの奇妙な二重キャストはなおさらです。

于 2021-01-29T16:54:54.817 に答える
-1

たぶん、この質問は論理ですか?つまり、何かを計算してオブジェクトを返すメソッドと、結果を文字列にキャストするメソッドの使用法があります。一般に、このメソッドは数回オーバーライドできます。このような機能は、Java 1.5 より前に使用されていました。 calss (ジェネリックなし) と各メソッドの戻り値は Object です。これは、子がいくつかあり、それぞれが独自の型を返すことができるためです。わかりませんが、答えになる可能性があり、このように二重キャストします

public class Main {
    public static void main(String[] args) {

        AbstractToDO abstractToDO2 = new SomeToDoTwo();
        String result2 = (String) abstractToDO2.toDo(); // here is second, all is good

        System.out.println(result2);

        AbstractToDO abstractToDO1 = new SomeToDoOne();
        String result1 = (String) abstractToDO1.toDo(); // here is second, Runtime error

        System.out.println(result1);

    }

    Object onePlusOne(){

        return 1+1 +" ";
    }
}

interface AbstractToDO{
     Object toDo();
}

class SomeToDoOne implements AbstractToDO{
    @Override
    public Object toDo() {
        return (Object)(1+1); // here is first casting, // we can use without (Object) casting
    }
}class SomeToDoTwo implements AbstractToDO{
    @Override
    public Object toDo() {
        return (Object)"1+1"; // here is first casting, // we can use without (Object) casting
    }
}
于 2013-01-21T03:25:37.943 に答える