- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当方法重载完成后,我知道我们只能创建具有相同名称的方法,前提是它们的方法签名不同。
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/
我从一所大学获得了一些示例代码,导入了项目并尝试运行测试:方法 assertThat(Integer, Matcher) 对于 MyClass 类型是不明确的 每个 assertThat 都被标记为红
关于将 iOS 应用程序迁移到 Swift 3.0 的过程。这是我面临的一个问题。 先上相关代码: let calendar = NSCalendar.current, calendCompo = c
我刚开始研究 Java 8 Lambda 功能。我在 Java 7 中编写了这段代码,并尝试在 lamdas 中执行它。请注意,最后一行会产生编译错误,因为重载的函数不明确。我明白原因。如何使用 la
如何优先(告诉编译器)使用“函数接收引用”(#B)而不是“函数接收值”(#A)? #include using namespace std; class Heavy{/* ...... */}; /
我正在使用 Google Map API V3 显示车辆行驶路径及其路线方向。但是通过谷歌方向图标,很难找到方向。下图解释更多 我看到了每个图标,它是 source 我找到了图片路径,是 http:/
我是一名优秀的程序员,十分优秀!