【问题标题】:Java formal type parameter definition (Generics)Java 形式类型参数定义(泛型)
【发布时间】:2008-12-11 20:26:14
【问题描述】:

我想定义一个泛型类型,其实际类型参数只能是

  1. 数字原始包装类之一(LongIntegerFloatDouble
  2. String

我可以通过这样的定义满足第一个要求

public final class MyClass<T extends Number> {
    // Implementation omitted
}

但我不知道如何见到他们两个。我怀疑这实际上是不可能的,因为AFAIK在定义正式类型参数时无法指定“或”语义,尽管您可以使用诸如

之类的定义来指定“和”语义
public final class MyClass<T extends Runnable & Serializable > {
    // Implementation omitted
}

干杯, 唐

【问题讨论】:

  • 类型擦除会将其放回对象(如果存在)。

标签: java generics


【解决方案1】:

Java 泛型不支持联合类型(此参数可以是 A OR B)。

在某些人可能感兴趣的相关说明中,如果您想强制执行多个限制,它确实支持多个边界。这是Java generics tutorial中提到的JDK的一个例子:

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

【讨论】:

  • 这不是一个坏例子(我看到它来自 SUN,而不是你的)? > 与 >,不是吗? 没有任何意义。
  • @Markus 不,这不是一个坏例子。这是不一样的。没有“扩展对象”的方法签名类型是 Comparable(不从对象继承)而不是所需的 Object。
【解决方案2】:

您可以对所有支持的类型使用工厂方法,并使构造函数私有/受保护。无论如何,你必须在构造函数中修复泛型类型,这样它才有意义,所以你可以这样编码:

public final class MyClass<T> {
    public static MyClass<Integer> newInstance(int i) {
        return new MyClass<Integer>(i);
    }
    public static MyClass<String> newInstance(String s) {
        return new MyClass<String>(s);
    }
    //More factory methods...

    protected MyClass(T obj) {
        //...
    }
}

或者如果你不想要构造函数参数,像这样: 公共最终类 MyClass { 公共静态 MyClass newIntegerInstance() { 返回新的 MyClass(); } //... }

正如 erickson 所说,无论如何,通用实现只能依赖于 Object,因此唯一的限制是,除了原始类型和 String 之外,您还可以为其他类型创建其他实现。

【讨论】:

    【解决方案3】:

    虽然泛型在这里不起作用,但具有NumberString 的派生类型的基类型可以。由于泛型类型无论如何都会被删除为Object,因此您放置在那里的任何功能都可以放在抽象基类中。您可能只需要子类上的特定于类型的访问器来获取值。

    另外,注意Number 类。它不限于装箱原始类型,任何人都可以扩展它——例如,BigInteger

    【讨论】:

      【解决方案4】:

      有趣的问题,让我有点困惑。然而显然这是不可能的。我尝试了几种不同的 hack,都没有真正奏效。

      【讨论】:

        【解决方案5】:

        也许您可以执行以下操作:

        1. 使MyClass&lt;T&gt; 成为一个包默认类,对其他组件不可见,或者至少只使用包默认ctors,这样它就不能在包之外扩展或实例化。
        2. MyClass&lt;T&gt;的包中创建两个公共类:
        MyNumericClass<T extends Number> extends MyClass<T>
        MyStringClass extends MyClass<String>
        

        这样,MyClass 的所有子类将被限制为使用 Number 子类或 String 参数化的子类。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-06
          • 1970-01-01
          • 2012-11-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多