Java泛型方法 - 如何使其调用专用方法

时间:2014-08-26 17:52:19

标签: java generics

Java中的泛型方法是否可以根据输入的类型调用特定的其他方法?

我尝试了以下示例,希望能够代表问题。

class X {
  public void pr(Object s) {
      System.out.println("Object");
  }

  public void pr(String s) {
      System.out.println("String");
  }

  public <T> void go(T x) {
      this.pr(x);
  }

  public static void main(String[] args) {
    String v = "hello";
    X x = new X();

    // Both print "Object", while I want "String"
    x.go(v);
    x.<String>go(v);
  }
}

我希望go()调用pr(String)。但无论我做什么,都会调用pr(Object)。

以上示例仅供演示,实际应用要复杂得多。

提前致谢。

4 个答案:

答案 0 :(得分:5)

不幸的是,由于类型擦除,您所描述的内容是不可能的,因此在运行时T被视为Object,因此在此选择pr(Object)

其中一个可能的解决方案是手动测试传递数据的类型并调用正确的方法,而不需要像

那样进行投射
public <T> void go(T x) {
    if (x instanceof String)
        pr((String)x);
    else
        pr(x);
}

但是如果您可以编辑类的代码,您将传递给go方法,那么首选的解决方案是在每个方法中添加/实现pr方法,以便您可以使用多态来调用它们:

interface CanPR{
    void pr();
}

class Foo implements CanPR{
    @Override
    public void pr() {
        System.out.println("pr from Foo");
    }
}

class Bar implements CanPR{
    @Override
    public void pr() {
        System.out.println("pr from Bar");
    }
}


class X {

    public <T extends CanPR> void go(T x) {
        x.pr();
    }

    public static void main(String[] args) {
        CanPR a = new Foo();
        CanPR b = new Bar();

        X x = new X();

        x.go(a); //prints: pr from Foo
        x.go(b); //prints: pr from Bar
    }
}

实际上在这种情况下,您甚至不需要go中的泛型类型,因此您可以将其重写为

    public void go(CanPR x) {
        x.pr();
    }

答案 1 :(得分:3)

试试这个:

class X {
      public void pr(Object s) {
          System.out.println("Object");
      }

      public void pr(String s) {
          System.out.println("String");
      }

      public <T> void go(T x) {
          if(x instanceof String){
              this.pr((String)x);
          } else {
              this.pr(x);
          }
      }

      public static void main(String[] args) {
        String v = "hello";
        X x = new X();

        // Both print "Object", while I want "String"
        x.go(v);
        x.go(new Object());
//      x.<String>go(v);
      }
    }

问题是String也是一个Object,所以你需要检查它是否是其他东西,这可以用instanceof来完成。

答案 2 :(得分:3)

Java generic是编译时助手,java编译器为泛型带走了类型信息。

但你可以做到

if (x instanceof String) {
  this.pr( (String) x );
}

答案 3 :(得分:0)

  

不幸的是,你所描述的是不可能的,因为   运行时类型擦除T被视为对象,因此选择了pr(Object)   这里。

不可能。我想,答案就是这样。看看here