0

I have a generic class that looks similar to this

public class NetworkItems<T> {

    private Status status;
    private T items;

    public NetworkItems() {
        this.status = Status.FAILURE;
        this.items = null;
    }

    public NetworkItems(Status status, T listItems) {
        this.status = status;
        this.items = listItems;
    }

    public NetworkItems(Status status) {
        this.status = status;
        this.items = null;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public T getItems() {
        return items;
    }

    public void setItems(T items) {
        this.items = items;
    }
}

All I want to do is check if the parameter T is a List of any kind in the constructors. If T is a List<> then I want to instantiate it into a new List<>();

I tried the following code

if (this.items instanceof List) {
    this.items = Collections.emptyList();
}

or this

this.items = new ArrayList<>();

But I keep getting an error because I couldn't give a parameter type. How do I make sure that I instantiate the items with a new List if the generic type T is a List?

Sriram R
  • 2,109
  • 3
  • 23
  • 40
  • 1
    If you plan on hard-coding a dependency on list, then why not just use `NetworkItems`? – Tim Biegeleisen May 02 '18 at 11:15
  • Because the container should be able to host both list of items and a standalone item. – Sriram R May 02 '18 at 11:28
  • @SriramR *Because the container should be able to host both list of items and a standalone item* - why should it? Why not have two different containers for single item or collection of items? – lexicore May 02 '18 at 11:39
  • I didn't wanna repeat code. The implementation is the same. Except for the T part. So I thought if there's a way to do without repeating code, why not do it? – Sriram R May 02 '18 at 11:49

3 Answers3

1

Give the class a non-optional constructor argument of type Supplier<T>.

public class NetworkItems<T> {

    private Status status;
    private T items;
    private Supplier<T> defaultCreator;

    public NetworkItems(Supplier<T> def) {
        this.status = Status.FAILURE;
        this.items = null;
        this.defaultCreator = def;
    }

    public T createDefault() {
        return defaultCreator.get();
    }
    // ...

Now, if you have an instance of NetworkItems, you can always get a default value. Eg,

NetworkItem<List<String>> stringListItems = new NetworkItem<>(ArrayList::new);
List<String> defItem = stringListItems.createDefault();
daniu
  • 14,137
  • 4
  • 32
  • 53
0

You can just add a type cast, then it should work like you already said:

if (this.items instanceof List) {
    this.items = (T) Collections.emptyList();
}
Ehler
  • 285
  • 3
  • 11
  • It gives an UncheckedCastException warning. – Sriram R May 02 '18 at 11:25
  • Yes, that's true but I think you cannot prevent this if you use such generic member variable because the constructor cannot know at compile time which type you want to use there. Maybe you can use another approach, instead using just `T items` you can use direcly a list `List items;` where you add your items. – Ehler May 02 '18 at 11:31
  • Also even if `T` is `List`, `this.items` may still be `null` so `instanceof` won't help much. – lexicore May 02 '18 at 11:38
  • Yeah, I did use it earlier as List. The thing is I want this container to be able to hold a List<> and an Object. So I just wanted to know if its possible without writing a new Holder. – Sriram R May 02 '18 at 12:08
0

Based on comments herein and your original post, it seems like items is intended as a collection regardless of your situation. Would you not be better suited to do the following?

  public class NetworkItems<T> {

    private Status status;
    private List<T> items;

    //continue the remainder of your implementation here 
  }

I understand this is not ideal for the scenario where 1 item can exist, but you ensure type safety here and adhere to the concept of this can be one or more items, by making items a collection.

Jacob
  • 168
  • 2
  • 13