我该怎么做这个java通用演员?

时间:2008-11-24 13:19:12

标签: java

如何制作这个java通用演员?

public interface IField {

}


class Field implements IField { // package private class

}

public class Form {
  private List<Field> fields;


  public List<IField> getFields() {
    return this.fields;

  }

}

return语句抛出一个编译器错误(我知道原因 - 我阅读了泛型教程),但编写这样的代码会非常方便。

如果我将“fields”声明为List,则需要在Form类的其他方法中对Field使用大量的强制转换。

我可以强制该死的编译器弯曲它的规则并编译该返回语句吗?

提前致谢。

5 个答案:

答案 0 :(得分:17)

更好的解决方案,IMO,是更改方法的签名以使用有界通配符:

public List<? extends IField> getFields()

这会让调用者将列表中的任何内容视为IField,但它不会让调用者在列表中添加任何内容(没有强制转换或警告),因为他们不知道“真实的“列表类型是。

答案 1 :(得分:12)

碰巧,你可以,因为Java泛型只是嫁接,而不是类型系统的一部分。

你可以做到

return (List<IField>)(Object)this.fields;

因为所有List<T>个对象都是相同的基础类型。

请记住,这允许任何人在您的列表中放置任何实现IField的类型,因此如果您的收藏不是只读的,则可能会遇到困难。

答案 2 :(得分:5)

不要这样做。

List<Field>不是List<IField>。您可以尝试强制编译器接受(我认为这是不可能的,我希望它不可能),但这会让您陷入困境。编译器将允许用户将从IField派生的AnotherField引入到给定的List中,从而破坏不变量,并打破泛型提供的类型安全性。稍后使用List<Field>将会中断,因为奇怪元素的提取将无法将隐式强制转换为Field,而您不会期望它发生。

如果您确实需要返回List<IField>而不是List<Field>,那么我建议您生成一个填充了相同元素的新列表。如果您可以修改界面,请转到Jon Skeets解决方案。

答案 3 :(得分:2)

如果调用者不需要能够修改列表:

return Collections.<IField>unmodifiableList(this.fields);

答案 4 :(得分:0)

阳光是对的,你可以施展它。

另一个解决方法是仔细检查您确实需要List<Field>,或者是否可以将内部fields变量更改为List<IField>

只要您只使用IField接口上列表内容的方法,您就应该能够进行明确的交换。