Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Hallo,
ich habe mir eine kleine Klasse geschrieben, mit der ich etwas komfortabler mit Kommandozeilenargumenten umgehen kann. Bisher konnte sie nur Stringparameter zurückgeben. Jetzt habe ich mir überlegt, dass ich die Methode überlagere und somit auch die Übergabe von int-Parametern ermögliche:
Java:
:
public String Argument(String selektor) { // Selektor suchen
int p = this.argumente.indexOf(selektor.trim());
if (p < 0) { // nicht gefunden
return "";
}
return this.argumente.substring(p + selektor.length(), this.argumente.indexOf(' ', p)).trim();
}
public int Argument(String selektor) {
int p = this.argumente.indexOf(selektor.trim());
if (p < 0) { // nicht gefunden
return 0;
}
return Integer.parseInt(this.argumente.substring(p + selektor.length(), this.argumente.indexOf(' ', p)).trim());
}
:
Obwohl die beiden Methodenheader gleich sind, weist der Compiler die Klasse ab.
Was mache ich falsch ?
Danke
Hi,
Wäre es nicht einfach immer den String einzulesen und als Ersatz im eigentlichen Programm eine Funktion zu schreiben, die versucht den String in einen Int zu parsen, schlägt das fehl wird der User wieder nach einem Int gefragt, solange bis er einen gültigen eingibt.
Gruß
Das stimmt nicht ganz. Die JVM kann Methoden sehr wohl nach dem Rückgabewert unterscheiden, und Java nutzt das an einer Stelle: Bei "synthetisch" generierten (oder "Brücken-") Methoden, die der Compiler einfügt, um Generics zum Laufen zu bekommen (ich kann auf Wunsch die gruseligen Details nachschlagen). Nur uns Normalsterblichen bleibt dieser Luxus verwehrt - Quod licet Iovi, non licet bovi...
Klar kann ich beim Aufrufer das Ergebnis wandeln, aber dass muss ich dann an vielen Stellen machen.
Schade, dass der Rückgabewert nicht zur Signatur der Methode zählt. Wäre irgendwie eleganter. So könnte je nach Methodenaufruf ein passender Typ zurückgegeben werden.
Danke
Hi,
wenn du das an vielen Stellen machen musst, warum schreibst du dir dann nicht eine Methode, die die andere Kapselt?
Ob du dann deine normale einlesen verwendest oder die Methode die erst einlesen aufruft und das Ergebnis in einen int konvertiert gibt sich doch nichts?
Gruß
Man kann mit Generics einen flexiblen Rückgabewert "simulieren" - aber wegen Type Erasure nur, wenn man den korrekten Typ irgendwie aus den Argumenten ermitteln kann (notfalls durch Übergabe eines [c]java.lang.Class[/c]-Objekts). Beispiel:
Java:
public class ReturnValue {
public static <T> T argument(String selector) {
if (selector.equals("integer")) return (T) Integer.valueOf(42);
if (selector.equals("string")) return (T) "answer";
return null;
}
public static void main(String[] args) {
String s = argument("string");
int i = argument("integer");
System.out.println(s + " " + i);
}
}
Falls es sich dabei nicht um externe Daten (wie z.B. ein geparstes File) handelt, deutet die Notwendigkeit für solche Hacks allerdings auf ein Designproblem hin.
Hier die versprochenen Details zu Brückenmethoden. Es gibt welche für covariante Rückgabetypen:
Zusätzlich zur covarianten überschriebenen Methode fügt der Compiler in die Subklasse jede der überschriebenen Methoden mit dem Return-Type der Supertypen hinzu. Diese rufen dann in der return-Anweisung die contravarianten Methoden mit den aktuellen Argumenten auf
(Java 5 im Einsatz, Friedrich Esser, Galileo Computing, S. 78)
Hat man also sowas:
Java:
interface Foo {
Number get();
}
class FooImpl implements Foo {
Integer get() { return 42; }
}
... dann findet man in der decompilierten Klasse von FooImpl eine zweite get-Methode [c]Number get(){ return get(); }[/c], wobei das darin aufgerufene get die covariante Methode (mit dem Rückgabetyp Integer) ist. Wie gesagt kann die JVM beide Versionen unterscheiden.
Dann gibt es Bridge-Methoden bei generischen Hierarchien:
Der Compiler fügt für alle Methoden der Supertypen eines Subtyps D Bridge-Methoden in D ein, wenn
- D die Methoden dieser Supertypen direkt mit einem anderen Raw-Type überschreibt.
- in D die Methoden dieser Supertypen zwar nicht direkt überschrieben werden, aber mit einem anderen Raw-Type aufgerufen werden kann (d.h. diese Methode nicht abstract ist)
Der Type einer Bridge-Methode ist der des Raw-Types der Superklasse, die die überschriebene Methode als letzte implementiert oder deklariert hat. In der Methode werden evt. vorhandene generische Argumente zum Raw-Type des Subtypen gecastet und - sofern vorhanden - die Subtyp-Methode aufgerufen oder ansonsten die Supertyp-Methode
Ich will eigentlich nicht genauer über diese Sätze nachdenken. Fakt ist, es gibt Brücken-Methoden, und da diese direkt vom Compiler eingefügt werden, unterliegen diese nicht den Beschränkungen, dass eine Methoden-Auflösung den Rückgabewert nicht berücksichtigen darf, sondern nutzen dieses Feature aus. Das erklärt auch, warum man Name-Clashes mit Methoden bekommen kann, die man gar nicht in der Klasse definiert hat - man ist auf eine Brücken-Methode gestoßen.