【问题标题】:Java: compile-time resolution and "most specific method"Java:编译时解析和“最具体的方法”
【发布时间】:2011-08-29 01:19:06
【问题描述】:

如果您尝试在下面使用重载函数compute1()compute2()compute5(),它们会导致编译错误:

package com.example.test.reflect;

class JLS15Test2
{
    int compute1(Object o1, Integer i, Integer j)         { return 1; }
    int compute1(String s1, Integer i, int j)             { return 2; }

    int compute2(Object o1, Integer i, int j)             { return 3; }
    int compute2(String s1, Integer i, Integer j)         { return 4; }

    int compute3(Object o1, Integer i, int j)             { return 5; }
    int compute3(String s1, Integer i, int j)             { return 6; }

    int compute4(Object o1, Integer i, Integer j)         { return 7; }
    int compute4(String s1, Integer i, Integer j)         { return 8; }

    int compute5(Object o1, Integer i, Object j)          { return 9; }
    int compute5(String s1, Integer i, int j)             { return 10; }


    public static void main(String[] args) 
    {
        JLS15Test2 y = new JLS15Test2();

        // won't compile:
        // The method compute1(Object, Integer, Integer) is ambiguous 
        // for the type JLS15Test2
        // System.out.println(y.compute1("hi", 1, 1));

        // Neither will this (same reason)
        // System.out.println(y.compute2("hi", 1, 1));
        System.out.println(y.compute3("hi", 1, 1));
        System.out.println(y.compute4("hi", 1, 1));

        // neither will this (same reason)
        // System.out.println(y.compute5("hi", 1, 1));
    }
}

在阅读了 JLS 第 15.12 节之后,我想我明白了......在匹配重载方法的第 2 阶段(允许装箱/拆箱,没有可变参数)中,当确定“最具体的方法”时,JLS 说(实际上)最具体的方法是其形式参数是其他适用方法的子类型,并且原语和对象(例如intInteger)永远不是彼此的子类型。所以IntegerInteger 的子类型,intint 的子类型,但Integerint 与/r/t 子类型比较不兼容,所以compute1()/ compute2() 对有一个最具体的方法。

(而在compute3()compute4() 中,带有String 参数的方法比带有Object 参数的方法更具体,因此程序会打印6 和8。)

我的推理正确吗?

【问题讨论】:

    标签: java language-lawyer jls subtype


    【解决方案1】:

    是的,你的推理是正确的。

    【讨论】:

    • 接受了,但我希望看到一些额外的启示。
    【解决方案2】:

    如果您添加另一个只接受原始 int 和装箱 Integer 的方法,它能够解析哪个是正确调用的方法:

    int compute6(int i) { return 11;}
    int compute6(Integer i){return 12;}
    ...
    System.out.println(y.compute6(1));
    

    基于此,我想它与不同参数之间的交互有关,而不仅仅是单独的类型关系。

    【讨论】:

    • 不,在您的示例中,compute6(int) 首先匹配,因为 JLS 指定应首先定位方法,而不尝试使用自动装箱/拆箱,这是一个不同的问题。 (是的,这很令人困惑。最后,没有简单直观的方法来管理边缘情况;您只需要使用 JLS 作为最终答案。)
    • 啊,有趣。不知道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-26
    • 2012-02-29
    • 2011-02-24
    • 1970-01-01
    相关资源
    最近更新 更多