当前位置: 首页 > 知识库问答 >
问题:

为什么在这段代码中会出现歧义错误?

郎成弘
2023-03-14

假设我们有以下三个类:

class A { }
class B extends A { }

public class App {
    static void f(int i, A a) { }
    static void f(float j, B b) { }
   
    static public void main() {
        int i = 0;
        B b = new B();
        App.f(i, b);
    }
}

这将产生以下错误:

App.java:11: error: reference to f is ambiguous
        App.f(i, b);
           ^
  both method f(int,A) in App and method f(float,B) in App match
1 error

既然i是整数,为什么它不选择类型f(int,A)

共有2个答案

漆雕育
2023-03-14

请注意,对于在java中调用重载方法:

原语类型的优先级顺序:

同类型

引用类型的优先级顺序:

同类型

说明:

    // you have here a method who accept an int = same Type 
    //  f(int i, A a) { } and this method can accept the other parameter 
    //  because B is a subclass of A
    int i = 0;
    // But You have a method who accept a B reference = same Type 
    // f(float j, B b) { } and this method can accept the other parameter 
    // because float is actually a supertype of int as mentionned by Sweeper
    B b = new B();

 // So calling the method with an int and a B reference 
 // will confuse the compiler because both of the two methods
 // accept one parameter as "same type" 
 // and can accept the other parameter
    App.f(i, b);
赫连法
2023-03-14

它模棱两可是因为两个原因:

  • 两种过载都适用,并且
  • 两个重载都不比另一个更具体

注意,f(int,A)重载和f(float,B)重载都可以用参数(i,B)调用,因为存在从intfloat的隐式转换,以及从BA的隐式转换。

当存在多个适用方法时会发生什么情况?Java应该选择最具体的方法。语言规范的§15.12.2.5对此进行了描述。事实证明,这些重载中的一个并不是比另一个更具体。

对于带有参数表达式e1,...,ek的调用,如果以下任何一个为真,一个适用的方法m1比另一个适用的方法m2更具体:

>

  • m2是通用的[...]

    m1和m2的形式参数类型为严格的,m1和m2的形式参数类型为不适用的。。。,Sn和m2具有形式参数类型T1。。。,对于所有i(1),对于参数ei,类型Si比Ti更具体≤ 我≤ n、 n=k)。

    m2不是通用的,并且m1和m2可以通过html" target="_blank">变量属性调用[...]

    只有第二点适用于f的两个重载。要使其中一个重载比另一个重载更具体,一个重载的每个参数类型必须比另一个重载中的相应参数类型更具体。

    对于任何表达式,类型S比类型T更具体,如果S

    请注意“

    语言规范继续讨论最大限度地特定的方法,这在这里并不真正适用于f。最后,它说:

    否则,方法调用是不明确的,并且会发生编译时错误。

    static void f(int x) {}
    static void f(float x) {}
    

    当使用int调用时,不会产生歧义,因为int重载更为具体。

    static void f(int x, B a) {}
    static void f(float x, A a) {}
    

    当使用参数类型(int, A)调用时不会有歧义,因为(int, B)重载更具体。

    static void f(int x, A a) {}
    static void f(float x, A a) {}
    

    当使用参数类型(int, A)调用时不会有歧义,因为(int, A)重载更具体。请注意,子类型关系是反射性的(即AA的子类型)。

  •  类似资料:
    • 问题内容: 考虑以下Java源代码: 该是。 为什么该语句有时会抛出? 谢谢。 问题答案: 线程安全 如果您的代码是多线程的,则有可能。例如: 如果在语句执行之后(但在循环之前)立即将另一个线程设置为,则您将获得一个。通过使用访问器(与延迟初始化结合使用)可以避免这种情况。 另外,如其他人所提到的,如果可能,请避免使用有利于泛型的此类循环构造。有关详细信息,请参见其他答案。 配件提供保护 如果始终

    • 令牌“if”的语法错误(应在此令牌之后 谢谢你的建议!

    • 我正在使用这个卡佩吉斯节点应用程序:https://github.com/narainsagar/node-casperjs-aws-lambda 我已经让我的代码在本地工作,并上传到Lambda,但我需要将我的代码包装在里面exports.handler这样我就可以从API网关向函数传递数据。(我已经对不使用这个应用程序的其他函数这样做了。)当我将代码放在里面时exports.handler失败

    • 我的代码: 错误: 第8行的错误1064(42000):您的SQL语法中有一个错误;请查看与您的MySQL服务器版本相对应的手册,以便在第9行')'附近使用正确的语法

    • 这段代码是我用Java Swing制作的Tic-Tac-Toe程序的一部分。为什么在添加用于添加按钮的for语句时返回NullPointerException?

    • 我想了解为什么一段代码不会抛出NullPointerException。 请考虑以下代码: 方法被重复调用,同时以下代码在单独的线程中运行: 只有一个实例。 从不引发NullPointerException。 但是,当方法暂停时,即使暂停0毫秒,也会按预期引发NullPointerException: 我的理解是,在理论上,在检查和调用之间存在竞争条件。在实践中,如果不引入暂停(即从后续方法调用中