I ran into some code today that I found questionable. Here's a simplified example (not realistic).
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);
}
Then there's an implementor like so:
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;
      }
}
Ignore any implementation problems you may find in that (I found a few too). What I'm getting at is that the interface does not use any generic type parameter for ArrayList (i.e ArrayList<?>), but the implementor of the interface's method does (i.e. ArrayList<GroceryList>). Other implementors may return ArrayLists with any other type parameters, no?
So my questions: Is this a problem? Should I refactor anything? Is it worth it? What's the advantage? What kind of problems can I run into if I have a method defined in an interface whose return type is a raw type, but the actual implementors of the method return various parameterized types?
 
     
    