【问题标题】:Cannot instantiate Generic item to a list Java无法将通用项目实例化为列表 Java
【发布时间】:2018-05-02 11:13:38
【问题描述】:

我有一个看起来与此类似的通用类

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;
    }
}

我要做的就是检查参数 T 是否是构造函数中的任何类型的列表。如果 T 是 List 那么我想将它实例化为一个新的 List();

我尝试了以下代码

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

或者这个

this.items = new ArrayList<>();

但我不断收到错误消息,因为我无法提供参数类型。 如果泛型类型 T 是 List,如何确保使用新 List 实例化项目?

【问题讨论】:

  • 如果您打算硬编码列表的依赖项,那么为什么不直接使用NetworkItems&lt;List&gt;
  • 因为容器应该能够同时托管项目列表和独立项目。
  • @SriramR 因为容器应该能够同时托管项目列表和独立项目 - 为什么要这样做?为什么不为单个项目或项目集合使用两个不同的容器?
  • 我不想重复代码。实现是一样的。除了 T 部分。所以我想如果有办法不用重复代码,为什么不做呢?

标签: java generics arraylist


【解决方案1】:

给类一个Supplier&lt;T&gt;类型的非可选构造函数参数。

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();
    }
    // ...

现在,如果您有NetworkItems 的实例,您始终可以获得默认值。例如,

NetworkItem<List<String>> stringListItems = new NetworkItem<>(ArrayList::new);
List<String> defItem = stringListItems.createDefault();

【讨论】:

    【解决方案2】:

    你可以只添加一个类型转换,然后它应该像你已经说过的那样工作:

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

    【讨论】:

    • 它给出了 UncheckedCastException 警告。
    • 是的,这是真的,但我认为如果你使用这样的泛型成员变量,你无法阻止这种情况,因为构造函数在编译时无法知道你想在那里使用哪种类型。也许您可以使用另一种方法,而不是仅使用T items,您可以直接使用列表List&lt;T&gt; items; 添加您的项目。
    • 即使TList&lt;Something&gt;this.items 可能仍然是null 所以instanceof 不会有太大帮助。
    • 是的,我之前确实将它用作 List。问题是我希望这个容器能够容纳一个 List 和一个对象。所以我只是想知道它是否可能不写一个新的持有人。
    【解决方案3】:

    根据此处的 cmets 和您的原始帖子,无论您的情况如何,似乎items 都旨在作为一个集合。你不是更适合做以下事情吗?

      public class NetworkItems<T> {
    
        private Status status;
        private List<T> items;
    
        //continue the remainder of your implementation here 
      }
    

    我知道这对于可以存在 1 个项目的场景并不理想,但您可以确保此处的类型安全,并通过将 items 设为一个集合来坚持这可以是一个或多个项目的概念。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-28
      • 2019-07-06
      • 2020-03-15
      • 2020-02-09
      相关资源
      最近更新 更多