【问题标题】:Java Generics - when is parameterization required?Java 泛型 - 什么时候需要参数化?
【发布时间】:2012-02-17 19:59:30
【问题描述】:

这是一个简单的例子:

class World<S extends Sprites, B extends Bodies> {

// Both  of these have a problem...

static World world = null; // "World is a raw type. References to generic type
                           // World<BOD,SPRT> should be parameterized"

static World<S, B> world = null; // "Cannot make a static reference to the non-static type S
                       // "Cannot make a static reference to the non-static type B

// The following is allowed but looks ugly/fishy to me
static World<?, ?> world = null; //

如果您想知道,我正在尝试实现单例模式。挑战在于这个类在一个单独的包 GAME 中扩展,我不能让这个包(模型)对那个 GAME 有任何依赖。因此构造函数必须是模型。所以可以让Constructor将单例对象存储在MODEL中这个类的静态变量中。

您认为static World&lt;?, ?&gt; world = null; 确实丑陋吗?有没有更好的方法来解决这个问题?

【问题讨论】:

  • 记住Java有类型擦除;将只有一个静态 world 变量,无论您实例化 World 类有多少不同的方式(因为就运行时而言它们都共享同一个类)。
  • 一开始我不会让 World 成为单例/静态的。当你编写一个存在两个世界的不同游戏时会发生什么?无论如何,在我看来,要确保 it 只创建一个 World,这取决于您的 GAME 包中的任何内容。这以现在的方式回答了您的问题,而是避免了这个问题。
  • 好点...实际上我的 GAME 包实现了一个传统的单例以确保只有一个...

标签: java generics inheritance singleton


【解决方案1】:

this answer 所述,您无法访问静态方法或字段中的泛型类型参数。因为静态字段在类的所有实例之间共享(在这种情况下,我猜您的类将是 Model),这如何同时适用于 Model&lt;Sprites, Bodies&gt;Model&lt;ClassA, ClassB&gt;

【讨论】:

  • 是的,这很有道理...它解释了为什么静态 World 无法编译。然而,World, ?> 如何摆脱它呢?
  • @pitosalas 因为? 是通配符,表示“任何类型”。因此,World&lt;?, ?&gt; 在这种情况下就像写普通的World,并且不受Model&lt;S, B&gt; 的类型参数的限制(记住这是编译错误的根源)。
  • 人们认为在这种情况下写 World, ?> 是丑陋的还是完全干净的?是不是比写一个也被警告接受的普通 World 更丑?
  • @pitosalas World&lt;?, ?&gt; 可能也不是您想要的。请注意,您不能向使用通配符参数化的容器添加任何内容(尝试向List&lt;?&gt; 添加一些内容,看看会发生什么)。这里的要点是你的设计很狡猾;尝试重新设计你的代码,这样你就不需要使用&lt;?&gt; 或静态。无论如何,您可能甚至都不需要单例。
【解决方案2】:

当然,如果您想要一个单例,您必须预先知道该单例中引用的确切类型是什么。

也许如果您在示例中添加更多细节,这将不再适用,但据我所知,您在这里不需要泛型。如果你想表达你存储的SpritesBodies的字段可以是这些类的任何子类,只要用这些类型声明这些字段,继承会处理剩下的事情。

想想这个名字:“泛型”,它被用于在不同的上下文中反复重用的东西。就像定义树结构的类一样,它可以保存任何类的对象。有时很难判断您是否需要泛型。但是单身人士绝对是相反的。没有什么比单例更通用的了:一个类,一个实例。

P.s.:不过有 Enums,它们都是通用的并且具有固定数量的实例,self-bound generic types 是这些情况的解决方案,但我几乎可以肯定你不需要这个。

【讨论】:

  • 是的,我事先知道...但是,还有其他原因导致我使用泛型,这与保持包分离防漏同时避免大量烦人的铸造有关。事实上,这个模型来自另一个 StackOverflow 线程:stackoverflow.com/questions/9270466/…
  • @pitosalas 也许更大的代码示例和一点解释可以帮助我们确定您当时需要的解决方案。就目前而言,您的问题的答案确实是您无法对静态字段进行参数化。
  • 我不愿用更长的代码示例来加重这个列表的负担......我不想被打:)
猜你喜欢
  • 2015-09-30
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多