java中的简单通用列表

and*_*bd1 7 java generics

为什么java泛型如此棘手?我以为我终于理解了,但是eclipse在下面的somOtherMethod中使用下面的getOuterList方法给出了一个错误.

protected List<?> getOuterList() {
  // blah blah
}

protected List<? extends Object> getOuterList() {
  // blah blah
}

protected void someOtherMethod() {
  ...
  getOuterList().add((MyObject)myObject);  //compile error
  ...
}
Run Code Online (Sandbox Code Playgroud)

更新:好的 - 所以我现在理解错误.我对什么List<?>List<? extends SomeObject>真正意味着缺乏了解.在前一种情况下,我认为这意味着可以包含任何内容的列表.在后一种情况下,我假设它是一组扩展SomeObject的对象的列表.正确表达我的理解就是List<Object>List<SomeObject>(没有扩展).我认为extend帮助我解决了他们没有解决的问题.所以这就是我真正的问题所在:

public interface DogKennel {
  public List<Dog> getDogs();
}

public class GreyHoundKennel implements DogKennel {

  protected List<GreyHound> greyHounds;

  public List<GreyHound> getGreyHounds() {
    return this.greyHounds;
  }

  public List<Dog> getDogs() {
    // Is there no way to handle this with generics
    // w/out creating a new List?
    return getGreyHounds(); //compiler error
  }

}
Run Code Online (Sandbox Code Playgroud)

Bob*_*oss 1

您被 Java 泛型在类型参数上不是多态这一事实绊倒了。

讨论您的代码片段,让我们将示例分开:

protected List<GreyHound> greyHounds; // List<GreyHound> is fine

/** This method returns a lovely List of GreyHounds */
public List<GreyHound> getGreyHounds() { 
  return this.greyHounds;
}

/** Here is the problem.  A List<GreyHound> is not a List<Dog> */
public List<Dog> getDogs() {
  return getGreyHounds(); //compiler error
}
Run Code Online (Sandbox Code Playgroud)

所以你原来的评论是正确的。这两个列表肯定是不同的,它们之间没有继承关系。因此,我建议您研究这两个选项:

  1. 尝试按照您在评论中的建议返回一个新列表。例如,return new ArrayList<Dog>(this.greyHounds);

  2. 您真的需要保留特定品种狗的清单吗?也许您应该将数据成员定义为List<Dog>添加特定 GreyHounds 的数据成员。即,protected List<Dog> greyHoundsOnly;您可以通过对象的外部接口来管理狗舍中允许哪些狗。

除非你有充分的理由保留特定类型的列表,否则我会认真考虑选项 2。

编辑:充实我上面建议的选项:

选项 1:返回一个新列表。优点:简单、直接,您会得到一个类型化的列表,并且消除了线程安全问题(不会向世界公开内部引用)。缺点:似乎是性能成本。

// Original code starts here.
public interface DogKennel {
  public List<Dog> getDogs();
}

public class GreyHoundKennel implements DogKennel {

  protected List<GreyHound> greyHounds;

  public List<GreyHound> getGreyHounds() {
    return this.greyHounds;
  }
// Original code ends here

  public List<Dog> getDogs() {
    // This line eliminates the thread safety issue in returning 
    // an internal reference.  It does use additional memory + cost
    // CPU time required to copy the elements.  Unless this list is
    // very large, it will be hard to notice this cost.
    return new ArrayList<Dog>(this.greyHounds);
  }

}
Run Code Online (Sandbox Code Playgroud)

选项 2:使用不同的数据表示形式。优点:更好地处理多态性,返回原始目标的通用列表。缺点:它的架构略有不同,可能不适合原始任务。

public abstract class DogKennel {
  protected List<Dog> dogs = new ArrayList<Dog>();
}

public class GreyHoundKennel extends DogKennel {

  // Force an interface that only allows what I want to allow
  public void addDog(GreyHound greyHound) { dogs.add(greyHound); }

  public List<Dog> getDogs() {
    // Greatly reduces risk of side-effecting and thread safety issues
    // Plus, you get the generic list that you were hoping for
    return Collections.unmodifiableList(this.dogs);
  }

}
Run Code Online (Sandbox Code Playgroud)