java 当参数是文字空值时,如何选择重载方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13033037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How is an overloaded method chosen when a parameter is the literal null value?
提问by zakSyed
I came across this question in a quiz,
我在一次测验中遇到了这个问题,
public class MoneyCalc {
public void method(Object o) {
System.out.println("Object Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
The output of this program is "String Version". But I was not able to understand why passing a null to an overloaded method chose the string version. Is null a String variable pointing to nothing ?
该程序的输出是“字符串版本”。但是我无法理解为什么将 null 传递给重载方法选择了字符串版本。null 是一个指向空的 String 变量吗?
However when the code is changed to,
但是,当代码更改为,
public class MoneyCalc {
public void method(StringBuffer sb) {
System.out.println("StringBuffer Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
it gives a compile error saying "The method method(StringBuffer) is ambiguous for the type MoneyCalc"
它给出了一个编译错误,说“方法 method(StringBuffer) 对于 MoneyCalc 类型不明确”
回答by Jon Skeet
Is null a String variable pointing to nothing ?
null 是一个指向空的 String 变量吗?
A null reference can be converted to an expression of any class type. So in the case of String
, this is fine:
空引用可以转换为任何类类型的表达式。所以在 的情况下String
,这很好:
String x = null;
The String
overload here is chosen because the Java compiler picks the most specificoverload, as per section 15.12.2.5 of the JLS. In particular:
String
选择这里的重载是因为 Java 编译器会根据 JLS 的第 15.12.2.5 节选择最具体的重载。特别是:
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error.
非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个方法而没有编译时类型错误,那么一个方法比另一个方法更具体。
In your second case, both methods are still applicable, but neither String
nor StringBuffer
is more specific than the other, therefore neither method is more specific than the other, hence the compiler error.
在第二种情况下,这两种方法仍然适用,但既不String
也不StringBuffer
是比另一个更具体的,因此既不方法比其他,因此编译器错误更具体。
回答by Edwin Dalorzo
Additionally, the JLS 3.10.7also declares that "null" is a literal value of the "null type". Therefore there exists a type called "null".
此外,JLS 3.10.7还声明“null”是“null 类型”的文字值。因此存在一种称为“null”的类型。
Later, the JLS 4.1states that there exists a null type of which is impossible to declare variables, but you can use it through the null literal only. Later it says:
后来,JLS 4.1声明存在一种无法声明变量的空类型,但您只能通过空字面量来使用它。后来它说:
The null reference can always undergo a widening reference conversion to any reference type.
空引用始终可以进行扩展引用转换为任何引用类型。
Why the compiler chooses to widen it to String might well be explained in Jon's answer.
为什么编译器选择将其扩展为 String 可能在Jon 的回答中得到了很好的解释。
回答by JonH
You can assign a string
to a null
value so it is valid and the order for java and most programming languages is fit to the closest type and then to object.
您可以将 a 分配string
给一个null
值,使其有效,并且 Java 和大多数编程语言的顺序适合最接近的类型,然后适合对象。
回答by asteri
To answer the question in the title: null
is neither a String
nor an Object
, but a reference to either can be assigned to null
.
回答标题中的问题:null
既不是 aString
也不是 an Object
,但是可以将其中一个的引用分配给null
。
I'm actually surprised this code even compiles. I tried something similar previously and I got a compiler error saying that the call was ambiguous.
我实际上很惊讶这段代码甚至可以编译。我之前尝试过类似的事情,但我收到一个编译器错误,说调用不明确。
However, in this case, it seems like the compiler is choosing the method which is lowest on the food chain. It's assuming that you want the least generic version of the method in order to help you out.
但是,在这种情况下,编译器似乎正在选择食物链中最低的方法。它假设您想要该方法的最不通用的版本来帮助您。
I'll have to see if I can dig up the example where I got a compiler error in this (seemingly) exact same scenario, though...]
我将不得不看看我是否可以挖掘出在这个(看似)完全相同的场景中出现编译器错误的示例,尽管......]
EDIT:I see. In the version I made, I had two overloaded methods accepting a String
and an Integer
. In this scenario, there is no "most specific" parameter (as in Object
and String
), so it can't choose between them, unlike in your code.
编辑:我明白了。在我制作的版本中,我有两个重载方法接受 aString
和 an Integer
。在这种情况下,没有“最具体”的参数(如Object
和String
),因此与您的代码不同,它无法在它们之间进行选择。
Very cool question!
很酷的问题!
回答by BSingh
As String type is more specific than Object type. Let's say you add one more method that takes an Integer type.
因为 String 类型比 Object 类型更具体。假设您再添加一个采用 Integer 类型的方法。
public void method(Integer i) {
System.out.println("Integer Version");
}
Then you will get a compiler error saying that the call is ambiguous. As now we two equally specific methods with same precedence.
然后你会得到一个编译器错误,说调用不明确。就像现在我们两个具有相同优先级的同样具体的方法。
回答by Ravi
Java compiler gives most derived class type to assign null.
Java 编译器给大多数派生类类型赋值为空。
Here is the example to understand it :
这是理解它的示例:
class A{
public void methodA(){
System.out.println("Hello methodA");
}
}
class B extends A{
public void methodB(){
System.out.println("Hello methodB");
}
}
class C{
public void methodC(){
System.out.println("Hello methodC");
}
}
public class MyTest {
public static void fun(B Obj){
System.out.println("B Class.");
}
public static void fun(A Obj){
System.out.println("A Class.");
}
public static void main(String[] args) {
fun(null);
}
}
output:B Class.
输出:B类。
on the other hand:
另一方面:
public class MyTest {
public static void fun(C Obj){
System.out.println("B Class.");
}
public static void fun(A Obj){
System.out.println("A Class.");
}
public static void main(String[] args) {
fun(null);
}
}
Result :The method fun(C) is ambiguous for the type MyTest
结果:方法 fun(C) 对于 MyTest 类型不明确
Hope it will help to understand this case better.
希望能帮助大家更好地理解这个案例。
回答by M.P
Source:https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5
Concept:Most specific method
Explanation: If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen. Try casting the null on to specific type and the method you wish will be automatically called.
来源:https : //docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5
概念:最具体的方法
说明:如果多个成员方法既可访问又可适用于方法调用,需要选择一个来提供运行时方法调度的描述符。Java 编程语言使用选择最具体的方法的规则。尝试将 null 转换为特定类型,您希望的方法将被自动调用。