Java überladen Regeln
Stieß ich auf zwei überlastung Fragen vor kurzem, dass ich nicht finden können, eine Antwort haben und keine java-Umgebung laufen einige test-code. Ich hoffe jemand kann mir helfen, durch zusammenstellen einer Liste von all den Regeln, die java-Compiler Folgen Sie für überlastung oder alternativ verweist mich an eine Liste, die bereits vorhanden ist.
Ersten, wenn die beiden Methoden unterscheiden sich nur durch eine endgültige varargs-parameter, unter welchen Umständen jeder genannt und können Sie rufen Sie die varargs-Methode ohne Argumente?
private void f(int a) { /* ... */ }
private void f(int a, int... b) { /* ... */ }
f(12); //calls the former? I would expect it to
f(12, (int[])null); //calls latter, but passes null for b?
//Can I force the compiler to call the second method in the same fashion
//as would happen if the first method didn't exist?
Zweite Frage, wenn die beiden Methoden unterscheiden sich durch die Arten geerbt, die von einer anderen aufgerufen wird? Ich würde erwarten, dass die abgeleitete version, genannt zu werden, und Gießen darf, rufen die anderen.
interface A {}
class B implements A {}
class C implements A {}
private void f(A a) {}
private void f(B b) {}
f(new C()); //calls the first method
f(new B()); //calls the second method?
f((A)(new B()); //calls the first method using a B object?
Diese zwei Beispiele, sondern als code-reader würde ich lieber eine kanonische Liste der genauen bestellt, Regeln für die Lösung das, weil ich Häufig keine Zeit haben, um die Einrichtung einer build-Umgebung zu überprüfen, was der compiler tut.
InformationsquelleAutor Peter Oehlert | 2012-06-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Überladen vs. Überschreiben
Die Auswahl der richtige Umsetzung der Methode erfolgt zur Laufzeit, wie Sie auch darauf hingewiesen, jetzt ist die Signatur der Methode, die aufgerufen werden soll, ist beschlossen, zur compile-Zeit.
Überlastung methodenauswahl zur Compile-Zeit
Den Java Language Specification (JLS) in Abschnitt 15.12 Method Invocation Expressions erklärt im detail den Prozess, den der compiler folgt, um zu wählen Sie die richtige Methode aufrufen.
Gibt es, Sie werden feststellen, dass dies ein compile-Zeit Aufgabe. Die JLS sagt in Abschnitt 15.12.2:
In der Regel, varargs-Methoden sind das Letzte gewählt, wenn Sie im Wettbewerb mit anderen Kandidaten-Methoden, weil Sie weniger spezifisch als diejenigen, die die selben parameter Typ.
Überprüfen Sie die compile-Zeit die Natur dieser, können Sie den folgenden test.
Deklarieren Sie eine Klasse wie diese und kompilieren Sie es.
Deklarieren Sie eine zweite Klasse, ruft die Methode auf den ersten ein und kompilieren Sie es.
Wenn man sich auf die wichtigsten, die Ausgabe sagt
Number
.Fügen Sie nun eine zweite, mehr spezifische überlastet Methode, um die
ChooseMethod
Klasse, und kompilieren Sie es (aber nicht neu kompilieren, die andere Klasse).Wenn Sie das Haupt wieder, der Ausgang ist noch
Number
.Grundsätzlich, weil es wurde beschlossen, zur compile-Zeit. Wenn Sie kompilieren Sie die
MethodChooser
Klasse (mit main), und das Programm erneut ausführen, wird die AusgabeInteger
.Als solche, wenn Sie erzwingen möchten, dass die Auswahl von einem der überladenen Methoden, die den Typ der Argumente muss übereinstimmen mit der Art der Parameter, die zur Kompilierzeit und nicht erst zur Laufzeit.
Überschreiben methodenauswahl zur Laufzeit
Wieder, die Signatur der Methode ist beschlossen, zur compile-Zeit, aber die tatsächliche Umsetzung entschieden wird, zur Laufzeit.
Deklarieren Sie eine Klasse wie diese und kompilieren Sie es.
Dann deklarieren Sie eine zweite Erweiterung der Klasse und kompilieren:
Und in der MethodChooser Klasse, die Sie tun:
Und wenn Sie es ausführen, erhalten Sie die Ausgabe
Number A
, und das ist Ok, weil die Methode wurde nicht überschrieben, inChooseMethodB
und damit die Umsetzung aufgerufen wird, ist, dass derChooseMethodA
.Fügen Sie nun eine Methode überschrieben, die in
MethodChooserB
:Und neu kompilieren nur diese eine, und führen Sie die main-Methode wieder.
Nun, Sie bekommen die Ausgabe
Number B
Als solche, die Umsetzung wurde gewählt, zur Laufzeit, und nicht Neukompilierung des
MethodChooser
Klasse erforderlich war.Haben Sie Lesen den link, den ich gemeinsam aus der JLS? Wenn Sie nicht finden, eine Antwort werden Sie nicht finden anderswo.
Ich habe, nachdem ich den Kommentar. Das ist die definitive Referenz auf das, was der compiler tun sollte, also, das ist wirklich der link, den ich suchte. Es ist sicherlich nicht die einfachste Lesen, und ich werde wahrscheinlich versuchen, einen Stich an, kommen mit einem mehr praktischen Destillation von es als etwas anderes scheint nicht zu existieren.
Es ist sicherlich einige Zeit dauert, um zu verdauen, aufgrund der formalen Sprache verwendet in den Erklärungen. Sicherlich, wenn Sie sitzen und versuchen ein paar Zeilen code, und mit etwas Geduld, in einiger Zeit könnten Sie kommen mit einem guten Kompendium von Beispielen, die es Wert ist zu teilen. Ich denke, ich würde lieben, Sie zu sehen und Sie würde sich lohnen, einen post in einem blog oder hier als Antwort auf deine eigene Frage.
Zweite mutigen Titel sollte Überlastung methodenauswahl zur Compile-Zeit.
InformationsquelleAutor Edwin Dalorzo
Erste Frage:
Ihre Annahme richtig ist. Der zweite Aufruf
f()
rufen die varargs-Methode. Sie können den compiler zu nennen, die zweite Methode mit:Zweite Frage:
Ja. Sie können jedoch nicht erweitern eine Schnittstelle. Wenn Sie ändern
A
um eine abstrakte Klasse ist, die Dinge zusammenzustellen.f(a, new int[0]);
InformationsquelleAutor gobernador