web-dev-qa-db-ja.com

Java ForEachステートメントの要素をキャストします

ステートメント自体の各ステートメントのaから取得した要素をキャストすることは可能ですか(またはお勧めします)?リスト内の各要素のタイプが<SubType>になることは知っています。

I.E。:

List<BaseType> list = DAO.getList();  
for(<SubType> element : list){ 
    // Cannot convert from element type <BaseType> to <SubType>
    ...
}

のではなく:

List <BaseType> list = DAO.getList();
for(<BaseType> el : list){
    <SubType> element = (<SubType>)el;
    ...
}
18
Carl Summers

本当に各エントリがサブタイプになることを知っていますか? DAOは単にList<BaseType>コントラクトを実行する必要があり、サブクラスを想定している場合は、どこかで何かがおかしいと思います。私はおそらく、DAOへのインターフェースを正しくすることにもっと集中し、契約上、必要なものを返すようにします。

18
Brian Agnew

他の人が述べたすべての理由のために、あなたはこれをするべきではありません。ただし、インターフェイスを変更できない場合は、次のことが可能です。

for (BaseType element : list) {
    SubType subType = (SubType)element;
    ...
}

私の知る限り、これがこれを実行し、真に型安全性を維持する唯一の方法です。つまり、問題を検出するために型消去に依存しないでください。これは、ずっと後になるまで必ずしも実行されるとは限りません。

これはまさにあなたが探していたものではないことを私は理解していますが、それは鋳造を処理します。

15
aperkins

実際、次のように、キャストとforループを組み合わせることができます。

List<BaseType> list = DAO.getList();  
for (SubType subType : ((List<SubType>) list)){ 
    ...
}

または、次の少しクリーンなパターンを使用できます。

List<SubType> list = (List<SubType>) DAO.getList();  
for (SubType subType : list){ 
    ...
}

Javaコンパイラから、抑制しない限り、チェックされていないキャスト警告が表示されます。最初のフォームの効果は、ループ内の各要素のキャストと実質的に同じです。2番目のフォームも適用されます。リストへの新しい追加はSubTypeに準拠する必要があります。

配列には異なる実行時型があるため、これは配列では機能しないことに注意してください。つまり、BaseType []をSubType []に​​キャストすることはできません。次のように、ArraysAPIを使用してこれを回避できます。

BaseType[] array = DAO.getArray();
for (SubType subType : Arrays.<SubType>asList(array)) {
    ...
}
11
Peter Centgraf

Googleコレクションに偏っていない場合は、transformメソッドでリストをラップできます。あなたの場合、それは非常に効率的で完全に準拠しています。ブライアンが提案したように、私はそれをラッパーメソッドとして置きます。

public List< SubType > fromDao ( )
{
    // Put a comment for maintainer

    // Lists from DAO always contain SubTypes
    return
        Lists.transform(
            DAO.getList( ),
            new Function< BaseType, SubType >( )
            {
                public SubType apply ( final BaseType from )
                {
                    return (SybType) from;
                }
            };
}

はい、可能です!しかし、神は禁じられています、なぜですか?私のキャリアの初期の試みはそれを行い、私は学びました。インターフェイスへのプログラミングには常に利点があります。サブタイプだけが必要なメソッド/機能を持っている場合の処理​​について、ジュニア開発者から常に質問があります。

メソッドbark()を持つDogサブタイプを持つAnimalクラスを言います。彼らはbark()機能を望んでいます。実際の課題は、bark()ではなく動物のspeak()の動物コミュニケーションの動作が必要なことです。したがって、新しいCatサブクラスはmeow()を必要としません。それでは、これについてはどうでしょうか。-私の犬はパックを形成しますが、猫はそうではありません。 Answer pack()の動作は、1匹の犬が所有しているわけではありません。パックは別の側面です。すべてのオブジェクトにパックを渡し、オブジェクトにパックに参加するように依頼します。 (ビジターパターン/アダプターパターン)。私のWolfクラスは同じ動作を使用できます。

私はこれについて厳格ですか、それが1回だけの場合は問題ありません。答えがわからない場合は、インターフェース契約で作業することで安全にプレイする方がよいでしょう。

0
questzen