Java形式类型参数定义(泛型)

8
我想定义一个通用类型,其实际类型参数只能是以下之一:
  1. 数值原始包装类之一(LongIntegerFloatDouble
  2. String
我可以通过以下定义来满足第一个要求:
public final class MyClass<T extends Number> {
    // Implementation omitted
}

但我不知道如何同时满足它们两个。 我怀疑这实际上是不可能的,因为据我所知,在定义形式类型参数时没有办法指定“或”语义,尽管您可以使用如下定义指定“和”语义:

public final class MyClass<T extends Runnable & Serializable > {
    // Implementation omitted
}

欢呼, 唐

类型擦除会将其放回到对象(如果存在的话)。 - Loki
5个回答

11

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

相关的一点可能对某些人有兴趣,如果你想强制执行多个限制,它确实支持多个边界。以下是Java generics tutorial中提到的JDK示例:

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

1
这不是个糟糕的例子吗(我看它是来自 SUN,而不是你的)?<T extends Object & Comparable<? super T>> 和 <T extends Comparable<? super T>> 是一样的,对吧?<T extends Object> 没有任何意义。 - Markus
@Markus 不,这不是一个糟糕的例子。它们并不相同。如果没有“extends Object”方法签名类型,则Comparable(它不继承自Object)而不是所需的Object。 - McTrafik

4

您可以使用工厂方法来支持所有类型,并将构造函数设置为私有/受保护。无论如何,您都必须修复构造函数中的通用类型,以便使其更有意义,因此您可能可以像这样编写代码:

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) {
        //...
    }
}

如果您不想使用构造函数参数,可以像这样实现:

public final class MyClass {
    public static MyClass newIntegerInstance() {
        return new MyClass();
    }
    //...
}

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


2
虽然泛型在这里不适用,但是一个带有派生类型NumberString的基本类型可以使用。由于泛型类型将被擦除为Object,因此您可以在抽象基类中放置任何功能。您可能只需要在子类中使用特定类型的访问器来获取值。
此外,请注意Number类。它不仅限于装箱原始类型,任何人都可以扩展它,例如BigInteger

0

也许你可以按照以下步骤操作:

  1. MyClass<T> 设为默认包级别类,对其他组件不可见,或者至少只有默认包级别的构造函数,这样它就无法在包外被扩展或实例化。
  2. MyClass<T> 的包中创建两个公共类:
MyNumericClass<T extends Number> extends MyClass<T>
MyStringClass extends MyClass<String>

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


0

有趣的问题,让我有些困惑。然而,显然这是不可能的。我尝试了几种不同的黑客方法,但都没有真正奏效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接