2012-03-04 5 views
0

ジェネリックとリストをインターフェイスで使用する際に問題があります。ジェネリックを使用してリスト内のオブジェクトをキャストする

私はCommentNewsクラスによって拡張されたインタフェースCommentを持っています。

コメント:

public interface Comment { 

    public static final String COMMENT_NEWS_PATH = "/comment/news"; 
    public static final String COMMENT_EVENT_PATH = "/comment/event"; 
    public static final String COMMENT_GROUP_PATH = "/comment/group"; 

    public User getUser(); 

    public void setUser(User user); 

    public String getText(); 

    public void setText(String text); 

    public Date getModified(); 

    public void setModified(Date modified); 

    public void setCommentsList(List<?> commentsList); 

    public <T extends Comment> List<T> getCommentsList(); 
} 

CommentNews:

public class CommentNews implements Comment { 

    private Integer id; 
    private User user; 
    private News news; 
    private String text; 
    private List<CommentNews> commentsList; 

    public CommentNews() {} 

    // Methods snipped for brevity 

    public List<CommentNews> getCommentsList() { 
     return commentsList; 

    } 

    public void setCommentsList(List<?> commentsList) { 
     this.commentsList = (List<CommentNews>) commentsList; 

    } 
} 

問題がsetCommentsList方法である、クラスキャストは、実際には、リスト内の各オブジェクトをキャストしません。私はインターフェイスと名前の衝突を生成するので、メソッドのシグネチャを変更することはできません。

ジェネリックを使用してキャスティングを行う方法はありますか?私はリストを反復することを控え、各オブジェクトを手動でキャストしたいと思います。

UPDATE: 私はコメントインタフェースを変更した場合、私は

public void setCommentsList(List<CommentNews> commentsList) { 
     this.commentsList = commentsList; 
    } 

public <T extends Comment>void setCommentsList(List<T> commentsList); 

とCommentNewsクラスにインターフェースを変更する場合は、タイプセーフでなければなりませんが、これは、その結果インタフェースとクラスの間の名前の衝突。

+0

すべてのオブジェクトのキャストは何をしますか?キャストはオブジェクトに対して何も変更しません。キャストを行うことによって発生する可能性があるのは、ClassCastExceptionです。 –

答えて

3

基本的に、あなたのインターフェイスはタイプセーフではありません。このような何かをやってから誰かを停止するには何もありません:

Comment comment = ...; // Wherever 
List<Integer> numbers = new List<Integer>(); 
numbers.add(10); 
comment.setCommentsList(numbers); 

あなたはが本当にがそれを許可しますか?

には、アクセスするたびにキャストを実行するリストラッパーがありますが、インターフェイスを変更する方がよいでしょう。

EDIT:あなたは、同じ種類のサブコメントを保持するだけにコメントのいずれかの種類をしたい場合、あなたはおそらくあなたのCommentインタフェースは、一般的なようにしたい、このように:

public interface Comment<T extends Comment<T>> { 

    // Note: no public modifier; it's allowed by the spec but discouraged 
    void setCommentList(List<T> comments); 
    List<T> getCommentList(); 
} 

(あなたはまだ、ワイルドカードを使用することができますもしあなたが望むなら、必要はないかもしれませんが、それは事を複雑にします。)

+0

私の更新された答えを見てください:) – j0ntech

+0

@olivervaga:あなたは質問:)を意味しますが、なぜCommentNewsにインターフェースとは別のメソッドシグネチャが必要なのかは分かりません。どんな種類のコメントでもsetCommentsへの呼び出しを処理できなければなりません。そうでない場合は、再帰的な一般的な定義が必要なように思えます。私の答えを編集します。 –

+0

再帰的な一般的な定義は良いヒントでしたが、私は問題がRESTクライアントに由来していることを発見しました。それでも、私はそれがまだ適用されるように答えを受け入れるつもりです。 – j0ntech