Java泛型和专用构造函数

thk*_*ala 9 java generics constructor

(这可能是重复的,但我找不到它 - 随意指出来)

考虑以下Java类:

public class A<T0, T1> {
    public A(T0 t0, T1 t1) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

使用类似的东西很容易实例化这个类new A<Integer, String>(1, "X").

现在假设这个类的大多数实例都有一个String第二个类型参数,T1并且在构造函数调用中使用的这种类型的对象也非常标准.

如果 A没有使用泛型,那么常见的扩展将是没有第二个参数的额外构造函数:

public class A {
    public A(int t0, String t1) {
        ...
    }

    public A(int t0) {
        this(t0, new String("X"));
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,对于使用泛型的类来说,这似乎是不可能的 - 至少在没有强制转换的情况下:

    public A(T0 t0) {
        this(t0, (T1)(...));
    }
Run Code Online (Sandbox Code Playgroud)

原因?虽然这个构造函数只接受一个参数,但它仍然使用两个类型参数,并且无法知道该类用户提供的任何类型与构造函数中使用的默认值兼容的先验T1.

稍微优雅的解决方案涉及使用子类:

 public class B<T0> extends A<T0, String> {
     ...
 }
Run Code Online (Sandbox Code Playgroud)

但是这种方法强制了类层次结构中的另一个分支,而另一个类文件则基本上是样板代码.

  • 有没有办法声明一个强制一个或多个类型参数为特定类型的构造函数?与使用子类具有相同效果的东西,但没有麻烦?

  • 我对仿制药和/或我的设计的理解是否存在根本错误?或者这是一个有效的问题?

Tom*_*ine 6

最简单的方法就是添加静态创建方法.

public static <T0> A<T0,String> newThing(T0 t0) {
    return new A<T0,String>(t0, "X");
}
Run Code Online (Sandbox Code Playgroud)

(也许选择适合特定用途的名称.通常不需要new String("...").)

从Java SE 7开始,您可以使用钻石:

A<Thing,String> a = new A<>(thing);
Run Code Online (Sandbox Code Playgroud)