【问题标题】:Java overloading with generic type parameter使用泛型类型参数的 Java 重载
【发布时间】:2017-08-17 07:33:33
【问题描述】:

我在一个类中有以下方法:

void delete(ClassA a) {
  //....
}

void delete(ClassB b) {
  //...
}

void delete(List<ClassA> list) {
  for (ClassA a: list) {
    delete(a);
  }
}

void delete(List<ClassB> list) {
  for (ClassB b: list){
    delete(b);
  }
}

前两种方法的重载工作正常。但是第三种方法和第四种方法有冲突。

是否可以用一种方法替换它们?我尝试了以下方法,不正确:

void delete(List<? extends Object> list){
  for (Object o: list){
     delete((o.getClass())o);
  }
}

如何在运行时检测列表中实例的类类型并调用相应的方法?

【问题讨论】:

  • 使用instanceof检查对象

标签: java generics overloading


【解决方案1】:

重载在编译时解决,因此您不能依赖运行时类型。

您可以做的是使用 instanceof 检查运行时类型并显式转换为相关类型:

void delete(List<? extends Object> list){
    for (Object o: list) {
        if (o instanceof ClassA) {
            delete((ClassA) o);
        } else if (o instanceof ClassB) {
            delete((ClassB) o);
        }
    }
}

【讨论】:

  • 难道不能只说“将 o 转换为它是实例的任何类”吗?没有明确地将其转换为该类?
  • @ArianHosseinzadeh 不,编译器必须知道传递给delete 的参数的编译时类型才能确定应该调用哪个重载方法。
【解决方案2】:

您尝试使用不同的实现来删除 List&lt;ClassA&gt;List&lt;ClassB&gt;。您可以在 Java 中执行此操作,但不能使用相同的方法名称。

因此,您可以拥有一个deleteAList(List&lt;ClassA&gt; aList) 和一个deleteBList(List&lt;ClassB&gt; bList)

从技术上讲,重载意味着不同的方法共享相同的基名,但具有不同的参数类型,因此编译器知道要调用哪个方法。

或者换一种说法,有效的方法名是由你创建的名字加上参数类型组成的。而且这个概念是在引入泛型之前定义的,所以它只看到delete(List list),而忽略了您添加到List 的泛型类型参数。因此,您有两个具有相同有效方法名称的方法,这就是编译器所抱怨的。

所以,通过使方法基名称不同来帮助编译器,一切正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多