0

I am trying to iterate over an ArrayList of objects and print out the 'name' attribute of each object in the list. However, I cannot access the object's attributes even though I have getter method for the name in the Person class. Here is some code:

 ArrayList persons = new ArrayList<>();
 persons.add(new Person("Name","Age"));
 persons.add(new Person("Name1","Age1"));
 persons.add(new Person("Name2","Age2"));

persons
 .stream()
 .forEach(e -> System.out.println(e.getName()));   //giving an error

  forEach(e -> System.out.println(e));  //no error

It wont allow me to do this. all I can have just 'e' in the print command, which prints the reference numbers of the objects.

Any help is appreciated :)

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
Nero909
  • 75
  • 2
  • 6
  • What is the exception you're getting? – hermitmaster Oct 11 '15 at 04:42
  • 5
    Turn on all Java compiler warnings. The compiler will warn you that `ArrayList persons` with no generic type is a "raw type" and should be something like `ArrayList persons` instead. – VGR Oct 11 '15 at 04:46
  • 2
    [What is a raw type and why shouldn't we use it?](http://stackoverflow.com/q/2770321/4856258) – Tagir Valeev Oct 11 '15 at 04:56

1 Answers1

6

Let's see what the compiler says. (This would have been easier if you had provided a minimal, complete and verifiable example.)

$ javac Main.java
Main.java:33: error: cannot find symbol
            .forEach(e -> System.out.println(e.getName()));
                                              ^
  symbol:   method getName()
  location: variable e of type Object
Note: Main.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error

You get a warning and an error. The error says that e is of type Object that – as we know – has no method getName. This should alert you because, after all, you've put objects of type Person in your List, no? The warning says that we should re-compile with the -Xlint:unchecked flag for details. So let's do it.

$ javac -Xlint:unchecked Main.java
Main.java:28: warning: [unchecked] unchecked call to add(E) as a member of the raw type List
        persons.add(new Person("Name1", 1));
                   ^
  where E is a type-variable:
    E extends Object declared in interface List
Main.java:29: warning: [unchecked] unchecked call to add(E) as a member of the raw type List
        persons.add(new Person("Name2", 2));
                   ^
  where E is a type-variable:
    E extends Object declared in interface List
Main.java:30: warning: [unchecked] unchecked call to add(E) as a member of the raw type List
        persons.add(new Person("Name3", 3));
                   ^
  where E is a type-variable:
    E extends Object declared in interface List
Main.java:33: warning: [unchecked] unchecked call to forEach(Consumergt;) as a member of the raw type Stream
            .forEach(e -> System.out.println(e.getName()));
                    ^
  where T is a type-variable:
    T extends Object declared in interface Stream
Main.java:33: error: cannot find symbol
            .forEach(e -> System.out.println(e.getName()));
                                              ^
  symbol:   method getName()
  location: variable e of type Object
1 error
4 warnings

Apparently, the compiler is complaining about persons being “raw”. Reading up on generics tells us that we should specify the type of object we want to put into the list. So set's do it.

import java.util.ArrayList;
import java.util.List;

final class Person {

    private final String name;
    private final int age;

    public Person(final String name, final int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return this.name;
    }

    public int getAge() {
        return this.age;
    }
}


public final class Main {

    public static void main(final String[] args) {
        final List<Person> persons = new ArrayList<>();  // <--- here ---
        persons.add(new Person("Name1", 1));
        persons.add(new Person("Name2", 2));
        persons.add(new Person("Name3", 3));
        persons
            .stream()
            .forEach(e -> System.out.println(e.getName()));
    }
}

And now it works!

$ javac Main.java && java -cp . Main
Name1
Name2
Name3
5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • Yes it works now! All I did was declare the generic type for arraylist. ArrayList = new ArrayList<>(); Thank you so much! I have been hitting my head on the wall over this – Nero909 Oct 11 '15 at 05:06
  • @Nero you should use `List` rather than `ArrayList` (code to the interface, not the implementation). Also, it isn't necessary to use the `-Xlint:unchecked` compiler switch. A plain `-Xlint` will turn on *all* diagnostics, and is easier to type. – David Conrad Nov 04 '15 at 19:02