将null传递给java中的重载方法|重载的变量是异常类型

将null传递给java中的重载方法|重载的变量是异常类型,java,exception,exception-handling,Java,Exception,Exception Handling,我正在用Java练习一些例子。代码如下所示: public class NullPassing { public static void main(String[] args) { method1(null); } public static void method1(Exception e) { System.out.println(e); } public static void method1(ArithmeticEx

我正在用Java练习一些例子。代码如下所示:

public class NullPassing {
    public static void main(String[] args) {
        method1(null);
    }
    public static void method1(Exception e) {
        System.out.println(e);
    }
    public static void method1(ArithmeticException e) {
        System.out.println(e);
    }
}
关于这一点,我没有什么问题

1) 上面的代码使用method1(算术异常e)执行并打印null,为什么不使用异常(因为它位于层次结构的顶部)

猜测:这是因为与
异常
相比,算术异常更具体。如果是这样,为什么要问第二个问题

2) 通过在现有代码中引入以下方法,程序显示编译时异常。为什么?

public static void method1(NullPointerException e) {
    System.out.println(e);
}

帮助我学习。谢谢

我们有两位候选人

 public static void method1(Exception e) {
 }
 public static void method1(ArithmeticException e) {
 }
我们传递一个
null
并且两个方法都接受null,所以我们选择更具体的一个,
arithmetricexception
是一个
Exception
,但是相反的情况不是真的,因此
arithmetricexception
更具体

现在我们有三位候选人

public static void method1(Exception e) {
}
public static void method1(ArithmeticException e) {
}
public static void method1(NullPointerException e) {
}

第一个是等式之外的,因为有更具体的,所以我们剩下两个候选者,一个接受
NullPointerException
,另一个接受
arithmetricexception
,两者都在同一级别,因此我们有一个不明确的调用

你对1的回答是正确的。如果选择两个或多个重载作为候选,并且其中一个重载比所有其他重载更具体,则选择最具体的重载

联合联络小组说:

如果一个方法调用可以访问并适用于多个成员方法,则有必要选择一个成员方法来为运行时方法分派提供描述符。Java编程语言使用的规则是选择最具体的方法。非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个方法而不会出现编译时错误,那么一个方法比另一个方法更为具体

(然后正式解释了“更具体”的含义。)


在第二个案例/问题中,您有:

public class NullPassing {
    public static void main(String[] args) {
        method1(null);
    }
    public static void method1(Exception e) {
        System.out.println(e);
    }
    public static void method1(ArithmeticException e) {
        System.out.println(e);
    }
    public static void method1(NullPointerException e) {
        System.out.println(e);
    }  
}
现在,我们有三个候选方法(可访问且适用的方法)。第一个候选人不如另外两个候选人具体,但剩下的两个候选人都不比另一个更具体。因此,这是一个编译错误

显然,您可以通过强制转换
null
来消除调用的歧义;e、 g

  method1((NullPointerException)null)
1.为什么它使用算术异常? Java尝试为任何对象类型选择最具体的重载方法。空对象的类型为“[特殊空类型]”,它是所有非基元类型的子类型;因此,最具体的子类型是
算术异常

有关Java编译器如何解决重载的更多信息,请参阅以下答案:

2.如果添加NullPointerException,为什么程序不编译? 一旦您有不在同一继承层次结构中的多个重载,Java编译器将获得多个最特定重载的可能候选对象:两个
方法1(NullPointerException)
方法1(算术异常)
都是最特定的候选对象。因此,您必须通过将
null
强制转换为重载类型来告诉编译器您实际需要什么:例如
method1((NullPointerException)null)


有关不明确重载的详细信息,请参见

Wow,我从未想到更具体的重载总是被选中的一个。@PieterDeBie虽然它不完全可比(因为分派仍然是静态的),但重载的行为类似于多态性:如果重写子类中的方法,然后选择这个更具体的方法。因此,我认为,如果重载的表现正好相反,它会引起很多意外(或bug)。我对你的第二个问题真的不清楚。您已经知道编译器将选择具有更特定类型的重载版本,但您想知道为什么它无法确定
NullPointerException
arithmetricexception
之间的哪种类型更为特定?这是一个奇妙的解决方案解释。谢谢。