Java通用方法-如何使其调用专用方法

Java通用方法-如何使其调用专用方法,java,generics,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

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);
  }
}
X类{
公共无效pr(对象s){
System.out.println(“对象”);
}
公共无效pr(字符串s){
System.out.println(“字符串”);
}
公开作废go(TX){
这是pr(x);
}
公共静态void main(字符串[]args){
String v=“hello”;
X=新的X();
//两者都打印“对象”,而我想要“字符串”
x、 go(v);
x、 go(v);
}
}
我希望go()调用pr(String)。但无论我做什么,pr(Object)都被称为

上面的示例仅用于演示,实际应用要复杂得多

提前感谢。

试试这个:

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);
      }
    }
X类{
公共无效pr(对象s){
System.out.println(“对象”);
}
公共无效pr(字符串s){
System.out.println(“字符串”);
}
公开作废go(TX){
if(字符串的x实例){
这个.pr((字符串)x);
}否则{
这是pr(x);
}
}
公共静态void main(字符串[]args){
String v=“hello”;
X=新的X();
//两者都打印“对象”,而我想要“字符串”
x、 go(v);
x、 go(新对象());
//x.go(v);
}
}

问题是字符串也是一个对象,所以您需要检查它是否是其他对象,这可以通过
instanceof

Java generic是编译时帮助器来完成,Java编译器会去除泛型的类型信息

但你能做到

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

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

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

public <T> void go(T x) {
    if (x instanceof String)
        pr((String)x);
    else
        pr(x);
}
实际上,在这个上下文中,您甚至不需要在
go
中使用泛型类型,所以您可以将其重写为

    public void go(CanPR x) {
        x.pr();
    }
不幸的是,你所描述的是不可能的,因为 运行时T的类型擦除被视为对象,因此选择pr(对象) 在这里


不可能。我想,这就是答案。只需在谷歌上搜索“类型擦除”。这里有很多关于它的问题。编译器将该方法编译为
公共void go(Object x)
。因此,声明的
x
类型是
Object
。此外,我们需要检查
x!=in
go
方法中的null
,否则它将抛出一个
MethodDumbuityException
。正确,代码中没有处理方法,但请确保它是正确的needed@Rp-这里怎么可能抛出任何异常?如果x==null,则使用s==null调用pr(对象s)。我甚至没听说过这件事exception@kamil09875:您是对的,没有这样的异常,但是如果重载参数不在继承层次结构中,它会抛出类似
java.lang的错误:未解决的编译问题:方法不明确?
。糟糕的是,这里它不会抛出那个异常,因为String是Object的一个子类。如果为空,则将调用带参数对象的方法。@Rp-只有一种情况下方法可能不明确,即显式调用方法(空);当您调用方法(var)时,var是一个类型已知的变量,不可能出现歧义。我试着理解你的想法,你能给我一个可能发生这种情况的小例子吗?:)谢谢你的回答。这就解释了,我学习了类型擦除。不幸的是,“instanceof”模式对我不起作用,因为这个东西可以处理的类太多了。我会考虑其他解决方案。@MarcinZukowski不幸的是,这是Java,在其早期版本中,向后兼容性非常重要,因此编译后的cone需要能够在不了解泛型类型的JVM的较旧版本上运行
,因此当时需要进行类型擦除,现在,它是语言的一部分,没有人想删除:/
    public void go(CanPR x) {
        x.pr();
    }