-1

None of this codes will compile. I would like to understand why and how I could solve this. This is simplified and the method-signature is given by a framework. I would like to offer a default that can be overwritten with subtypes of 'TableItem'.

Error at add:

public <TI extends TableItem> ArrayList<TI> getTable() {
  ArrayList<TI> list = new ArrayList<TI>();
  TableItem item = new TableItem();
  list.add(item);
  return list;
}

Error at return:

public <TI extends TableItem> ArrayList<TI> getTable() {
  ArrayList<TableItem> list = new ArrayList<TableItem>();
  TableItem item = new TableItem();
  list.add(item);
  return list;
}

Edit:
This helped me a bit: Difference between <? super T> and <? extends T> in Java

Community
  • 1
  • 1
Sammy
  • 1,026
  • 1
  • 13
  • 26
  • 2
    What do you mean by "breaks"? If you mean there's a compile-time error, please include that in the question. – Jon Skeet Dec 09 '14 at 14:39
  • It also seems that you swapped the error messages and related code. – Thomas Weller Dec 09 '14 at 14:45
  • @ Jon Skeet: I meant (like I wrote in the first sentence, that It will not compile so therefore the compiler will give an error at that position. – Sammy Dec 09 '14 at 14:46
  • @Thomas: You are right, my redesign failed :-) ....corrected – Sammy Dec 09 '14 at 14:47
  • 1
    Whoever voted down, would you (or anyone else) please tell me WHY the examples will not compile? As you voted, it seems, that you know why and that it is simple. – Sammy Dec 09 '14 at 14:58

2 Answers2

2

Your problem seems to be with generics. Adding to a generics list ...

I usually reason about this stuff, by remembering a mnemonic I learned in Effective Java:

PECS: producer-extends, consumer super.

So this means the following in your case: Since the returned list in the method getTable() is a consumer(i.e. you are adding to this list), then u should declare it as:

public <TI extends TableItem> ArrayList<? super TableItem> getTable() {  
          ArrayList<TableItem> list = new  ArrayList<TableItem>();
          TableItem item = new TableItem();
          list.add(item);
          return list;
        }
javaHunter
  • 1,067
  • 6
  • 9
  • This looks good. It seems, that I can remove ``. I will read about `super` at generics. Thx! – Sammy Dec 09 '14 at 15:05
  • This may explain this: http://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java – Sammy Dec 09 '14 at 15:12
  • Declaring a return type containing a wild card is not really useful as it imposes restrictions to the caller with no advantages for the method’s implementation. Just return `ArrayList` – Holger Dec 12 '14 at 16:48
0

This is impossible to do it the way you are doing it. If you really want the user to be able to define a class, there are two ways to do it. One would be supplying the class:

public <TI extends TableItem> ArrayList<TI> getTable() {
    return getTable(TableItem.class);
}
public <TI extends TableItem> ArrayList<TI> getTable(Class<TI> tiClass) {
    ArrayList<TI> list = new ArrayList<TI>();
    TableItem item = tiClass.getConstructor().newInstance(); //remember to catch exceptions here!
    list.add(item);
    return list;
}

or another one would be the user providing the TableItem object:

public <TI extends TableItem> ArrayList<TI> getTable() {
    return getTable(new TableItem());
}
public <TI extends TableItem> ArrayList<TI> getTable(TI tiObject) {
    ArrayList<TI> list = new ArrayList<TI>();
    list.add(tiObject);
    return list;
}

Are you sure that you want your program to be structured this way though? The function itself seems redundant (you are just creating a list), it can be shortened (Arrays.asList(object)) and the list you return is modifiable.

molenzwiebel
  • 740
  • 4
  • 20
  • I use a framework, which will call `getTableXY()` where XY is a name of an attribute. I can't change this. I simplified the methodname in my post. I just want implement a default for this method while beeing able to extend the `TableItem`'s in subclasses. – Sammy Dec 09 '14 at 14:55