可能的Java泛型(模板)专业化(覆盖具有特定类型的模板类型)

Ash*_*Ash 25 java generics

我想知道在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)

  • 我已经创建并接受了我自己的答案,因为虽然其他答案有些正确并得出了这个结论,但它们都含有误导性的观点或以某种方式误解了这个问题. (2认同)

DJC*_*rth 5

在这方面,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)

那可能不会编译,但是我没有时间确定确切的语法。它确实说明了原理。