1

The 'iterator()' method is a method in the Iterable interface. This method returns an object of a class that implements the Iterator interface. Since the Collection Interface extends the Iterable interface, it inherits the 'iterator()' method from it (the Iterable interface). And so, any object of a class that implements the Collection interface can call the 'iterator()' method.

Let's assume that I instantiate a class, that implements the Collection interface, like this:

List<String> names = new LinkedList<String>();

And after instantiation, I add objects, to the collection, like this:

names.add("John");
names.add("Joe");

Now, if I want an iterator object to iterate over the collection of String objects, I presumed that I could use the following syntax to get an iterator object:

Iterator<String> iterator = names.iterator();

However, I see a different syntax altogether, on a lot of websites, the syntax being Iterator iterator = names.iterator();

Which brings me to the question - Why do we see

Iterator iterator = names.iterator();

used over

Iterator<String> iterator = names.iterator();?

Is it because of backward compatibility? The way I see it, there ought to be a diamond notation after the word 'Iterator' e.g.

Iterator<String> iterator = names.iterator();

Links referred - Declaring an iterator in Java

By the way, is Peter Lawrey's answer to a question at Declaring an iterator in Java, the answer to my question? If yes, can somebody please expand on his answer? Thanks in advance.

  • 3
    **NEVER USE `Iterator iterator = names.iterator()`**. This is a rawtype, it is there for backwards compatability to Java 4 code written before generics existed. Avoid using rawtypes - if you turn on compiler warnings you should get a warning about this. – Boris the Spider Apr 22 '18 at 18:46

3 Answers3

2

Because Iterator<String> allows

while (iterator.hasNext()) {
  String item = iterator.next();
  // use it
}

Using only Iterator would force us to cast:

while (iterator.hasNext()) {
  String item = (String) iterator.next();
  // use it
}

which should be avoided.

BTW, use List<String> names = new LinkedList<>();, not List<String> names = new LinkedList<String>();.

  • I used `List names = new LinkedList();` since I wanted the example code to be precise. In practice, `List names = new LinkedList<>();` wouldn't have any advantage over its counterpart except for convenience, maybe. Or would it? (It took me a while to figure out how to highlight code using backticks - hence the multiple deletions of this comment) – Sheshadri Iyengar Apr 22 '18 at 19:24
  • 1
    Five characters less. –  Apr 22 '18 at 19:25
2

The accepted answer of the question referenced makes a use of a raw type without any good reason as the question already used generic types.


The following declares a generic List but a raw Iterator :

List<String> names = new LinkedList<>();
Iterator iterator = names.iterator();

So you will have to cast the element returned by the iterator to the concrete type such as :

Iterator iterator = names.iterator();
String myString = (String) iterator.next();

it makes no sense. Use always generic type and you should also favor the use of diamond operator (it is just syntactic sugar) :

List<String> names = new LinkedList<>();
Iterator<String> iterator = names.iterator();

Use raw types only as you don't have any other choice : you develop in Java 1.4 or earlier (not very common today).

davidxxx
  • 125,838
  • 23
  • 214
  • 215
1

It is indeed because of backwards compatibility, which is Java's strong point (and the source of a lot of weaknesses as well). Suppose you have some Java 1.4.2 code that doesn't know about generics, then it would no longer run on Java 1.5 or higher. And since the 1.4 branch is no longer maintained, that would be a problem.

Under the hood, after compilation, and again because of backwards compatibility, Java uses type erasure, and your Iterator<String> is nothing but an Iterator. However, if you use the so-called raw type (Iterator) instead of the generic type (Iterator<String>), the compiler is no longer able to maintain type safety. Which is why you should avoid raw type at all costs in modern Java code.

SeverityOne
  • 2,476
  • 12
  • 25