请注意,所有代码都是简化示例,目的是仅传达我的问题的核心思想。经过一点编辑后,它应该全部编译并运行。

我有几个都实现一个公共接口的类。

public interface Inter{}
public class Inter1 implements Inter{}
public class Inter2 implements Inter{}

在一个单独的类中,我有一个Inter类型的列表,该列表用于根据用户输入存储和删除Inter1和Inter2类型。
java.util.ArrayList<Inter> inters = new java.util.ArrayList<Inter>();

我也有一系列重载方法,这些方法处理每个实现之间的交互方式,以及2个“Inter”的默认实现。
void doSomething(Inter in1, Inter in2){
    System.out.println("Inter/Inter");
}
void doSomething(Inter1 in1, Inter1 in2){
    System.out.println("Inter1/Inter11");
}
void doSomething(Inter2 in1, Inter1 in2){
    System.out.println("Inter2/Inter1");
}

定期调用这些方法,如下所示:
for(int i = 0; i < inters.size() - 1; i++){
    for(int o = i+1; o < inters.size(); o++){
        Inter in1 = inters.get(i);    Inter in2 = inters.get(o);

        doSomething(in1.getClass().cast(in1), in2.getClass().cast(in2));

        System.out.println("Class 1: " + in1.getClass().getName());
        System.out.println("Class 2: " + in2.getClass().getName());
    }
}

一个示例输出是:
Inter/Inter
Class 1: Inter
Class 2: Inter
Inter/Inter
Class 1: Inter
Class 2: Inter1
Inter/Inter
Class 1: Inter1
Class 2: Inter1

从输出看,很明显,即使在应调用其他方法的情况下,也会调用doSomething(Inter in1,Inter in2)。有趣的是,输出的类名称是正确的。

当在运行时使用反射确定类类型时,为什么Java有静态方法重载?
有什么办法让Java做到这一点?我知道我可以使用反射,Class.getMethod()和method.invoke()来获得所需的结果,但是使用casting这样做会更加整洁。

我意识到以前曾问过有关类似概念的问题,但是尽管所有答案都提供了信息,但没有一个让我满意。
双重调度看起来很可行,但这将意味着要重做许多代码,因为我经常使用这种类型的东西。

最佳答案

在我看来,我们正在谈论发生了什么事:

doSomething(in1.getClass().cast(in1), in2.getClass().cast(in2));

让您惊讶的是,输出的类型始终是Inter,您似乎对这里发生的事情有些困惑。特别是,您似乎认为in1.getClass().cast(in1)in2.getClass().cast(in2)应该由于不同的运行时类型而导致不同的重载。但是,这是错误的。

方法重载解析是静态发生的。这意味着它是基于方法的两个参数的声明类型而发生的。由于in1in2都声明为Inter,因此选择的方法显然是void doSomething(Inter in1, Inter in2)

这里的要点是in1被声明为Inter。这意味着,就静态分析而言,in1.getClass()本质上与Inter.class相同-getClass仅返回Class<? extends Inter>。因此,强制转换是无用的,而且您永远只会得到第一个重载。

08-26 06:10