Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在返回集合的接口中使用Java泛型。最佳实践?陷阱?_Java_Generics_Oop_Collections_Interface - Fatal编程技术网

在返回集合的接口中使用Java泛型。最佳实践?陷阱?

在返回集合的接口中使用Java泛型。最佳实践?陷阱?,java,generics,oop,collections,interface,Java,Generics,Oop,Collections,Interface,我今天遇到了一些我觉得有问题的代码。下面是一个简化的示例(不现实) 然后有这样一个实现者: public GroceryList implements IListable { private ArrayList<GroceryItem> groceries; public GroceryList() { this.groceries = new ArrayList<GroceryItem>(); } public Arr

我今天遇到了一些我觉得有问题的代码。下面是一个简化的示例(不现实)

然后有这样一个实现者:

public GroceryList implements IListable {
    private ArrayList<GroceryItem> groceries;

    public GroceryList() {
        this.groceries = new ArrayList<GroceryItem>();
    }

    public ArrayList<GroceryItem> getFirstNThings(int n) {
        ArrayList<GroceryItem> firstNThings = new ArrayList<GroceryItem>();
        for (int i=0; i < n; i++) {
            firstNThings.add(this.groceries.get(i));
        }
        return firstNThings
     }

     public ArrayList<GroceryItem> getLastNThings(int n) {
         ArrayList<GroceryItem> lastNThings = new ArrayList<GroceryItem>();
         for (int i=this.groceries.size(); i < this.groceries.size()-n; i--) {
           lastNThings.add(this.groceries.get(i-1);
         }
         return lastNThings;
      }
}
公共杂货店列表表{ 私营ArrayList杂货店; 公共杂货店(){ this.groceries=新的ArrayList(); } 公共阵列列表GetFirstInthings(int n){ ArrayList FirstInthings=新的ArrayList(); 对于(int i=0;i 忽略您可能在其中发现的任何实现问题(我也发现了一些)。我的意思是,接口没有为ArrayList(即ArrayList)使用任何泛型类型参数,但接口方法的实现者会使用(即ArrayList)。其他实现者可能会返回带有任何其他类型参数的ArrayList,不是吗


所以我的问题是:这是一个问题吗?我应该重构任何东西吗?值得吗?优点是什么?如果在接口中定义了一个返回类型为原始类型的方法,但该方法的实际实现者返回各种参数化类型,我会遇到什么样的问题?

如果IListable的两个方法都始终返回对于相同类型,请改用此选项:

public interface IListable<T> {
  //returns first n items from list
  public ArrayList<T> getFirstNThings(int n);

  //returns last n items from list
  public ArrayList<T> getLastNThings(int n);
}
公共接口表{
//返回列表中的前n项
公共ArrayList getFirstNThings(int n);
//返回列表中最后n个项目
公共数组列表getLastInthings(int n);
}
如果这不是一个选项,试着用?来代替。虽然基本上是一样的,但它避免了难看的警告

public interface IListable {
  //returns first n items from list
  public ArrayList<?> getFirstNThings(int n);

  //returns last n items from list
  public ArrayList<?> getLastNThings(int n);
}
公共接口表{
//返回列表中的前n项
公共ArrayList getFirstNThings(int n);
//返回列表中最后n个项目
公共数组列表getLastInthings(int n);
}

一般来说,在实现中使用比在超级类型或接口中更具体的返回类型不是问题。如果处理IListable,则需要处理返回列表中的任何对象类型。如果处理GroceryList,则只需要GroceryItems。这不仅适用于返回类型的Generic类型参数,而且还适用于因此,如果接口指定了
List get()
,则可以将其实现为
ArrayList get()

最佳实践是永远不要在打开的代码中返回带有纯通配符的
列表
,就像不应该返回
null
一样

Java中的通配符泛型会给所有使用您的代码的程序员带来污染。您可以在关闭代码中解决本地问题


通常,您将避免返回协方差和逆变换通配符,如
list。此方法还允许您将GroceryList制作成一个完全通用类型的列表,以便以后重用。除了Sfussengenger所说的,我还更喜欢返回
list
的方法,而不是
ArrayList
public interface IListable {
  //returns first n items from list
  public ArrayList<?> getFirstNThings(int n);

  //returns last n items from list
  public ArrayList<?> getLastNThings(int n);
}