【问题标题】:Two methods with the same signature, why it works具有相同签名的两种方法,为什么它有效
【发布时间】:2013-05-01 08:51:44
【问题描述】:

我有一个类将字符串视为一个集合。这是该类中的两个方法:

@Override
public <B> IndexedSeq<B> map(final Function1<? super Character, B> function) {...}

public RichString map(final Function1<? super Character, Character> function) {...}

只是方法中的签名与我的问题有关。 现在,Eclipse 确实发出警告,表明这两种方法具有相同的擦除。但它仍然允许我创建它们,并且它们按预期工作:每当我提供一个将字符转换为字符的函数时,都会返回一个 RichString,正如我想要的那样。

我的问题是为什么它会起作用,因为在运行时没有关于泛型类型的信息,并且方法的返回不是方法签名的一部分?当我调用它们时,JVM 怎么知道要调用这两个方法中的哪一个?

编辑:

我认为,在擦除之后,这两种方法将具有以下签名:

@Override
public IndexedSeq map(final Function1<Object, Object> function) {...}

public RichString map(final Function1<Object, Object> function) {...}

这将使它们仅在返回类型上有所不同。

【问题讨论】:

    标签: java generics methods jvm


    【解决方案1】:

    你是正确的,这不应该编译。 Java 6 中有一个错误导致这样的代码被错误地接受:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6182950

    【讨论】:

    • 我不会将您的答案标记为正确答案,因为我相信这两种方法会退回到相同的擦除。而且,在 JDK 7 中,这种代码不再编译是有道理的。
    • 我真的很高兴是这种情况(尽管对我的代表有影响;-))。我不喜欢不知道为什么String foo(Map&lt;Character, Character&gt; m) 会擦除到String foo(Map m)(众所周知),但String &lt;B&gt; foo(Map&lt;Character, B&gt; m) 没有擦除到String foo(Map m)。我认为在方法参数声明中使用类型参数作为类型参数有点奇怪。发现不是这样,我松了一口气。 :-)
    【解决方案2】:
    1. 运行时在类/方法签名方面有大量关于泛型类型的信息,但在对象实例方面却没有。第二个重载的整个签名可能可以通过反射来检索。
    2. 没关系,因为无论如何方法重载都是在编译时解决的。歧义可能在那里得到解决,例如由编译器考虑到Function&lt;Character, Character&gt; 类型参数的第二个重载“更具体”。

    【讨论】:

    • 是的,我相信编译器会知道调用哪一个。但是当它做字节码的时候,这两种方法不会有相同的擦除,导致错误吗?
    • @ViniciusSeufitele 我认为第一个应该删除到IndexedSeq&lt;Object&gt; map(Function1&lt;Object, Object&gt;),第二个应该删除到RichString map(Function1&lt;Object, Character&gt;)。也就是说,Java 编译器向我抱怨擦除,所以我不确定你所说的代码工作是什么意思。
    • @ViniciusSeufitele 嗯。它在 JDK6 下编译,但不在 JDK7 下编译。似乎语言中的某些东西已更改以解释这一点。
    • @ViniciusSeufitele 如果这是一个警告,那么当您升级到 JDK7 时,它很有可能会变成一个错误。显然,关于擦除规则的某事发生了变化,或者编译器在之前接受错误代码的地方变得更加严格。我不确定您是否会从实际 Java 编译器团队之外的人那里得到结论性的解释,看看这是一个已经很神秘的机制的细微差别。
    • @ViniciusSeufitele 对于它的价值,用javap 戳类表明来自签名的所有信息都存在于字节码中。 (擦除并不真正意味着人们认为它意味着什么 - 它并没有剥离尖括号之间的所有内容。)
    猜你喜欢
    • 2010-12-28
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    相关资源
    最近更新 更多