2008-12-18 4 views
12

Warum es (scheinbar) einen Unterschied, ob ich null als Argument direkt übergeben oder ein Object passieren, dass ich den Wertnull zugewiesen?Java-Methode Dispatch mit Null-Argumente

Object testVal = null; 
test.foo(testVal); // dispatched to foo(Object) 
// test.foo(null); // compilation problem -> "The method foo(String) is ambiguous" 

public void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
} 

public void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
} 

Mit anderen Worten, warum der (kommentiert-out) zweiter Anruf foo(...) nicht zu foo(Object) versandt?

Update: Ich benutze Java 1.6. Ich könnte Hemals Code ohne Probleme kompilieren, aber meiner kompiliert immer noch nicht. Der einzige Unterschied, den ich sehe, ist, dass Hemals Methoden statisch sind, während meine nicht. Aber ich verstehe wirklich nicht, warum das einen Unterschied machen sollte ...?

Update 2: Gelöst. Ich hatte eine andere Methode foo (Runnable) in meiner Klasse, so dass der Dispatcher nicht eindeutig die spezifischste Methode auswählen konnte. (Siehe meinen Kommentar in Hemals zweiter Antwort.) Danke für Ihre Hilfe.

Antwort

24

Welche Java-Version verwenden Sie? Mit 1.6.0_11 kompiliert und läuft der Code (unten eingefügt).

Ich bin sicher, es ist offensichtlich, warum foo(testVal) zu foo(Object) geht.

Der Grund, warum foo(null) zu foo(String) geht, ist ein wenig komplex. Die Konstante null ist vom Typ nulltype, die eine Unterart aller Typen ist. So erweitert sich diese nulltypeString, die Object erweitert.

Wenn Sie foo(null) aufrufen, sucht der Compiler nach der überladenen Methode mit dem spezifischsten Typ. Seit String ist spezifischer als Object das ist die Methode, die aufgerufen wird.

Wenn Sie eine andere Überladung hatten, die so spezifisch wie String war, sagen Sie foo(Integer), dann würden Sie einen mehrdeutigen Überlastungsfehler erhalten.

class NullType { 

    public static final void main(final String[] args) { 
    foo(); 
    } 

    static void foo() 
    { 
    Object testVal = null; 
    foo(testVal); // dispatched to foo(Object) 
    foo(null); // compilation problem -> "The method foo(String) is ambiguous" 
    } 

    public static void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
    } 

    public static void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
    } 

} 
+0

Gerade getestet, und ich bin betäubt, dass (a) 6u11 nicht sagt, es ist mehrdeutig, und (b), dass Null in String nicht Object aufgelöst wird. Lerne jeden Tag etwas Neues - +1 für den Unterricht. –

+1

@Software Monkey: Sobald Sie akzeptieren, dass die Konstante Null vom Typ Null ist und der Null-Typ ist ein Subtyp aller Typen, ist dies ziemlich offensichtlich. Objekt

+0

Pedanterie: Die Methode überschreibt das Objekt mit String. Überladen bedeutet, dass der Methodenname derselbe ist, aber die Signatur variiert weiter. Ausgezeichnete Antwort. Danke. – Sam

2

Da der zweite auskommentierte Aufruf mit NULL für den Compiler mehrdeutig ist. Die literale Null könnte eine Zeichenfolge oder ein Objekt sein. Während der zugewiesene Wert einen bestimmten Typ hat. Sie müssen die Null, z. test.foo ((String) null), um die Mehrdeutigkeit zu entfernen.

1

Hat jemand das Beispiel versucht ???

Mit 1.6.0 foo (null) ist für die meisten spezifische Methode versandt, die foo (String) ist ...

Wenn Sie eine neue Methode foo (Integer) der Compiler können wählen, nicht die meisten sagen hinzufügen spezifische anwendbare Methode und zeigt einen Fehler an.

-Patrick

1

Leider eine Antwort, für einen Kommentar zu benutzen, aber ich brauche Code zu schreiben, die nicht in Kommentar passen.

@Yang, ich bin auch in der Lage zu kompilieren und führen Sie Folgendes. Können Sie einen vollständigen Code, der mit einer Zeile kompiliert wird, kommentieren, so dass, wenn ich die Zeile auskommentiere, diese nicht kompiliert wird?

+0

Huh, ich habe meine Testklasse aufgeräumt, um sie hier zu posten und erkannte, dass ich außer foo (String) und foo (Object) auch ein foo (Runnable) hatte - was ich jetzt als foo (null) wegen String mehrdeutig verstehe ist nicht spezifischer als Runnable und umgekehrt. Danke Hemal für deine wertvolle Hilfe! –

+0

Ich bin froh, dass ich helfen konnte. Bitte schön. –

Verwandte Themen