我想知道在Java中专门化泛型类型的选项是什么,即在模板化的类中对某些类型进行特定的覆盖.
在我的例子中,我是一个泛型类(类型为T)通常返回null,但返回""(空字符串),当T是String类型时,或者当它是Integer类型时返回0(零)等.
仅提供方法的类型特定重载会产生"方法不明确"错误:
例如:
public class Hacking {
public static void main(String[] args) {
Bar<Integer> barInt = new Bar<Integer>();
Bar<String> barString = new Bar<String>();
// OK, returns null
System.out.println(barInt.get(new Integer(4)));
// ERROR: The method get(String) is ambiguous for the type Bar<String>
System.out.println(barString.get(new String("foo")));
}
public static class Bar<T> {
public T get(T x) {
return null;
}
public String get(String x) {
return "";
}
}
}
Run Code Online (Sandbox Code Playgroud)
是使用特定类型子类化泛型类的唯一选项(请参阅以下示例中的StringBar?
public static void main(String[] args) {
Bar<Integer> barInt = new Bar<Integer>();
StringBar barString2 = new StringBar();
// OK, returns null
System.out.println(barInt.get());
// OK, returns ""
System.out.println(barString2.get());
}
public static class Bar<T> {
public T get() {
return null;
}
}
public static class StringBar extends Bar<String> {
public String get() {
return "";
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是唯一的方法,必须为我想要专门化的每种类型创建子类而不是Bar类中的get()重载,这有点痛苦.
我猜我可以检查Bar.get()方法中的instanceof,例如T get(T t){if(t instanceof String)return""; if(t instanceof Integer)返回0; else返回null; }
但是,我被教会在可能的情况下避免使用instanceof并使用多态.
Ash*_*Ash 13
考虑到所有事情,共识似乎是问题中提到的StringBar方法方法是唯一的方法.
public static class StringBar extends Bar<String> {
public String get() {
return "";
}
}
Run Code Online (Sandbox Code Playgroud)
在这方面,Java中的泛型与C ++中的模板有很大不同。不可能编写通用版本的特定版本来针对特定情况做一些不同的事情,就像C ++可以做到的那样。在运行时也无法确定T是什么-这是因为信息没有传递到字节码(目标代码)中,因此在运行时甚至不存在。这是由于所谓的“类型擦除”。
BarString和BarInt将是这样做的明显方式,但是您可以进行一些改进。例如,您可以编写一个通用Bar来涵盖常见情况,然后编写特殊的BarString和BarInt来实现特殊情况。确保只能通过工厂创建实例,该工厂采用要处理的对象的类:
class Bar<T> {
class BarString extends Bar<String> {
// specialist code goes here
}
static Bar<T> createBar(Class<T> clazz) {
if (clazz==String.class) {
return new BarString();
} else {
return new Bar<T>;
}
Run Code Online (Sandbox Code Playgroud)
那可能不会编译,但是我没有时间确定确切的语法。它确实说明了原理。