【问题标题】:need C++ template-like functionality in Java在 Java 中需要类似 C++ 模板的功能
【发布时间】:2015-01-10 01:06:35
【问题描述】:

在我的程序中,我有以下类层次结构:

public abstract class Effect
  {
  // ...  
  }

public class Effect1 extends Effect
  {
  public static final NAME = "blah blah 1";
  // ...
  }

public class Effect2 extends Effect
  {
  public static final NAME = "blah blah 2";
  // ...
  }

(更多具有完全不同实现的 EffectN 类)。后来,我有了另一个使用这些 EffectN 的类:

public abstract class EffectList
  {
  protected Effect mEffect;

  // ...
  }

public class EffectList1 extends EffectList
  {
  public static final N = Effect1.NAME;

  public EffectList1
    {
    mEffect = new Effect1();
    }

  // ... 
  }

public class EffectList2 extends EffectList
  {
  public static final N = Effect2.NAME;

  public EffectList2
    {
    mEffect = new Effect2();
    }

  // ...
  }

(更多的 EffectListN 类,每个 EffectN 一个)。

现在,虽然 EffectN 确实有完全不同的实现,但所有 EffectListN 都(几乎)相同——它们之间的唯一区别如上所示。

现在,如果这是 C++,所有的 EffectListN 类都可以用 1 个模板轻松生成,但是 AFAIK(对 Java 来说还很新)Java 泛型无法完成这项工作,对吗?

有什么建议吗?

【问题讨论】:

标签: java


【解决方案1】:

您是否正在尝试创建通用方式来调用构造函数?如果是这样,只要所有实现都提供相同类型的参数,就可以通过反射来完成,例如默认构造函数:

class EffectList<EffectType extends Effect> {
  public EffectList(Class<EffectType> clazz) {
    try {
      mEffect = clazz.getConstructor().newInstance();
    } catch (Exception ex) {
      // suppressing Exceptions - in production code you should handle it better
      throw new RuntimeException(ex);
    }
    // ...
  }

  // ...
}

然后像这样使用它:

EffectList<Effect1> effectList1 = new EffectList(Effect1.class);
EffectList<Effect2> effectList2 = new EffectList(Effect2.class);

然而,静态字段不能以这种方式处理 - 你可以做的最好的是将其设为实例变量并通过反射获取值:

clazz.getDeclaredField("NAME").get(null); // null is used to obtain static fields

无法处理静态字段的原因是所有 EffectList 之间只有一个变量共享(因为在它下面只有一个类,只添加了编译时检查)。

【讨论】:

  • 谢谢,您的评论帮助我意识到静态字段是这里问题的本质。我最终改变了架构,不再需要实例化大量的 EffectListN 类,而只需要每个实例的一个实例。这让我摆脱了静态字段。
【解决方案2】:

我不知道您将如何使用 C++ 来实现,但根据您的描述,不,Java 泛型将无法处理此问题。

一方面,您拥有依赖于EffectN 类型中定义的其他static 字段的static 字段。 Java 中没有任何内容设置类型应具有static 字段的限制。您将无法动态设置

public static final N = SomeEffect.NAME;

其次,由于类型擦除,你将无法做到

public EffectList2
{
    mEffect = new SomeEffect(); // assuming SomeEffect is the type parameter
}

您需要传入Class 实例并使用反射来实例化此类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 2011-12-17
    相关资源
    最近更新 更多