Java: Why does my List contain different types? (Filtering Lists)

By | July 12, 2018
Questions:

The whole time I thought, if I am using a List like List<Thing> things = new ArrayList<>() all items in this list are of Type Thing. Yesterday i was taught the other way.

I’ve created the following stuff and wonder why it is like it is.

An Interface Thing

public interface Thing {
  String getType();

  String getName();
}

A class ObjectA

public class ObjectA implements Thing {
  private static final String TYPE = "Object A";
  private String name;

  public ObjectA(String name) {
    this.name = name;
  }

  @Override
  public String toString() {
    final StringBuffer sb = new StringBuffer("ObjectA{");
    sb.append("name='").append(name).append('\'');
    sb.append('}');
    return sb.toString();
  }

  @Override
  public String getType() {
    return TYPE;
  }

  @Override
  public String getName() {
    return name;
  }

  // equals and hashCode + getter and setter
}

A class ObjectB

public class ObjectB implements Thing {
  private static final String TYPE = "Object B";
  private String name;
  private int value1;
  private String value2;
  private boolean value3;

  public ObjectB(String name, int value1, String value2, boolean value3) {
    this.name = name;
    this.value1 = value1;
    this.value2 = value2;
    this.value3 = value3;
  }

  @Override
  public String getType() {
    return TYPE;
  }

  @Override
  public String getName() {
    return name;
  }

  @Override
  public String toString() {
    final StringBuffer sb = new StringBuffer("ObjectB{");
    sb.append("name='").append(name).append('\'');
    sb.append(", value1=").append(value1);
    sb.append(", value2='").append(value2).append('\'');
    sb.append(", value3=").append(value3);
    sb.append('}');
    return sb.toString();
  }

  // equals and hashCode + getter and setter
}

The main method

  public static void main(String[] args) {
    final List<Thing> things = new ArrayList<>();
    final ObjectA objA = new ObjectA("Thing 1");
    final ObjectB objB = new ObjectB("Thing 2", 123, "extra", true);

    things.add(objA);
    things.add(objB);

    // The List doesn't contain Thing entities, it contains ObjectA and ObjectB entities
    System.out.println(things);

    for(final Thing thing : things) {
      if (thing instanceof ObjectA) {
        System.out.println("Found Object A: " + thing);
        final ObjectA object = (ObjectA) thing;
      }
      if (thing instanceof ObjectB) {
        System.out.println("Found Object B: " + thing);
      }
    }
  }

The output of this method is:

[ObjectA{name='Thing 1'}, ObjectB{name='Thing 2', value1=123, value2='extra', value3=true}]

So i assume i’ve ObjectA entities and ObjectB entities in my List<Thing>.

Question: Can someone provide a link (or some keywords which can be used for searching), which explain this behavior, or can explain it to me?

additional Question: I’ve started to filter this List<Thing> with instanceof but i have read instanceof and casting are bad practice (e.g. no good model design). Is the are “good” way to filter this List for all Types of ObjectA to perform only on these objects some operations?

Answers:

Leave a Reply

Your email address will not be published. Required fields are marked *