【问题标题】:Casting objects in list using generics使用泛型在列表中投射对象
【发布时间】:2012-03-04 12:16:30
【问题描述】:

我在使用泛型和带有接口的列表时遇到问题。

我有一个Comment接口,它由CommentNews类扩展。

评论:

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();
}

评论新闻:

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 方法,类转换实际上并没有转换列表中的每个对象。我无法更改方法签名,因为这会与接口产生名称冲突。

有没有办法使用泛型进行强制转换?我想避免遍历列表并手动转换每个对象。

更新: 如果我将评论界面更改为如果我将界面更改为

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

和 CommentNews 类

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

它应该是类型安全的,但这会导致接口和类之间的名称冲突。

【问题讨论】:

  • 每个对象的演员表会做什么?演员表不会改变任何对象。进行强制转换唯一可能发生的事情是 ClassCastException。

标签: java list generics interface casting


【解决方案1】:

从根本上说,您的界面不是类型安全的。没有什么可以阻止某人做这样的事情:

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

真的要允许吗?

可以有一个列表包装器,它在被访问时执行强制转换(而不是预先),但最好更改接口。

编辑:如果您希望任何类型的评论仅包含相同类型的子 cmets,您可能希望使您的 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();
}

(如果您愿意,您仍然可以使用通配符,但您可能不需要,这会使事情复杂化。)

【讨论】:

  • @olivervaga:你的意思是问题:) 但不清楚为什么你希望CommentNews 对接口有不同的方法签名。它必须能够处理对带有任何评论的 setComments 的调用,确定吗?如果没有,听起来您可能想要一个递归的通用定义。将编辑我的答案。
  • 递归泛型定义是一个很好的提示,但我现在发现我的问题源于我正在使用的 REST 客户端。尽管如此,我还是会接受这个答案,因为它仍然适用……有点。
猜你喜欢
  • 1970-01-01
  • 2020-06-02
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-02
相关资源
最近更新 更多