1

Is there some way to print different data from an ArrayList containing different objects? For example, I created two basic classes:

import java.util.*;

class Furniture{
    String name;
    int weight;

    Furniture(String name, int weight){
        this.name = name;
        this.weight = weight;
    }

    String getName(){
        return name;
    }
    int getWeight(){
        return weight;
    }
    }
}
class Resident{
    String name;

    Resident(String name){
        this.name = name;
    }

    String getName(){
        return name;
    }
}

Then I stored them in an ArrayList<Object> and wanted to print the names, by using declared below printArrayList method:

public class Main{

public static <E> void printArrayList(ArrayList<E> arrayToPrint){
    for(E element : arrayToPrint){
        try{
            System.out.println(element.getName());
        }
        catch(Exception e){
            System.out.println("Exception e: " + e);
        }
    }
}

 public static void main(String []args){
    Furniture sofa = new Furniture("Sofa", 5);
    Resident mike = new Resident("Mike");

    ArrayList<Object> arrayList = new ArrayList<>();

    arrayList.add(sofa);
    arrayList.add(mike);
    printArrayList(arrayList);
}

Now, I know that not all objects can have a variable name or declared get method, therefore I tried to exclude these cases by try/catch. I also tried to exclude it by using fe:

if(elements.getName() == null)

Still, same results.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
td1
  • 21
  • 1
  • 4
  • 1
    Possible duplicate of [How to use the toString method in Java?](https://stackoverflow.com/questions/3615721/how-to-use-the-tostring-method-in-java) – Mick Mnemonic Jul 27 '18 at 08:22
  • You shold cast your object before accessing its methods. – Sumesh TG Jul 27 '18 at 08:22
  • Why don't you use the toString method ? – LoolKovsky Jul 27 '18 at 08:23
  • 1
    you can use `instanceOf` method to check if object is of specific class (like `element instanceOf Furniture`) or use `Reflection` API for checking class/variable/method existence – Ashishkumar Singh Jul 27 '18 at 08:23
  • 3
    I would wonder if it's a good idea to have completely unrelated objects in a List in the first place. Resident and Furniture don't seem to have any reason to be in the same list. If they have, they should at least share a common interface (`Named`?), and you should have a `List`. – JB Nizet Jul 27 '18 at 08:25
  • 2
    Your first problem is `ArrayList` – AxelH Jul 27 '18 at 08:25

2 Answers2

4

You don't need to use a parameterized type. Rather introduce a specific interface (for example NameAware) that exposes the getName() method that your classes with implement. In this way you could rely on a common type.

public interface NameAware{
   String getName();
}

public class Resident implements NameAware{
     ...
     public String getName(){
        return name;
    }
}

public class Furniture implements NameAware{
     ...
     public String getName(){
        return name;
    }
}

And define your method as :

public static void printArrayList(ArrayList<NameAware> arrayToPrint) {
    for (NameAware element : arrayToPrint) {
        try {
            System.out.println(element.getName());
        } catch (Exception e) {
            System.out.println("Exception e: " + e);
        }
    }
}

Note that you should change your actual code from :

ArrayList<Object> arrayList = new ArrayList<>();

to

ArrayList<NameAware> arrayList = new ArrayList<>();
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • best would be to declare the parameter as `ArrayList extends NameAware>` – Lino Jul 27 '18 at 08:31
  • even better `List extends NameAware>` or `Iterable extends NameAware>` – Mick Mnemonic Jul 27 '18 at 08:32
  • @Lino You are right. But Is it not a reading overhead and a not necessary thing for the actual requirement ? `List extends NameAware>` would mean that we want to set some restrictions (as not adding element in the list) and opening the possibilities on the generic type the List. But it makes the code more complex to read and it is actually not a requirement. – davidxxx Jul 27 '18 at 08:41
  • @Mick Mnemonic I fully agree to replace all declared type `ArrayList` by `List` in the actual code but concerning `Iterable` it looks like a premature code generalization. Why do we should make more abstract the `List` in the methods that consumes actually only a `List` ? Currently nothing requires it and introducing it would give the reverse feeling. – davidxxx Jul 27 '18 at 08:51
  • @davidxxx, yes, using `Iterable` wouldn't hurt but doesn't really help either. The method is basically about iteration so in that sense it makes sense. – Mick Mnemonic Jul 27 '18 at 09:04
2

The best practice would be to declare an interface with the getName method, and have both Furniture and Resident implement it.

public interface Namable {
    public String getName();
}

Then, use a List<Namable> instead of a List<Object>:

Furniture sofa = new Furniture("Sofa", 5);
Resident mike = new Resident("Mike");

List<Namable> arrayList = new ArrayList<>();

arrayList.add(sofa);
arrayList.add(mike);

for (Namable n : arrayList) {
    System.out.println(n.getName());
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • Why did you even post this if he wrote: "Now, I know that not all objects can have a variable name or declared get method, therefore I tried to exclude these cases by try/catch. I also tried to exclude it by using fe:" – LoolKovsky Jul 27 '18 at 09:01