方法重载并选择最具体的类型
示例代码是:
public class OverloadingTest {
public static void test(Object obj){
System.out.println("Object called");
}
public static void test(String obj){
System.out.println("String called");
}
public static void main(String[] args){
test(null);
System.out.println("10%2==0 is "+(10%2==0));
test((10%2==0)?null:new Object());
test((10%2==0)?null:null);
}
输出是:
名为字符串
的字符串
10%2==0 为真
对象称为
名为
第一次调用test(null)
会调用带有String
参数的方法,根据Java语言规范
这是可以理解的。
1)谁能解释一下在前面的调用中调用 test() 的依据是什么?
2) 同样,当我们输入 if
条件时:
if(10%2==0){
test(null);
}
else
{
test(new Object());
}
它总是使用 String
参数调用该方法。
编译器在编译时会计算表达式(10%2)
吗?我想知道表达式是在编译时还是运行时计算的。谢谢。
The sample code is :
public class OverloadingTest {
public static void test(Object obj){
System.out.println("Object called");
}
public static void test(String obj){
System.out.println("String called");
}
public static void main(String[] args){
test(null);
System.out.println("10%2==0 is "+(10%2==0));
test((10%2==0)?null:new Object());
test((10%2==0)?null:null);
}
And the output is :
String called
10%2==0 is true
Object called
String called
The first call to test(null)
invokes the method with String
argument , which is understandable according to The Java Language Specification
.
1) Can anyone explain me on what basis test()
is invoked in preceding calls ?
2) Again when we put , say a if
condition :
if(10%2==0){
test(null);
}
else
{
test(new Object());
}
It always invokes the method with String
argument .
Will the compiler compute the expression (10%2)
while compiling ? I want to know whether expressions are computed at compile time or run time . Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这是 Java 语言规范所说的内容关于这个问题。
这是您的情况下的 test(String) 方法。
因此,如果您添加...
它将显示编译错误 - 方法 test(String) 对于类型 OverloadingTest 来说不明确。
正如JLS所说:
This is what Java Language Specifications say about the problem.
This is test(String) method in your case.
And because of that if you add...
it will show compilation error -The method test(String) is ambiguous for the type OverloadingTest.
Just like JLS says:
Java 使用早期绑定。最具体的方法是在编译时选择的。最具体的方法是根据参数的数量和参数的类型来选择的。在这种情况下,参数的数量不相关。这给我们留下了参数的类型。
参数有什么类型?两个参数都是表达式,使用三元条件运算符。问题归结为:条件三元运算符返回什么类型?类型是在编译时计算的。
给出了两个表达式:
列出了类型评估的规则 在这里。在
B
中很简单,两个术语完全相同:将返回null
(无论是什么类型)(JLS:“如果第二个和第三个操作数具有相同的类型(可能是 null 类型),那么这就是条件表达式。”)。在A
中,第二项来自特定类。由于这更具体,并且null
可以替换Object
类的对象,因此整个表达式的类型是Object
(JLS:“如果如果第二个和第三个操作数之一是空类型,另一个是引用类型,则条件表达式的类型就是该引用类型。”)。在对表达式进行类型评估后,方法选择符合预期。
您给出的
if
示例有所不同:您使用两种不同类型的对象调用方法。三元条件运算符始终在编译时评估为符合这两个条件的一个类型。Java uses early binding. The most specific method is chosen at compile time. The most specific method is chosen by number of parameters and type of parameters. Number of parameters is not relevant in this case. This leaves us with the type of parameters.
What type do the parameters have? Both parameters are expressions, using the ternary conditional operator. The question reduces to: What type does the conditional ternary operator return? The type is computed at compile time.
Given are the two expressions:
The rules of type evaluation are listed here. In
B
it is easy, both terms are exactly the same:null
will be returned (whatever type that may be) (JLS: "If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression."). InA
the second term is from a specific class. As this is more specific andnull
can be substituted for an object of classObject
the type of the whole expression isObject
(JLS: "If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.").After the type evaluation of the expressions the method selection is as expected.
The example with
if
you give is different: You call the methods with objects of two different types. The ternary conditional operator always is evaluated to one type at compile time that fits both terms.JLS 15.25:
所以类型
是Object。
JLS 15.25:
So the type of
is Object.
等同于:
由于
o
的类型是Object
(就像(10%2==0)?null:new Object()< 的类型一样) /code>)
test(Object)
将始终被调用。o
的值并不重要。Is the same as:
Since type of
o
isObject
(just like the type of(10%2==0)?null:new Object()
)test(Object)
will be always called. The value ofo
doesn't matter.这是一个非常好的问题。
让我尝试澄清您上面编写的代码。
在此,
null
将转换为字符串类型,因此调用test(String obj)
,根据 JLS,您确信该调用。这将返回布尔“true”值。因此,第一个布尔“true”值将自动转换为布尔包装类对象。布尔包装对象正在寻找与三元运算符中的
new Object()
选项的最佳匹配。并且该方法以 Object 作为参数进行调用,因此调用了以下方法为了实验目的,您可以尝试以下组合,然后您会获得更好的清晰度。
这次它再次返回布尔“true”值,并且它将再次遵循与上面解释的相同的转换。但这次三元运算符中没有
new Object()
参数。因此它将自动类型转换为null
对象。同样,它遵循与第一个方法调用相同的方法调用。if .. else
语句。然后编译器也会对代码做出公平的决定。您的 if 条件始终为 true 并调用此代码
test(null)
。因此,它始终以 String 作为参数调用第一个test(String obj)
方法,如上所述。This is the really nice question.
Let me try to clarify your code that you have written above.
In this the
null
will be converted into string type so calling thetest(String obj)
, as per JLS you are convinced with the call.Which is going to return the boolean "true" value. So first boolean "true" value is going to auto cast into Boolean Wrapper class object. Boolean wrapper Object is finding the best match with your
new Object()
option in the ternary operator. And the method calls with Object as a parameter so it calls the following methodFor the experiment sake you can try the following combinations then you will get better clarity.
This time again it returns as boolean "true" value, and it will again follow the same casts as explained above. But this time there is no
new Object()
parameter is there in your ternary operator. So it will be auto type cast intonull
Object. Again it follows same method call as the your first method call.if .. else
statement. Then also the compiler doing the fair decision with the code.Here all the time your if condition is true and calling this code
test(null)
. Therefore all the time it call the firsttest(String obj)
method with String as parameter as explained above.你的答案是:运行时,因为在运行时指定参数是字符串的实例或不是,所以在编译时找不到它。
Your answer is : Runtime because in runtime specify parameter is instance of String or not so in compile-time can't find this.
我认为你的问题是你做出了错误的假设,你的表达式:
和
总是会调用 test(null),这就是为什么它们会经历 test (Object)。
I think your problem is that you are making the wrong assumption, your expressions:
and
Will always call test(null), and that's why they will go through test (Object).
正如 @Banthar 提到的,
?:
运算符首先为变量赋值,然后评估条件。另一方面,您提到的
if
条件始终返回 true,因此编译器将仅用if< 的主体替换整个
if-else
块。 /代码>。as @Banthar mentionend the
?:
operator assigns a value to a variable first then evaluates the condition.On the other hand, the
if
condition you mentioned always returns true, so the compiler will replace the wholeif-else
block with only the body of theif
.1)
test()
方法是由编译时参数的类型决定的:输出:
2) 编译器更聪明,编译后的代码就相当于:
可以检查字节码使用 javap -c :
1) the
test()
method is determined by the type of the parameter at the compilation time :output :
2) The compiler is even smarter, the compiled code is equivalent to just :
you can check the bytecode with
javap -c
: