Überladene Methode-Auswahl, basierend auf dem parameter den Typ real
Ich experimentiere mit diesem code:
interface Callee {
public void foo(Object o);
public void foo(String s);
public void foo(Integer i);
}
class CalleeImpl implements Callee
public void foo(Object o) {
logger.debug("foo(Object o)");
}
public void foo(String s) {
logger.debug("foo(\"" + s + "\")");
}
public void foo(Integer i) {
logger.debug("foo(" + i + ")");
}
}
Callee callee = new CalleeImpl();
Object i = new Integer(12);
Object s = "foobar";
Object o = new Object();
callee.foo(i);
callee.foo(s);
callee.foo(o);
Diese Drucke foo(Object o)
drei mal. Ich erwarte, dass die Methode der Auswahl in Betracht zu ziehen, die tatsächlichen (nicht deklariert) parameter Typ. Bin ich etwas fehlt? Gibt es eine Möglichkeit, diesen code ändern, so dass es gedruckt werden foo(12)
, foo("foobar")
und foo(Object o)
?
InformationsquelleAutor Sergey Mikhanov | 2009-10-15
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja. Ihre Erwartung ist falsch. In Java dynamische Methode dispatch geschieht nur für das Objekt die Methode aufgerufen wird, nicht für die parameter-Typen mit überladenen Methoden.
Unter Berufung auf die Java Language Specification:
Worden: die compile-Zeit-Typ der Parameter der Methode wird verwendet, um die Signatur der Methode aufgerufen werden, in diesem Fall
foo(Object)
. Zur Laufzeit wird die Klasse der - Objekt die Methode aufgerufen wird legt fest, welche Implementierung der Methode aufgerufen wird, unter Berücksichtigung, dass es möglicherweise eine Instanz einer Unterklasse des deklarierten Typs, überschreibt die Methode.InformationsquelleAutor Michael Borgwardt
Wie bereits erwähnt überlastung Auflösung erfolgt zur compile-Zeit.
Java-Teilnehmer hat ein schönes Beispiel für:
Puzzle-46: Der Fall der Verwirrenden Konstruktor
Dieses puzzle stellt Ihnen mit zwei Verwirrend Konstruktoren. Die main Methode ruft einen Konstruktor,
aber welche? Die Ausgabe des Programms hängt von der Antwort. Was bedeutet das Programm drucken, oder ist es
auch legal?
Lösung 46: Fall der Verwirrenden Konstruktor
...
Java ist überlast-resolution-Verfahren arbeitet in zwei Phasen. Die erste phase wählt alle Methoden oder Konstruktoren, die sind zugänglich und anwendbar. Die zweite phase wählt die die meisten spezifischen der Methoden oder Konstruktoren ausgewählt, die in der ersten phase. Eine Methode oder ein Konstruktor ist weniger spezifische als eine andere, wenn Sie können, akzeptieren Sie keine Parameter übergeben, um die anderen [JLS 15.12.2.5].
In unserem Programm, die beiden Konstruktoren sind zugänglich und anwendbar. Der Konstruktor
Verwirrend(Objekt) akzeptiert keine parameter übergeben Verwirrend(double[]), so
Verwirrend(Objekt) ist weniger spezifisch. (Jeder double array ist ein Objekt, aber nicht jeder Objekt ist ein double array.) Die meisten spezifischen Konstruktor ist daher Verwirrend(double[]), die erklärt, die Ausgabe des Programms.
Dieses Verhalten macht Sinn, wenn Sie übergeben einen Wert vom Typ double[]; es ist widersprüchlich, wenn Sie pass null. Der Schlüssel zum Verständnis dieses Puzzles ist, dass der test für die Methode oder der Konstruktor ist am bestimmten nicht die tatsächlichen Parameter: die Parameter erscheinen in der Aufruf.
Sie werden nur verwendet, um zu bestimmen, welche überbeanspruchungen kommen, sind anwendbar. Sobald der compiler legt fest, welche überbeanspruchungen kommen, sind anwendbar und zugänglich ist, wählt es den meisten spezifischen überlastung, Verwendung nur der formale Parameter: die Parameter erscheinen in der Erklärung.
Aufrufen der Verwirrend(Objekt) Konstruktor mit einem null parameter, schreiben neue
Verwirrend((Object)null). Dies gewährleistet, dass nur Verwirrend(Objekt) anwendbar ist. Mehr
in der Regel, um den compiler zu zwingen wählen Sie eine bestimmte überlastung, cast tatsächlichen Parameter der deklarierten Typen der formalen Parameter.
Es ist nie zu spät für gute Worte 🙂
Ich glaube, wenn wir auch Hinzugefügt der Konstruktor "private Verwirrend(int[] iArray)" es würde nicht kompilieren, wäre es nicht? Denn jetzt gibt es zwei Konstruktoren, die mit der gleichen Spezifität.
+1 für die "spezifischen" -> alles, was ich wissen musste 🙂
Wenn ich dynamic return-Typen als Funktion der Eingabe, es verwendet immer die weniger spezifischen... sagte, dass die Methode, die verwendet werden kann für alle möglichen Werte zurückgeben...
InformationsquelleAutor denis.zhdanov
Fähigkeit zum Versand, ein Aufruf einer Methode basierend auf den Typen der Argumente wird aufgerufen,multiple dispatch. In Java wird dies mit Besucher-Muster.
Jedoch, da Sie den Umgang mit
Integer
s undString
s, Sie können leicht integrieren Sie dieses Muster (das kann man einfach nicht ändern, diese Klassen). So ein Riesenswitch
auf Objekt-Laufzeit wird Ihre Waffe der Wahl.InformationsquelleAutor Anton Gogolev
In Java die Methode zu nennen (wie in der Signatur der Methode zu verwenden) wird ermittelt zur compile-Zeit, also geht es mit dem compile-Zeit-Typ.
Das typische Muster zu arbeiten, um dies zu überprüfen, der Objekt-Typ in der Methode mit der Objekt-Signatur, und delegieren Sie an die Methode mit einer Besetzung.
Wenn Sie haben viele Arten, und diese ist unüberschaubar, dann ist die Methode überladen ist wahrscheinlich nicht der richtige Ansatz, eher die öffentliche Methode sollte nur Objekt und zu implementieren eine Art von Strategie-Muster zu delegieren, den angemessenen Umgang mit pro Objekttyp.
InformationsquelleAutor Yishai
Ich hatte ein ähnliches Problem mit dem Aufruf der richtigen Konstruktor einer Klasse namens "Parameter" können verschiedene grundlegende Java-Typen wie String, Integer, Boolean, Long, etc. Gegeben ein array von Objekten, ich möchte konvertieren Sie Sie in ein array von meinen Parameter-Objekte durch Aufruf der meisten-spezifischen Konstruktor für jedes Objekt in der Eingabe-array. Ich wollte auch zum definieren der Parameter des Konstruktors(Object o) , wirft eine IllegalArgumentException. Ich natürlich gefunden, dass diese Methode aufgerufen wird für jedes Objekt in meinem array.
Die Lösung, die ich verwendet wurde, um die Konstruktor über reflection...
Nicht hässlich instanceof -, switch-Anweisungen oder Besucher-Muster erforderlich! 🙂
InformationsquelleAutor Alex Worden
Java sieht auf den Typ der Referenz, wenn Sie versuchen, um festzustellen, welche Methode zu nennen. Wenn Sie erzwingen möchten, dass Ihr code wählen Sie die 'richtige' Methode, Sie können erklären, Ihre Felder als Instanzen des bestimmten Typs:
Könnte man auch werfen Sie Ihre params, wie der Typ des param:
InformationsquelleAutor akf
Wenn es eine exakte übereinstimmung zwischen der Anzahl und Typen der Argumente angegeben in der Methodenaufruf und die Methode, die Signatur der überladenen Methode dann, dass ist die Methode, die aufgerufen wird. Sie sind mit Objekt-Referenzen, also java entscheidet zur compile-Zeit, die für das Objekt param, es ist eine Methode, die direkt akzeptiert-Objekt. So wird es genannt, dass die Methode 3 mal.
InformationsquelleAutor Ashish Thukral