有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java类。使用方法重载强制转换为最特定的

我有一个这样的代码

function a(Object m) {} 
function a(BasicDbObject) {}
function a(TypeA) {}
function a(TypeB) {}
function a(TypeC) {}
.....
function b(Object m) {
    // Some function using Java reflection to determine class of Object m
    Class X = c(m); 
    a(X.cast(m));

}

问题就在这里。它总是执行a(Object m)而不是a(BasicDbObject m),即使它是BasicDbObject

我的最终目标是执行与传递的对象最接近的函数


共 (3) 个答案

  1. # 1 楼答案

    function a(Object m) {}
    function a(BasicDbObject) {}

    当方法被重载时,可能无法直观地知道为任何参数集调用的方法,因为与重写方法的情况不同,被调用的方法重载是在编译时(即静态)而不是在运行时(即动态)确定的。这种行为令人困惑,因为重写方法更常见,这设置了我们对方法调用的期望

    有一些规则可以使方法重载尽可能可靠和简单。这些都在有效的Java中得到了很好的列举(J.Bloch,第二版和第三版)

    您的情况变得复杂,因为:

    • 有两个重载具有相同数量的参数,其类型没有根本不同。。。而且
    • 重载的行为显然取决于参数的类型(如果行为相同,则只需将一个重载转发给另一个)

    当出现这种情况时,您应该尝试通过为重载指定不同的名称来纠正它。这样做应该总是可能的,这样做通常会提高代码的清晰度和可维护性

    如果出于任何原因无法执行此操作,那么最好的解决方法是使用一个方法替换重载,该方法接受最通用的参数类型,并根据传递的参数的最特定类型调用帮助器方法

    因此,您可以通过使用

    public Function a(Object m) {
    
        if (m instanceof BasicDbObject) return doDbObject(m);
        if (m instanceof OtherDbObject) return doOtherDbObject(m);
    
        return doGenericObject(m);
    }
    

    请注意,当Java在语言中采用模式匹配时,这不是您将使用的代码。还要注意,这段代码的作用是为重载指定不同的名称,但是在运行时使用instanceof比较而不是在编译时使用不同的名称来选择不同的方法

    TLDR;如果在参数类型没有(或可能没有)根本不同的情况下执行方法重载,那么最好不要重载并使用不同的方法名称

  2. # 2 楼答案

    您所尝试的无法完成,因为Java是静态类型的,方法重载是在编译时而不是运行时解决的

    在运行时解决重载的唯一方法是使用反射完成方法调用本身

  3. # 3 楼答案

    严重的不回答:错误的方法

    您不需要使用反射来动态确定类型,然后确定要调用哪个重载方法

    相反,使用多态性。意思是:不要重载,而是覆盖

    请放心:让“反思”工作很难。使其正确稳健稳定是一场极具挑战性的艰苦战斗

    您基本上想要发明自己的个人动态分派实现。除非你有非常紧迫的理由这样做,否则这是一个可怕的想法。因为你很可能会弄错。很多次。即使您的代码正在工作,以后在生产中发生不可预见的事情时,也会发生许多事件

    正如所说:不要这样做。不要与语言抗争,而是使用语言为您提供的方法来解决这些问题:类的继承树和多态方法。然后让JVM决定调用哪个方法。最有可能的是,JVM会做得比您将提出的更好