0

Not sure if my title is specific enough. Let me show you this:

class D {
      private List list;

  D() { 
      this.list = new LinkedList();
  }

   public LinkedList addHello() { 
      this.add("Hello");
      return this.list;
   }
}

I get it that since LinkedList implements List that I can use a LinkedList for a variable with a List type. Now I have the a method that returns "the list" after it added "Hello" to it.

I am a bit confused about it, but I guess I am right when I see two possible compile errors there right? At first, the List has no type, so how can it add a String? So it should be:

private ArrayList<String> list;

So the first compile error ist the add method, and the second WOULD be that the method addHello() returns the list which has the type List.

So my main question is: When you refer a List variable, or to say it more in general: if you have a interface, and you use it as a variable and then you refer to a class that has implemented the interface ( this.list = new LinkedList(); ), It does not mean that the List technically became a LinkedList, right? Even though the List refers to a LinkedList it does not make it one, am I right?

So the method returns a List but it demands a LinkedList.

Is that all correct?

yemerra
  • 1,352
  • 4
  • 19
  • 44
  • 2
    change it to `public List addHello()` A super-type `List` can't be cast to sub-class `LinkedList` without explicit down-cast. – Braj Aug 22 '14 at 15:52

2 Answers2

2

At first, the List has no type, so how can it add a String? So it should be:

private ArrayList<String> list;

So the first compile error ist the add method

It is a raw List, so it's like List<Object>, it can accept everything that is an Object, and String is an Object. You should not declare it as ArrayList because that's the specific implementation, instead keep it like List<String>. If you declare it raw, it won't raise a compiler error, but a warning.

Now, this code:

public LinkedList addHello() { 
    this.list.add("Hello");
    return this.list;
}

This simply won't compile because you state you have to return a (raw) LinkedList but you instead return a (raw) List. This is wrong because you cannot return a super type when you state you will return a more specific type. If moving this example for fruits, it's like your method states I will always return oranges but the implementation returns a fruit, which may be an apple, a strawberry or whatever that is not an orange.

To solve this, just change the return type:

public List addHello() { 
    this.list.add("Hello");
    return this.list;
}

And, as @ElliotFrisch covered in his answer, just don't use raw types in your code, instead add the generic check for compilation (because at runtime it will be erased).


if you have a interface, and you use it as a variable and then you refer to a class that has implemented the interface ( this.list = new LinkedList(); ), It does not mean that the List technically became a LinkedList, right?

Covered here: What does it mean to "program to an interface"?

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Thank you, but how about the "this.add("Hello");" Isn't that totally wrong too? Because add is a method of List but by "this." I am refering to the D-Object which does not implement add. – yemerra Aug 23 '14 at 11:26
  • @DennidvonEich typo from copying code directly. Fixed. – Luiggi Mendoza Aug 23 '14 at 16:39
0

It's a raw-type, and you should return the interface List (as that's what you've defined your list reference as). Something like,

private List<String> list;
D() { 
  this.list = new LinkedList<>(); // <-- diamond operator
}

public List<String> addHello() {  // return type.
  this.add("Hello");
  return this.list;
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249