Ich bin auf diese Frage in einem Quiz gestoßen,
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);
}
}
Die Ausgabe dieses Programms ist "String Version". Aber ich konnte nicht verstehen, warum das Übergeben einer Null an eine überladene Methode die String-Version auswählte. Ist null eine String-Variable, die auf nichts zeigt?
Wenn der Code jedoch in geändert wird,
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);
}
}
Es wird ein Kompilierungsfehler ausgegeben, der besagt: "Die Methodenmethode (StringBuffer) ist für den Typ MoneyCalc nicht eindeutig."
java
overloading
zakSyed
quelle
quelle
Antworten:
Eine Nullreferenz kann in einen Ausdruck eines beliebigen Klassentyps konvertiert werden. Im Fall von
String
ist dies also in Ordnung:Die
String
Überladung wird hier ausgewählt, weil der Java-Compiler die spezifischste Überladung gemäß Abschnitt 15.12.2.5 des JLS auswählt . Bestimmtes:In Ihrem zweiten Fall sind beide Methoden weiterhin anwendbar, aber weder
String
nochStringBuffer
spezifischer als die andere, daher ist keine Methode spezifischer als die andere, daher der Compilerfehler.quelle
Object
kann jeden Typ nehmen und in einen einwickelnObject
, während einString
nur einen nehmen kannString
. In diesem FallString
ist ein Typ spezifischer als derObject
Typ.question.method((String)null)
Darüber hinaus deklariert JLS 3.10.7, dass "null" ein Literalwert vom Typ "null" ist. Daher gibt es einen Typ namens "null".
Später gibt JLS 4.1 an , dass es einen Nulltyp gibt, dessen Variablen nicht deklariert werden können. Sie können ihn jedoch nur über das Nullliteral verwenden. Später heißt es:
Warum der Compiler es auf String erweitert, wird in Jons Antwort erklärt .
quelle
Sie können
string
einemnull
Wert ein zuweisen , damit er gültig ist und die Reihenfolge für Java und die meisten Programmiersprachen dem nächstgelegenen Typ und dann dem Objekt entspricht.quelle
Um die Frage im Titel zu beantworten:
null
ist weder einString
noch einObject
, aber ein Verweis auf eines kann zugewiesen werdennull
.Ich bin tatsächlich überrascht, dass dieser Code sogar kompiliert wird. Ich habe zuvor etwas Ähnliches ausprobiert und einen Compilerfehler erhalten, der besagt, dass der Aufruf nicht eindeutig ist.
In diesem Fall scheint der Compiler jedoch die Methode zu wählen, die in der Nahrungskette am niedrigsten ist. Es wird davon ausgegangen, dass Sie die am wenigsten generische Version der Methode möchten, um Ihnen zu helfen.
Ich werde sehen müssen, ob ich das Beispiel ausgraben kann, in dem ich in diesem (scheinbar) genau gleichen Szenario einen Compilerfehler erhalten habe ...]
EDIT: Ich verstehe. In der von mir erstellten Version hatte ich zwei überladene Methoden, die a
String
und an akzeptiertenInteger
. In diesem Szenario gibt es keinen "spezifischsten" Parameter (wie inObject
undString
), daher kann er im Gegensatz zu Ihrem Code nicht zwischen diesen wählen.Sehr coole Frage!
quelle
Der String-Typ ist spezifischer als der Objekttyp. Angenommen, Sie fügen eine weitere Methode hinzu, die einen Integer-Typ annimmt.
Dann wird ein Compilerfehler angezeigt, der besagt, dass der Aufruf nicht eindeutig ist. Wie jetzt haben wir zwei gleich spezifische Methoden mit gleicher Priorität.
quelle
Der Java-Compiler gibt den meisten abgeleiteten Klassentyp an, um null zuzuweisen.
Hier ist das Beispiel, um es zu verstehen:
Ausgabe: Klasse B
andererseits:
Ergebnis: Die Methode fun (C) ist für den Typ MyTest nicht eindeutig
Hoffe, es wird helfen, diesen Fall besser zu verstehen.
quelle
Quelle: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5
Konzept: Spezifischste Methode
Erläuterung: Wenn auf mehr als eine Mitgliedsmethode zugegriffen werden kann und Für einen Methodenaufruf muss eine ausgewählt werden, um den Deskriptor für den Laufzeitmethodenversand bereitzustellen. Die Programmiersprache Java verwendet die Regel, dass die spezifischste Methode ausgewählt wird. Versuchen Sie, die Null auf einen bestimmten Typ zu übertragen, und die gewünschte Methode wird automatisch aufgerufen.
quelle
Ich würde auch nicht sagen. NULL ist ein Zustand, kein Wert. Weitere Informationen hierzu finden Sie unter diesem Link (der Artikel gilt für SQL, aber ich denke, er hilft auch bei Ihrer Frage).
quelle
null
ist definitiv ein Wert, wie im JLS definiert.