Java類謎題46:令人混淆的構(gòu)造器案例

字號:

本謎題呈現(xiàn)給你了兩個容易令人混淆的構(gòu)造器。main方法調(diào)用了一個構(gòu)造器,但是它調(diào)用的到底是哪一個呢?該程序的輸出取決于這個問題的答案。那么它到底會打印出什么呢?甚至它是否是合法的呢?
    public class Confusing {
     private Confusing(Object o) {
     System.out.println("Object");
     }
     private Confusing(double[] dArray) {
     System.out.println("double array");
     }
     public static void main(String[] args) {
     new Confusing(null);
     }
    }
    傳遞給構(gòu)造器的參數(shù)是一個空的對象引用,因此,初看起來,該程序好像應(yīng)該調(diào)用參數(shù)類型為Object的重載版本,并且將打印出Object。另一方面,數(shù)組也是引用類型,因此null也可以應(yīng)用于類型為double[ ]的重載版本。你由此可能會得出結(jié)論:這個調(diào)用是模棱兩可的,該程序應(yīng)該不能編譯。如果你試著去運行該程序,就會發(fā)現(xiàn)這些直觀感覺都是不對的:該程序打印的是double array。這種行為可能顯得有悖常理,但是有一個很好的理由可以解釋它。
    Java的重載解析過程是以兩階段運行的。第一階段選取所有可獲得并且可應(yīng)用的方法或構(gòu)造器。第二階段在第一階段選取的方法或構(gòu)造器中選取最精確的一個。如果一個方法或構(gòu)造器可以接受傳遞給另一個方法或構(gòu)造器的任何參數(shù),那么我們就說第一個方法比第二個方法缺乏精確性[JLS 15.12.2.5]。
    在我們的程序中,兩個構(gòu)造器都是可獲得并且可應(yīng)用的。構(gòu)造器Confusing(Object)可以接受任何傳遞給Confusing(double[ ])的參數(shù),因此Confusing(Object)相對缺乏精確性。(每一個double數(shù)組都是一個Object,但是每一個Object并不一定是一個double數(shù)組。)因此,最精確的構(gòu)造器就是Confusing(double[ ]),這也就解釋了為什么程序會產(chǎn)生這樣的輸出。