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

时间:2008-12-11 20:26:14

标签: java generics

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

  1. 其中一个数字原始包装类(LongIntegerFloatDouble
  2. String
  3. 我可以通过像这样的定义来满足第一个要求

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

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

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

    干杯, 唐

5 个答案:

答案 0 :(得分:11)

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

在一些可能感兴趣的相关注释中,如果要强制执行多个限制,它确实支持多个边界。以下是Java generics tutorial中提到的JDK的一个示例:

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

答案 1 :(得分:4)

您可以对所有受支持的类型使用工厂方法,并使构造函数为private / protected。你必须在构造函数中修改泛型类型,以便它有意义,所以你可能会像这样编码:

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 {         public static MyClass newIntegerInstance(){             返回新的MyClass();         }         // ...     }

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

答案 2 :(得分:2)

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

另外,请注意Number课程。它并不局限于装箱原始类型,因为任何人都可以扩展它 - 例如,BigInteger

答案 3 :(得分:0)

有趣的问题,它让我感到困惑。但显然这是不可能的。我尝试了几种不同的黑客,没有一种真正起作用。

答案 4 :(得分:0)

也许你可以做以下事情:

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

    这样,MyClass的所有子类都将限于那些使用Number子类或String进行参数化的子类。