1

Why does this code:

import java.util.*;
class Playground {
    public static void main(String[ ] args) {
        List<Integer> l = new LinkedList<>();
        Iterator<Integer> i = l.descendingIterator();
    }
}

Generate this compiler error

./Playground/Playground.java:5: error: cannot find symbol
        Iterator<Integer> i = l.descendingIterator();
                               ^
  symbol:   method descendingIterator()
  location: variable l of type List<Integer>
1 error
  • Here is the relevant JavaDocs API
  • Running Java 7.. In case that is issue. Thought it had been around for donkeys years.
  • Here is a canned example elsewhere.
  • You could copy/paste code from here into this website to see,
Mureinik
  • 297,002
  • 52
  • 306
  • 350
JGFMK
  • 8,425
  • 4
  • 58
  • 92
  • 6
    Try `LinkedList l = new LinkedList<>();` Your type of `l` is a `List` and hence it doesn't have such a method on it. – Thiyagu Jan 04 '20 at 13:25
  • @user7 If you've grown up using things like Spring - you learnt to always code to interfaces... So I stick by the accepted answer as the one I go with. – JGFMK Jan 04 '20 at 13:47
  • Coding to an interface is not specific to Spring. It is a natural thing to do. – Thiyagu Jan 04 '20 at 13:53
  • 4
    If I am not mistaken main goal of programming-on-interface is to give us flexibility to change actual type of object handled by variable. If variable needs to be cast then that defeats the purpose of it because we no longer can use *any* subtype of interface but we are limiting acceptable objects to one type which was specified while casting. – Pshemo Jan 04 '20 at 14:06
  • 1
    If you want to code to an interface, you should use the `Deque` interface and not `List` here – Thiyagu Jan 04 '20 at 14:34
  • 2
    Refusing to use the actual type for the variable because “always code to interfaces” and then perform a type cast to the actual type, is Cargo Cult programming. Well, @Pshemo already explained it, but it can’t be emphasized enough. – Holger Feb 05 '20 at 17:16

3 Answers3

4

Following the principal

“Coding to interfaces, not implementation.”

I suggest to use the Deque interface that provides descendingIterator() method

Deque<Integer> deque = new LinkedList<>();
Iterator<Integer> iterator = deque.descendingIterator();

instead.

samabcde
  • 6,988
  • 2
  • 25
  • 41
3

You are trying to call descendingIterator on a List reference. The compiler doesn't know that the runtime type is a LinkedList, hence the compilation error.

If you want to access this method, you could define the reference as a LinkedList:

LinkedList<Integer> l = new LinkedList<>();
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • Ah right. I had it indoctrinated to always code Collections against interfaces. That rule of thumb is flawed. That would explain it. Thank you. – JGFMK Jan 04 '20 at 13:30
  • Sure, that would work, _if_ the method is defined as part of the interface contract. Its not in this instance, as `LinkedList` implements additional methods outside of the `List` contract – Jason Jan 04 '20 at 13:42
  • 2
    You could code against the `Deque` interface, if you want to. – Dorian Gray Jan 04 '20 at 14:25
2

List is an interface and LinkedList is an implementation of List

You have the option of explicit typecasting like the following

Iterator<Integer> i = ((LinkedList<Integer>)l).descendingIterator();

or change your code to be the following:

import java.util.*;
class Playground {
    public static void main(String[ ] args) {
        LinkedList<Integer> l = new LinkedList<>();
        Iterator<Integer> i = l.descendingIterator();
    }
}
Pshemo
  • 122,468
  • 25
  • 185
  • 269
papaya
  • 1,505
  • 1
  • 13
  • 26
  • 1
    I actually prefer this. As it adheres to the Interface principle still – JGFMK Jan 04 '20 at 13:32
  • Sorry - re-edited again. You need to do a double cast. To get rid of compiler issues. – JGFMK Jan 04 '20 at 13:41
  • 1
    `( Iterator)` is not needed. `descendingIterator()` called on `LinkedList` will return `Iterator` so that additional cast is irrelevant. – Pshemo Jan 04 '20 at 13:43
  • IT IS... To get rid of.. " Note: Recompile with -Xlint:unchecked for details. 1 error" – JGFMK Jan 04 '20 at 13:45
  • @JGFMK Where do you get that information? I don't see any warning when I use code like https://ideone.com/BOWb1Y. – Pshemo Jan 04 '20 at 13:47
  • @JGFMK I did, got only "No output.", no info about any error. https://i.stack.imgur.com/6Bhxn.png – Pshemo Jan 04 '20 at 13:51