【问题标题】:Java Generic with 1 type parameter and 2 constraints具有 1 个类型参数和 2 个约束的 Java 泛型
【发布时间】:2013-05-09 23:38:30
【问题描述】:

我知道可以将多个约束添加到通用类定义中,例如:

class Example<I extends Object & Comparable<Object>>{}

但我想要一个泛型 (MyGeneric),它采用另一个泛型 (SomeGeneric&lt;T&gt;) 作为其类型参数,并约束该泛型 (例如 T extends SomeClass) 的类型参数 (T)。

重要的是,我需要知道类内部SomeGenericSomeClass 的类型(GT 都需要绑定)。例如,想象这样的事情:

class MyGeneric<G extends SomeGeneric<T>, T extends SomeClass>
{
   public G returnSomeGenericImpl(){}
   public T returnSomeClassImpl(){}
}

问题: 上面的方法有效,但我希望我的类只有一个类型参数,以使我的类的实现者生活更轻松。有没有办法做到这一点?

这样的东西会很好(但这个特定的代码是不正确的):

class MyGeneric<G extends SomeGeneric<T extends SomeClass>>
{
   public G returnSomeGenericImpl(){}
   public T returnSomeClassImpl(){}
}

如果我不清楚,我很乐意澄清我的意图。

【问题讨论】:

  • 我不明白这怎么可能奏效。如果您从不指定具体类型T,编译器应该如何猜测它?如果只有一个选项,那很容易,但通常没有。如果您不关心特定类型,那么为什么不使用有界通配符类型(或方法上的本地类型参数)。
  • @JoachimSauer 你是说由于类型擦除,编译器可以强制执行我想要的约束,但无法提取/知道泛型的类型?例如,它可以做&lt;G extends SomeGeneric&lt;SomeClass&gt;&gt;甚至&lt;G extends SomeGeneric&lt;? extends SomeClass&gt;&gt;,但是T的类型(在这种情况下是?)是未知的。
  • @JoachimSauer 关于您评论的第二部分,显然我确实关心特定类型,因为我想从public T returnSomeClassImpl(){}返回它的一个实例
  • @Bohemian 指定两种类型一般是没有问题的,但是在这种情况下写new Whatever&lt;SomeGeneric&lt;T&gt;,T&gt;() 感觉是多余的,我们只是重复T。如果不可能,那就不可能,这就是问题的重点
  • 好吧,如果你想将G extends SomeGeneric&lt;T&gt;绑定到SomeGeneric&lt;T&gt;,那么也许你可以完全摆脱G

标签: java generics


【解决方案1】:

看起来不可能实现。

通过删除一个类型变量并尝试定义它,将类型定义减少一阶后,

class G extends SomeGeneric<T extends SomeClass>{}

无法编译,因为类型参数 T 未绑定到已定义的类型参数。但是,这行得通 -

class G<T extends SomeClass> extends SomeGeneric<T>{}

因此,我推断使用两种类型进行参数化的唯一方法是预先声明它们。

【讨论】:

  • @seeta 当你写“所以,我推断用两种类型参数化的唯一方法是预先声明它们。” “预先”是什么意思?预先定义一个类的问题是我需要强制所有必要的类扩展这个类......这不是一个解决方案。然而“这看起来不可能实现”可悲的是,我认为我同意
  • @nakosspy 关于“该类有两个类型参数 T 和 G。两者都必须预先声明”,当然,没有人对此进行过辩论。问题是关于 java 如何允许它们被声明。
  • @AlexAverbuch 在前面,我的意思是用类名声明参数。正如你所写 - MyGeneric, T extends SomeClass>
  • @AlexAverbuch 你愿意接受关闭的答案吗?
  • 我已经(犹豫地)接受了你的回答,但主要是——正如你所说——结束。我希望有人能给出更好的答案,比如“不,这是不可能的,这里详细解释了原因”或“是的,这是一种你可以用来实现你想要的模式”
【解决方案2】:

试试这个

class Test1<T extends List<? extends Number>> {

    public static void main(String[] args) throws Exception {
        new Test1<ArrayList<Number>>();  
        new Test1<ArrayList<Integer>>(); 
        new Test1<ArrayList<Object>>();  // compile error
    } 
}

【讨论】:

  • 您能在此添加更多解释吗?所以关注此讨论对我会更有帮助
  • 它说“允许的类型是数字列表”
  • 请重读问题:“重要的是,我需要知道类内部 SomeGeneric 和 SomeClass 的类型(G 和 T 都需要绑定)”
  • 如果两者都需要绑定,那么它们都必须是参数。如果内部类型不是参数,则不能绑定它。
【解决方案3】:

想象一下:

Type t = someClass();
Type g = someGeneric(t);

foobar(g,t)

与此相比

Type g = someGeneric(someClass());
foobar(g,?)

第二个是 Evgeniy Dorofeev 的解决方案。 你看到问题了吗?您不能绑定到参数中的变量。与泛型相同。 你想做的就是这个

Type g = someGeneric(Type t = someClass());
foobar(g,t)

【讨论】:

  • 感谢您的解释,但我认为这不能作为答案。也许最好回复@EvgeniyDorofeev 作为对他的回答的评论..?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多