为了账号安全,请及时绑定邮箱和手机立即绑定

Java Class.cast 到最具体的方法重载

Java Class.cast 到最具体的方法重载

子衿沉夜 2021-06-08 17:57:41
我有一个看起来像这样的代码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 回答

?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

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

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

有一些规则可以尽可能健壮和简单地进行方法重载。这些都在 Effective Java(J. Bloch,第 2 和第 3 版)中很好地列举出来。

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

  • 您有两个具有相同数量参数的重载,它们的类型并没有完全不同......和......

  • 重载的行为显然取决于参数的类型(如果行为相同,那么您只需将一个重载转发到另一个)

出现这种情况时,您应该尝试通过给重载不同的名称来纠正它。应该始终可以这样做,并且这样做通常可以提高代码的清晰度和可维护性。

如果由于任何原因无法做到这一点,那么最好的解决方法是用一种方法替换重载,该方法接受最通用的参数类型,并根据传递的参数的最具体类型调用辅助方法。

因此,除了上述之外,您还可以通过使用...

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;如果您在参数类型没有(或可能没有)完全不同的情况下进行方法重载,那么最好不要重载并使用不同的方法名称。


查看完整回答
反对 回复 2021-06-23
?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

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

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


查看完整回答
反对 回复 2021-06-23
?
茅侃侃

TA贡献1842条经验 获得超21个赞

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

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

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

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

您基本上想发明自己的个人动态调度实现。除非你有非常迫切的理由这样做,否则这是一个糟糕的主意。因为很可能你会弄错。很多很多次。即使您的代码正在运行,但当生产中发生不可预见的事情时,稍后也会发生许多事件。

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


查看完整回答
反对 回复 2021-06-23
  • 3 回答
  • 0 关注
  • 203 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信