【问题标题】:Java class has 2 methods with the same function signature but different return typesJava 类有 2 个具有相同函数签名但返回类型不同的方法
【发布时间】:2016-07-21 04:54:27
【问题描述】:

AFAIK 不可能有具有相同调用签名的方法。然而:

$ javap -public java.time.LocalTime  | grep "minus" | grep "Temporal" | grep -v "long"
    public java.time.LocalTime minus(java.time.temporal.TemporalAmount);
    public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);

这些清楚地显示了具有相同调用签名的多个方法。

  1. Java 如何解析函数调用?
  2. 为什么会有多个函数?

编辑:通过只保留相关位来简化问题。

【问题讨论】:

  • 你确定这些是同一个类的方法吗?
  • 这是javap 的输出 - 所以我认为它们是同一类的方法。如果您查看javap -public java.lang.StringBuilder - 它清楚地表明它们属于同一类(除非我不知道javap 的某些行为)
  • 大家发帖说这些方法只是重载了,请仔细看javap的输出。存在具有完全相同参数的方法对,例如public java.time.LocalTime minus(java.time.temporal.TemporalAmount);public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);。这不仅仅是超载;重载不允许这样做。
  • java.time.LocalTime 只有public java.time.LocalTime minus(java.time.temporal.TemporalAmount);。另一种可能是合成桥接方法或类似方法。拆解看了吗?
  • 为了澄清这个问题,我建议删除关于StringBuilder的部分,这似乎让人认为你在问方法重载

标签: java overloading javap


【解决方案1】:

这是由于 Java 如何实现协变返回类型。 java.time.LocalTime 有一个带有签名的minus 方法

LocalTime minus(TemporalAmount amountToSubtract)

但是这个方法实现了一个来自java.time.temporal.Temporal的带有签名的接口方法

Temporal minus(TemporalAmount amount)

由于协变返回类型,这是允许的,但由于方法查找的工作方式,在运行时查找返回 Temporal 的方法不会找到返回 LocalTime 的方法。因此,编译器创建了一个具有相同签名但返回Temporal普通禁止 方法。此方法调用返回LocalTime 的版本。在运行时,需要Temporal 返回类型的调用会找到桥接方法,一切正常。

这种桥接方法通常是不可见的,但它会显示在 javap 输出中,导致您目前的困惑。

来源:http://www.artima.com/weblogs/viewpost.jsp?thread=354443

这是来自StringBuilder 的桥接方法之一的javap -c 反汇编,显示了它如何调用具有相同签名但返回类型更具体的方法:

  public java.lang.Appendable append(java.lang.CharSequence) throws java.io.IOException;
    Code:
       0: aload_0       
       1: aload_1       
       2: invokevirtual #6                  // Method append:(Ljava/lang/CharSequence;)Ljava/lang/StringBuilder;
       5: areturn       

【讨论】:

  • 这阐明了正在发生的事情。我不知道桥接方法的存在。谢谢!
【解决方案2】:

Java forbids two methods in the same class or interface with the same name and signature.

但是,两个不同的类、接口或枚举可以具有相同的方法签名;例如,这是有效的:

public java.time.LocalTime minus(long, java.time.temporal.TemporalUnit);
public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);

一个minus方法属于LocalTime类,另一个属于Temporal接口。由于LocalTime implements Temporal,这两者之间必须签名匹配,否则合同不履行,这将导致编译错误。

【讨论】:

  • 您正在查看错误的方法对。以public java.time.LocalTime minus(java.time.temporal.TemporalAmount);public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount); 为例。
  • @user2357112:那么完全没有问题。这是两个不同的类。
  • 可能,但是为什么它们都出现在javapjava.time.LocalTime 输出中?
  • 我不明白 - 他们是 2 个不同的班级吗?它们是同一个类中具有相同名称和具有不同返回值的相同参数列表的 2 个方法。根据重载规则,返回值不是调用签名的一部分,因此这两种方法不允许共存。
  • @SaurabhDas:TemporalLocalTime 的名称不同。 The API makes this relationship apparent.
【解决方案3】:

Temporal 是由LocalTime 实现的接口,因此它们的方法具有相同的签名 如果你想检查试试这个

javap java.time.LocalTime

【讨论】:

    猜你喜欢
    • 2013-02-28
    • 1970-01-01
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-09
    相关资源
    最近更新 更多