【问题标题】:Generic with Variable Type Arguments具有可变类型参数的泛型
【发布时间】:2012-01-03 17:59:18
【问题描述】:

我想做类似的事情

public interface Foo<R, P...> {
    public R bar(P...) {/*misc*/}
}

获取要在我的绑定实现中使用的类型数组。这在java中可能吗?

Varargs 旨在让我拥有给定类的任意数量的参数。

我想使用它(或类似的东西)让我的方法接受多个参数,每个参数都是给定不同类的成员。这些类是在绑定泛型时定义的。

我知道有一些变通方法,但是有没有一种类型安全的方法可以做到这一点?

【问题讨论】:

  • 到目前为止你得到的有什么问题?唯一的问题是 varags 不能很好地与泛型配合使用。

标签: java generics syntax variadic-functions


【解决方案1】:

由于您显然希望能够使 bar 采用 不同类型 的多个参数(可变参数 不用于),我建议您这样做取而代之的是一个参数。然后,您可以使该单个参数成为一个容器,其中包含您要使用的每个单独的“参数”。

一般来说,最好为要与此方法一起使用的每组参数创建一个类,以便为它包含的每个对象命名。但是,您也可以创建一系列元组类型(例如 Pair)以用作持有者。

这是一个例子:

public class Foo<R, P> {
  /*
   * Not sure how you intend to provide any kind of implementation
   * here since you don't know what R or P are.
   */
  public R bar(P parameters) { ... }
}

public class SomeFoo extends Foo<SomeResult, Pair<Baz, Bar>> {
  public SomeResult bar(Pair<Baz, Bar> parameters) { ... }
}

SomeFoo foo = ...
SomeResult result = foo.bar(Pair.of(baz, bar));

【讨论】:

  • 我认为这是个好主意,它允许绑定类定义参数的数量和类型,方法是将它们包装在容器/元组对象中。 tuple/pair 是核心库/jdk 的一部分吗?我找不到它们,尽管我想自己写会很简单。我是否正确建议 java 中的元组完全履行 c 中结构的作用?
  • 一般来说,我会避免创建元组类型(它们在 JDK 中不存在,因为它们由于各种原因不能很好地工作)并创建真正的类,为每个包含的对象提供一个有用的名称。我主要只是提到了这一点,因为它接近您似乎要求的内容,并且因为它是您拥有的选项。简短的回答是,如果你想对任意数量的任意类型的对象进行分组,那么类就是要走的路。你可以让一个类变得非常小和简单,并让它基本上充当一个结构。
  • Eclipse 实际上有一个自动执行此操作的功能:refactor &gt; introduce parameter object
【解决方案2】:

你写的:

我想用它(或类似的东西)让我的方法接受多个参数,每个参数都是给定不同类的成员。

我认为如果没有一些丑陋的 hack,就不可能以类型安全的方式执行此操作,例如在对象中包含 Class 的实例。

问题是,使用 VarArgs 你实际上是在一个数组中传递的。但是你不能有一个包含不同类型对象的数组,它们都必须是相同的(或子类,所以如果你有 X[] y 那么每个元素必须是 X 的子类)

如果你的函数真的可以处理多种类型,你可以创建一个类,它存储一个 Class 的实例和一个 T 的实例,并传入该容器的 var args 列表。

所以例如你可以有

class TypedInstance<T>{
   Class<T> type;
   T instance;
}

然后有一个看起来像

的函数
public whatever(TypedInstance<? extends Object>... whatever){
  ...
  doSomethingWith(whatever[0].type, whatever[0].instance);
  ...
}

由于 Java 的类型擦除,需要这些类型的 hack。泛型参数在运行时被移除,所以如果你想使用它,你必须把它放回去。

【讨论】:

  • +1 好主意,但该函数从不使用 P。除了必须扩展 Object 之外,参数类型没有类型安全。 'instance'的类型可以通过instance.getClass()获取;基本上,您将 T 类型的实例包装在 wrapper 中,这有点毫无意义。
  • 没错,但没有真正的方法可以直接做到这一点……尽管 Colin D 使用嵌套元组的想法非常出色。让我想起了在 Scheme/lisp 中做事的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-04
  • 1970-01-01
  • 2018-04-16
  • 1970-01-01
相关资源
最近更新 更多