【问题标题】:new <T> in JavaJava 中的新 <T>
【发布时间】:2013-09-25 09:55:42
【问题描述】:

我有这个问题

一种从一个类中删除不需要的细节并返回带有想要的对象的集合的方法。问题是我希望这个方法能够与不同的类一起工作(尽管它们基于一个抽象),所以我使用泛型类型。问题是,有一次我需要创建一个实例,这是不可能的。我寻找了一些出路,但它似乎不适用于我的情况。 所以,代码如下

 private <T extends RestMandate> List<T> toRestMandate(List<CardMandate> mandates ) {
    List<T> restMandates = new ArrayList<>(mandates == null ? 0
            : mandates.size());
    if (mandates != null) {
        for (CardMandate mandate : mandates) {
             restMandates.add(new T(mandate));
        }
    }

    return restMandates;
}

RestMandate 是基类, CardMandate 是我获取信息。有什么想法吗?

【问题讨论】:

  • 您想简单地将List&lt;CardMandate&gt; 转换为List&lt;RestMandate&gt; 吗?
  • 实际上是的)问题是 CardMandate 的对象有太多参数,我正在取出它们。如果您有其他更简单的解决方案,我将不胜感激)
  • 什么意思对象的参数太多了?
  • 对不起,字段太多(取自数据库,我不需要)
  • 好吧,现在是展示一些例子的时候了。这并不完全有意义。您不能从对象中删除属性。您是否坚持处理超类-子类关系。不管是什么,发布一个例子。

标签: java generics instantiation


【解决方案1】:

由于泛型类型参数在运行时被删除,因此您无法像尝试那样引用它。唯一的出路是类型标签参数+反射实例化。

更好的选择是重新设计您的解决方案来解决这个问题,而不依赖于泛型和类型标签。改用动态方法分派:向RestMandate 添加一个方法,该方法将返回转换为所需类型的对象。

【讨论】:

  • 我明白,但我喜欢这种方法)它非常好,除了实例化这个东西。我会在工厂模式下这样做,以防没有解决方案有帮助
  • 在其他一些已经具体化类型参数的语言中很好:)
【解决方案2】:

因为Type Erasure,T 在运行时变成了Object。你已经不知道它的真实类型了。

如果你有它的类,你仍然可以通过反射来实例化对象。为此,您必须将类赋予您的方法:

private <T extends RestMandate> List<T> toRestMandate(List<CardMandate> mandates, Class<T> clazz ) {
  ...
  for (CardMandate mandate : mandates) {
     /*
      * I get the constructor which needs one CardMandate and call it.
      * Note : I do not recommend this solution (no check at compile-time!). 
      * Like Marko Topolnik, I advise to redesign the solution.
      */
     restMandates.add(clazz.getConstructor(CardMandate.class).newInstance(mandate));
  }
  ...
}

【讨论】:

  • 他正在使用参数化构造函数。 newInstance() 需要一个 0-arg 构造函数。
  • 我不能叫这个。它一直说类型不匹配。 List cardMandates; List restMandate; toRestMandate(cardmandates, restMandate);
  • 第二个参数必须是一个类,而不是一个列表。传递 ExpiringCard.class 作为第二个参数。
【解决方案3】:

要创建实例,您也需要 Class&lt;T&gt; 对象

private <T extends RestMandate> List<T> toRestMandate(List<CardMandate> mandates, Class<T> clazz) {
    //....
    T newInst = clazz.newInstance();

    //....
}

【讨论】:

  • 我看过这个,newInstance有异常的麻烦,程序不想用Constructor.newInstance()支持variant
  • 他正在使用参数化构造函数。 newInstance() 需要一个 0-arg 构造函数。
猜你喜欢
  • 1970-01-01
  • 2011-11-09
  • 2014-05-25
  • 2013-05-13
  • 2012-01-22
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 2022-06-17
相关资源
最近更新 更多