gpt4 book ai didi

java - 当传递参数给方法在 Java 中变得模棱两可?

转载 作者:行者123 更新时间:2023-11-30 10:33:46 26 4
gpt4 key购买 nike

当方法重载完成后,我知道我们只能创建具有相同名称的方法,前提是它们的方法签名不同。

class Demo{
public static void myMethod(int y, double x){}
public static void myMethod(double x,int y){}

public static void main(String args[]){
byte b=10;
myMethod(b,b);
}
}

上面显示的代码给出了一个错误,说 error: reference to myMethod is ambiguous出现这个问题是因为byte值自动转换后可以赋给int和double两种类型,不知道该传给哪个方法对不对?如果我错了请纠正我..

我尝试了以下程序。我以为这也会报错,但编译没有报错

class MyClass{
public static void myMethod(int i){
System.out.println("myMethod1(int)");
}
public static void myMethod(double a){
System.out.println("myMethod2(int)");
}
}

class Demo{
public static void main(String args[]){
MyClass.myMethod(100);
}
}

我认为它也会给出与之前相同的错误,但这给出的输出为 myMethod(int)... 所以我假设因为它有一个可以传递 int 的完美匹配方法值,它不会给出错误..

但是如果我对上面的第二个程序进行以下更改,为什么它不会报错呢??

class MyClass{
public static void myMethod(int i){
System.out.println("myMethod1(int)");
}
public static void myMethod(double a){
System.out.println("myMethod2(int)");
}
}

class Demo{
public static void main(String args[]){
byte b=10;
MyClass.myMethod(b);
}
}

byte可以自动转成int和double对吗?输出为 myMethod(int)..这不应该让编译器感到困惑并给出错误 reference to myMethod is ambiguous 吗??

最佳答案

我不会指定和详细说明编译器用来决定必须调用哪个方法的所有规则,因为它包含其他条件。我将只关注您的问题的方法参数标准。

15.12.2.5. Choosing the Most Specific Method ,你有一个宝贵的信息:

非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个方法而不会出现编译时类型错误,则一个方法比另一个方法更具体。

在您的示例中,这里是应该回答您的问题的 JLS 部分:

One fixed-arity member method named m is more specific than another member method of the same name and arity if all of the following conditions hold:

  • The declared types of the parameters of the first member method are T1, ..., Tn.

  • The declared types of the parameters of the other method are U1, ..., Un.

  • If the second method is generic, then let R1 ... Rp (p ≥ 1) be its type parameters, let Bl be the declared bound of Rl (1 ≤ l ≤ p), let A1 ... Ap be the type arguments inferred (§15.12.2.7) for this invocation under the initial constraints Ti << Ui (1 ≤ i ≤ n), and let Si = Ui[R1=A1,...,Rp=Ap] (1 ≤ i ≤ n).

    Otherwise, let Si = Ui (1 ≤ i ≤ n).

  • For all j from 1 to n, Tj <: Sj.

  • If the second method is a generic method as described above, then Al <: Bl[R1=A1,...,Rp=Ap] (1 ≤ l ≤ p).

您应该感兴趣的是 For all j from 1 to n, Tj <: Sj .

在编译时,如果确定了几种适用的方法,则选择最具体的一种。
然而,如果不止一种方法对有效参数类型具有最大特异性,编译器就不知道应该调用哪个方法。所以它会发出编译错误。

您可以在 JLS : 15.12.2. Compile-Time Step 2: Determine Method Signature 中找到此信息:

A method is said to be maximally specific for a method invocation if it is accessible and applicable and there is no other method that is applicable and accessible that is strictly more specific.

If there is exactly one maximally specific method, then that method is in fact the most specific method; it is necessarily more specific than any other accessible method that is applicable. It is then subjected to some further compile-time checks as described in §15.12.3.

It is possible that no method is the most specific, because there are two or more methods that are maximally specific. In this case:

- If all the maximally specific methods have override-equivalent (§8.4.2) signatures, then:

  • If exactly one of the maximally specific methods is not declared abstract, it is the most specific method.

  • Otherwise, if all the maximally specific methods are declared abstract, and the signatures of all of the maximally specific methods have the same erasure (§4.6), then the most specific method is chosen arbitrarily among the subset of the maximally specific methods that have the most specific return type.

  • However, the most specific method is considered to throw a checked exception if and only if that exception or its erasure is declared in the throws clauses of each of the maximally specific methods.

- Otherwise, we say that the method invocation is ambiguous, and a compile-time > error occurs.

如果我们将这些规则应用于您的三个示例(我更改了顺序,以编译良好的情况开始,以编译错误的情况结束)。

1) 找到了一种最具体的方法

class MyClass{
public static void myMethod(int i){
System.out.println("myMethod1(int)");
}
public static void myMethod(double a){
System.out.println("myMethod2(int)");
}
}

class Demo{
public static void main(String args[]){
MyClass.myMethod(100);
}
}

编译器看到一个完美匹配的方法:myMethod(int i)因为传递的值是 int .它编译得很好。

2) 找到了一种最具体的方法

class MyClass{
public static void myMethod(int i){
System.out.println("myMethod1(int)");
}
public static void myMethod(double a){
System.out.println("myMethod2(int)");
}
}

class Demo{
public static void main(String args[]){
byte b=10;
MyClass.myMethod(b);
}
}

编译器发现一个方法比另一个方法具有更高的特异性。
来自 byte 的隐式转换至 int确实比 byte 的隐式转换更具体至 double根据扩大原始转换规则。

我们可以检查 void myMethod(int i)void myMethod(double a) 更具体如果第一个方法处理的任何调用都可以传递给另一个方法而不会出现编译时类型错误。

myMethod(3);适用于void myMethod(double x)编译正常。
但是myMethod(double)3);适用于void myMethod(int y)产生编译错误。
所以找到了一个独特的最大特定方法:void myMethod(int i) .
编译没问题。

3) 未找到唯一的最大特异性方法

class Demo{
public static void myMethod(int y, double x){}
public static void myMethod(double x,int y){}

public static void main(String args[]){
byte b=10;
myMethod(b,b);
}
}

编译器看到两种方法,其中没有一种比另一种具有更高的特异性。
首先,在这两种情况下,都需要将有效参数类型隐式转换为方法参数的声明类型。
但在这两种情况下,特异性是相同的。

我们可以检查 void myMethod(int y, double x)myMethod(double x,int y) 一样具体如果 any 方法处理的任何调用无法在没有编译时类型错误的情况下传递给另一个调用。

myMethod(double)3,4);适用于void myMethod(int y, double x)产生编译错误 int变量不能接受 double值(value)。
myMethod(3,(double)4);适用于void myMethod(double x,int y)出于同样的原因产生编译错误。

未找到唯一的最大特异性方法。所以编译器无法猜测应该调用哪个方法。出现编译错误。

关于java - 当传递参数给方法在 Java 中变得模棱两可?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42045220/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com