java - 当参数是文字空值时,如何选择重载方法?
我在测验中遇到了这个问题,
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);
}
}
该程序的输出是“String Version”。 但是我无法理解为什么将null传递给重载方法会选择字符串版本。 null是一个String变量,指向什么?
但是当代码更改为时,
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);
}
}
它给出了一个编译错误,说“方法方法(StringBuffer)对于MoneyCalc类型是不明确的”
zakSyed asked 2019-08-02T04:56:43Z
8个解决方案
101 votes
null是一个String变量,指向什么?
可以将空引用转换为任何类类型的表达式。 所以在String的情况下,这很好:
String x = null;
选择此处的String重载是因为Java编译器根据JLS的第15.12.2.5节选择最具体的重载。 特别是:
非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个没有编译时类型错误的调用,那么一个方法比另一个方法更具体。
在第二种情况下,两种方法仍然适用,但String和StringBuffer都没有比另一种方法更具体,因此两种方法都不比另一种方法更具体,因此编译器错误。
Jon Skeet answered 2019-08-02T04:57:26Z
9 votes
此外,JLS 3.10.7还声明“null”是“null类型”的文字值。 因此存在一种称为“null”的类型。
稍后,JLS 4.1声明存在一个无法声明变量的null类型,但您只能通过null文本使用它。 后来它说:
空引用总是可以进行扩展的引用转换 任何参考类型。
为什么编译器选择将它扩展为String可能会在Jon的答案中解释。
Edwin Dalorzo answered 2019-08-02T04:58:13Z
2 votes
您可以将string分配给null值,使其有效,并且java和大多数编程语言的顺序适合最接近的类型,然后适合对象。
JonH answered 2019-08-02T04:58:38Z
2 votes
要回答标题中的问题:String既不是Integer也不是Object,但可以将对两者的引用分配给String。
我真的很惊讶这个代码甚至编译。 我之前尝试过类似的东西,但我收到编译错误,说这个调用是模棱两可的。
但是,在这种情况下,似乎编译器正在选择食物链中最低的方法。 假设您需要方法的最不通用版本以帮助您。
我将不得不看看我是否可以挖掘出这个(貌似)完全相同的情况下我遇到编译器错误的例子,尽管...]
编辑:我明白了。 在我制作的版本中,我有两个重载方法接受String和Integer.在这种情况下,没有“最具体”的参数(如Object和String),所以它不能在它们之间进行选择,这与你的 码。
很酷的问题!
asteri answered 2019-08-02T04:59:39Z
0 votes
由于String类型比Object类型更具体。 假设您再添加一个采用Integer类型的方法。
public void method(Integer i) {
System.out.println("Integer Version");
}
然后你会得到一个编译错误,说这个调用是不明确的。 现在我们有两个具有相同优先权的同样具体的方法。
BSingh answered 2019-08-02T05:00:12Z
0 votes
Java编译器为大多数派生类类型赋予null。
以下是理解它的示例:
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);
}
}
输出:B级。
另一方面:
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);
}
}
结果:方法fun(C)对于MyTest类型是不明确的
希望有助于更好地理解这种情况。
Ravi answered 2019-08-02T05:01:12Z
0 votes
资料来源:[https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5]
概念:最具体的方法
Explanation:如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符。 Java编程语言使用选择最具体方法的规则。 尝试将null转换为特定类型,并自动调用您希望的方法。
M.P answered 2019-08-02T05:01:52Z
-1 votes
我不会说。 NULL是状态而不是值。 查看此链接以获取更多相关信息(该文章适用于SQL,但我认为它也有助于解决您的问题)。
northpole answered 2019-08-02T05:02:18Z