einen Vector auslesen
Hannes
- java
0 Axel Richter0 Hannes0 Martin Jung0 Slyh0 Martin Jung0 Slyh0 Martin Jung0 Slyh
hi all,
ich belege den Vector mit Strings und will ihn anschließend auslesen.
Wenn ich println benutze geht alles, aber wenn ich den Vectorinhalt in eine Variable vom Typ String schreibe geht es nicht.
Ihr habt bestimmt ne IDEE ...
private Vector fErrorLog = new Vector();
if (fErrorLog.size() > 0) {
System.out.println("------------------------------------------ ERRORS ------------------------------------------");
for (int i = 0; i < fErrorLog.size(); i++) {
System.out.println(fErrorLog.get(i));
}
System.out.println("--------------------------------------------------------------------------------------------");
}
Hallo,
ich belege den Vector mit Strings und will ihn anschließend auslesen.
Wenn ich println benutze geht alles, aber wenn ich den Vectorinhalt in eine Variable vom Typ String schreibe geht es nicht.private Vector fErrorLog = new Vector();
if (fErrorLog.size() > 0) {
System.out.println("------------------------------------------ ERRORS ------------------------------------------");for (int i = 0; i < fErrorLog.size(); i++) {
System.out.println(fErrorLog.get(i));
}System.out.println("--------------------------------------------------------------------------------------------");
}
Es wäre zwar besser gewesen, Du hättest den Code gepostet, der _nicht_ funktioniert, aber ich denke mal, Du hast nicht beachtet, dass in Collections nur Elemente der Klasse Object abgelegt werden. Die Methode get(int index) gibt deshalb ein Object zurück. Du musst es in einen String casten.
String str = new String();
for (int i = 0; i < fErrorLog.size(); i++) {
str = str.concat((String)fErrorLog.get(i));
}
Gruß
Axel
hi Axel,
danke für Deine Hilfe!
Gruß Hannes
Hi,
Es wäre zwar besser gewesen, Du hättest den Code gepostet, der _nicht_ funktioniert, aber ich denke mal, Du hast nicht beachtet, dass in Collections nur Elemente der Klasse Object abgelegt werden. Die Methode get(int index) gibt deshalb ein Object zurück. Du musst es in einen String casten.
1. Sollte man aus Performancegründen in diesem Falle einen StringBuffer (dieser ist im Gegensatz zu String-Objekten mutable) verwenden.
2. Sollte auch der direkte Aufruf von toString() funktionieren, da dieser immer einen String zurückgibt und man sich den Cast erspart - im Falle der Klasse String eine Referenz auf das String-Objekt selbst ('return this'):
Beispiel:
StringBuffer buf = new StringBuffer();
for (int i = 0; i < fErrorLog.size(); i++) {
buf.append((fErrorLog.get(i).toString());
}
Gruß
Axel
Viele Grüße,
Martin Jung
Hallo,
- Sollte man aus Performancegründen in diesem Falle einen StringBuffer (dieser ist im Gegensatz zu String-Objekten mutable) verwenden.
Nein! Wieso? Will er den String ändern? Nein. Wieso sollte er dann
StringBuffer verwenden?
- Sollte auch der direkte Aufruf von toString() funktionieren, da dieser immer einen String zurückgibt und man sich den Cast erspart - im Falle der Klasse String eine Referenz auf das String-Objekt selbst ('return this'):
Nein, man sollte das ganz sicher nicht so tun! Was ist, wenn er
irgendwo einen Programmierfehler hat und nun statt einem String
weißnicht ein Integer-Objekt in den Vector geschrieben hat. Ein
toString() würde für den Integer funktionieren.
Bei einem Cast würde - wie gewünscht - eine ClassCastException geworfen.
Du erkaufst dir mit deinem toString() eine schwer auffindbare
Fehlerquelle!
Übrigens ist die toString()-Version sogar langsamer als die Version
mit dem Cast, wie folgender Code beweist:
Vector v = new Vector();
v.add("Hubbabubba");
String s;
System.out.println(System.currentTimeMillis());
for (int i = 0; i < 1000000000; i++) {
s = (String)v.get(0);
}
System.out.println(System.currentTimeMillis());
for (int i = 0; i < 1000000000; i++) {
s = v.get(0).toString();
}
System.out.println(System.currentTimeMillis());
Die Schleife mit dem Cast benötigt ca. 25 Sekunden. Die Schleife mit
dem toString()-Aufruf dagegen ca. 33 Sekunden. Damit ist deine als
besser propagierte Lösung fehleranfälliger und 33%(!) langsamer!
Gruß
Slyh
Hi,
Nein! Wieso? Will er den String ändern? Nein. Wieso sollte er dann StringBuffer verwenden?
Aus Performancegründen (wie ich begründet habe) - Beispiel:
import java.util.Vector;
/** * @version 0.1 * * @history 17.01.2003 Martin Jung created * * @author <a href="mailto:junmar@web.de">Martin Jung</a> */ public class StringPerformance {
static int length = 100000; static String[] arr = new String[length]; static String result = ""; static long begin, lap; static String NL = System.getProperty("line.separator");
static { for (int i = 0; i < arr.length; i++) { arr[i] = new String("a"); // assure to have disctinct String objects if (i > 0) { if (arr[0] == arr[i]) { System.out.println("Exit because no distinct String object" + " at position:" +i); System.exit(1); } } } System.out.println("created object of type " +StringPerformance.class+ " with " +length+ " String objects" +NL); }
public static void main(String[] arguments) { concat(); stringBuffer(); cast(); instanceOf(); }
public static void concat() {
System.out.println("entering concat()..."); // for-Schleife entfaltet result = arr[0] .concat(arr[1]) // 1. temporäres String Object .concat(arr[2]) // 2. temporäres String Object .concat(arr[3]); /* das bedeutet: für n Konkatenierungen mit .concat() werden (unnötigerweise) n-1 temporäre String Objekte kreiert, die dann wieder 'GC'-ed werden (müssen)! Darunter dürfte sowohl die Performance leiden als auch das Speicherprofil */
// test begin = System.currentTimeMillis(); for (int i = 0; i < arr.length; i++) { result = result.concat(arr[i]); } lap = System.currentTimeMillis() - begin; System.out.println("concat(): " +lap+ " msec" +NL); }
public static void stringBuffer() {
System.out.println("entering stringBuffer()..."); StringBuffer buf = new StringBuffer();
// test begin = System.currentTimeMillis(); for (int i = 0; i < arr.length; i++) { buf = buf.append(arr[i]); } result = buf.toString(); lap = System.currentTimeMillis() - begin; System.out.println("stringBuffer(): " +lap+ " msec" +NL); }
public static void cast() {
System.out.println("entering cast()"); Vector v = new Vector(); v.add("Hubbabubba"); int max = length * 100; String s; System.out.println("now using " +max+ " String objects...");
begin = System.currentTimeMillis(); for (int i = 0; i < max; i++) { s = v.get(0).toString(); } lap = System.currentTimeMillis() - begin; System.out.println("toString: " +lap+ " msec");
begin = System.currentTimeMillis(); for (int i = 0; i < max; i++) { s = (String)v.get(0); } lap = System.currentTimeMillis() - begin; System.out.println("cast: " +lap+ " msec" +NL); /* Du hast Recht (mit JDK 1.3.1) - allerdings dürfte dieser * Performanceeffekt besonders von der VM-Implementierung abhängen. */ }
public static void instanceOf() {
System.out.println("entering instanceOf()"); Vector v = new Vector(); v.add("Hubbabubba"); int max = length * 100; String s; System.out.println("now using " +max+ " String objects...");
begin = System.currentTimeMillis(); for (int i = 0; i < max; i++) { s = (String)v.get(0); } lap = System.currentTimeMillis() - begin; System.out.println("cast ohne type check: " +lap+ " msec");
Object obj; begin = System.currentTimeMillis(); for (int i = 0; i < max; i++) { obj = v.get(0); if (obj instanceof String) { s = (String) obj; } } lap = System.currentTimeMillis() - begin; System.out.println("cast mit type check: " +lap+ " msec"); /* Du hast Recht (mit JDK 1.3.1) - allerdings dürfte dieser * Performanceeffekt besonders von der VM-Implementierung abhängen. */ } }
Nein, man sollte das ganz sicher nicht so tun! Was ist, wenn er irgendwo einen Programmierfehler hat und nun statt einem String weißnicht ein Integer-Objekt in den Vector geschrieben hat. Ein toString() würde für den Integer funktionieren.
Hannes deklarierte: private Vector fErrorLog = new Vector();
Daraus schloss ich spekulativ, der Programmierer beabsichtigt dem Vektor werden ausschließlich String Objekte hinzuzufügen und macht dies auch (der 'private' access modifier ließ mich zusätzlich vermuten, der Vektor stellt ein internes Member dar).
Bei einem Cast würde - wie gewünscht - eine ClassCastException geworfen.
Wieso ist das erwünscht? Ob eine ClassCastException geworfen werden soll, ist eine Designentscheidung. Diese würde ich variabel treffen:
Entwicklung: Ein expliziter Cast hilft, um Programmierfehler aufzudecken. Sollte es sich weiterhin um einen gänzlich privaten Member halten (ohne Getter/Setter), wäre der cast - wie von Dir gezeigt - die performantere Lösung (zumindest mit JDK 1.3.1). Anmmerkung: wenn der (private) Vector hingegen über eine publizierte API (Getter/Setter) zugänglich gemacht wird/werden soll, ist der cast zwar immer noch performanter, verhindert aber nicht, dass irgendjemand folgendes in seinem Code folgendes schreibt:
BesagtesObjekt obj = new BesagterObjekt(); Vector v = obj.gibMirErrorLogVector(); v.add(Integer.toString(5));
Du erkaufst dir mit deinem toString() eine schwer auffindbare Fehlerquelle!
Warum schwer auffindbar? Ich sollte die Stelle meines Codes kennen, an dem die Log-Infos assembliert werden. Also weiß ich, wo ich einen Breakpunkt zu setzen habe, starte den Debugger und sollte die Fehlerursache (relativ - diese Einschränkung gilt beim Entwanzen ja prinzipiell ;-)) ) schnell gefunden haben.
Übrigens ist die toString()-Version sogar langsamer als die Version mit dem Cast, wie folgender Code beweist:
Du hast Recht - siehe Beispielcode. Ich denke allerdings, dass dieser Performanceunterschied von der Implementierung der VM abhängt (während der Performanceunterschied wzischen String.concat() und StringBuffer.append() primär durch die Spezifikation begründet ist - wobei eine VM-Implementierung natürlich genau diesbezüglich besonders optimiert sein könnte)
Viele Grüße, Martin Jung
Hallo,
Wieso sollte er dann StringBuffer verwenden?
Aus Performancegründen (wie ich begründet habe)
Ja, aber der Performancevorteil tritt ja nur dann auf, wenn der
String selbst verändert wird. (Wie ich begründet habe.)
Dann darfst du gerne StringBuffer verwenden. Aber wieso hier? Macht
die Sache doch nur viel aufwendiger. Außerdem hat man nicht den
schönen Vorteil, daß Strings intern effizient verwaltet werden.
Beispiel:
int count = 500000;
String[] sa = new String[count];
System.out.println(System.currentTimeMillis());
for (int i = 0; i < count; i++) {
sa[i] = new String("Hubbabubba");
}
System.out.println(System.currentTimeMillis());
StringBuffer[] sb = new StringBuffer[count];
for (int i = 0; i < count; i++) {
sb[i] = new StringBuffer("Hubbabubba");
}
System.out.println(System.currentTimeMillis());
Das Anlegen der String-Objekte ist ca. um den Faktor 4 schneller.
Ich würde außerdem behaupten, daß in diesem - zugegebenermaßen
sehr spezialisiertem Beispiel - weit weniger Speicher verbraucht wird.
Aber das konnte ich jetzt leider nicht nachweisen.
public static void concat() {
System.out.println("entering concat()...");
// for-Schleife entfaltet
result = arr[0]
.concat(arr[1]) // 1. temporäres String Object
.concat(arr[2]) // 2. temporäres String Object
.concat(arr[3]);
/* das bedeutet: für n Konkatenierungen mit .concat() werden
(unnötigerweise) n-1 temporäre String Objekte kreiert,
die dann wieder 'GC'-ed werden (müssen)!
Darunter dürfte sowohl die Performance leiden als auch das
Speicherprofil */
Richtig. Allerdings änderst du hier wieder einen String. In diesem Fall
verwendet man - wie du und ich ja korrekt gesagt festgestellt haben -
besser einen StringBuffer. Genau dafür ist er ja da.
Darum ging's aber ja nicht.
public static void cast() {
[...]
/* Du hast Recht (mit JDK 1.3.1) - allerdings dürfte dieser
* Performanceeffekt besonders von der VM-Implementierung abhängen.
*/
}
Auch mit JDK 1.4.1 und vermutlich allen vorangegangenen JVMs. :-)
Der Grund ist vermutlich einfach der, daß ein Cast viel weniger
Overhead erzeugt als ein Methodenaufruf (->toString). Natürlich hängt
das von der VM-Implementierung ab. Aber was hängt nicht von der
Implementierung ab? Wenn du Leute beim Implementieren eines Casts
Schrott programmieren, wird das natürlich langsam. Wenn die Leute
beim Implementieren von StringBuffer.append() Schrott bauen und
beispielsweise temporäre String-Objekte verwenden würden, wäre append()
auch langsamer. ;-)
Nein, man sollte das ganz sicher nicht so tun! Was ist, wenn er
irgendwo einen Programmierfehler hat und nun statt einem String
weißnicht ein Integer-Objekt in den Vector geschrieben hat. Ein
toString() würde für den Integer funktionieren.
Hannes deklarierte:
private Vector fErrorLog = new Vector();Daraus schloss ich spekulativ, der Programmierer beabsichtigt dem Vektor werden ausschließlich String Objekte
hinzuzufügen und macht dies auch
Zweifellos.
(der 'private' access modifier ließ mich zusätzlich
vermuten, der Vektor stellt ein internes Member dar).
Naja, mich nicht. Möglich wär's aber. :-)
Darum ging es mir aber nicht. Es ging mir allgemein um die Verwendung
von toString statt einem explizitem Cast. Wenn das Programm ne Nummer
größer ist, etwas komplexer und evtl. sogar von fremden Programmierern
verwendet wird, könnte es passieren - und das halte ich nicht für zu
praxisfern - daß statt einem String eben irgend ein anderer Objekt-
Typ versehentlich(!) zum Vector geaddet wird. Vielleicht aus Unacht-
samkeit. Vielleicht weil die Namen ähnlich sind. Jedenfalls funktioniert
die toString()-Variante anschließend noch, obwohl sie das nicht
sollte, weil eben kein Cast erfolgt, sondern weil toString() für
jedes Objekt exisiert.
Beispiel:
Ich habe eine Klasse XmlParser. Diese hat eine Methode "getError()".
Nun ist ein Fehler aufgetreten und ich möchte diesen loggen, will
also
fErrorLog.add(xmlParser.getError());
schreiben, schreibe aber versehentlich
fErrorLog.add(xmlParser);
stattdessen.
Später gebe ich den ErrorLog aus oder verarbeite ihn (oder wasauchimmer)
und wundere mich, wieso da nun irgendwelcher Schrott ausgegen wird.
Ich muß die Fehlerstelle suchen usw.
Würde ich einen expliziten Cast durchführen, würde ich zur Laufzeit
eine Exception an der entsprechenden Stelle erhalten, könnte dort
Debuggen (intelligente IDEs können sogar einen Breakpoint auf
beliebige Exceptions setzen) und würde sofort den Fehler bemerken.
(Zugegebenermaßen ist das Beispiel an den Haaren herbeigezogen. Aber
ich hoffe, es wurde klar was ich sagen wollte.)
Bei einem Cast würde - wie gewünscht - eine ClassCastException geworfen.
Wieso ist das erwünscht? Ob eine ClassCastException geworfen werden soll, ist eine Designentscheidung.
Richtig. Es wäre ein besserers Design wenn der Fehler nicht einfach
geschluckt wird, indem ein toString() verwendet wird, das (wie gesagt)
noch dazu langsamer ist. :-)
Entwicklung:
Ein expliziter Cast hilft, um Programmierfehler aufzudecken.
Meine Rede.
Anmmerkung: wenn der (private) Vector hingegen über eine
publizierte API (Getter/Setter) zugänglich
gemacht wird/werden soll, ist der cast zwar immer noch
performanter, verhindert aber nicht, dass irgendjemand folgendes
in seinem Code folgendes schreibt:BesagtesObjekt obj = new BesagterObjekt();
Vector v = obj.gibMirErrorLogVector();
v.add(Integer.toString(5));
Ich habe auch nicht gesagt, daß es das verhindert. Ich habe nur gesagt,
daß das Programm dadurch schlechter wartbar und langsamer wird.
Wenn du einen Setter verwendest, kann sowas natürlich nicht mehr
passieren. Hier würde sogar ein Fehler während des Kompilierens auf-
treten. -> Beste Lösung.
Ich fasse nochmal zusammen:
* Deine Lösung: Keine Fehlermeldung
* Meine Lösung: Fehlermeldung bei Laufzeit
* Mit Setter: Fehlermeldung beim Kompilieren
- Produktivversion:
[...] definitiv _keine_ ClassCastException zulassen.
Warum:
a) eine RuntimeException führt zum Programmabbruch (- sofern sie nicht abgefangen wird)
b) Das unbeabsichtigte Loggen von Informationen (irgendwelchen String-Objekten) rechtfertigt in keinem Falle einen Programmabbruch.
c) Aufgrund der Performancetests würde ich dieses dann durch einen cast mit vorangegangener Typprüfung gewährleisten.
Hier gebe ich dir in allen Punkten recht. In einer Produktversion
wäre ein toString() (bzw. die instanceof-Sache) besser, da nur
harmloser Schrott geloggt wird, dafür kein Programmabbruch erfolgt.
Dafür erfolgt während des Testens keine Exception. Der Fehler würde
damit beim Testen tendenziell weniger wahrscheinlich gefunden werden,
als wenn eine Exception auftritt.
Du erkaufst dir mit deinem toString() eine schwer auffindbare
Fehlerquelle!
Warum schwer auffindbar? Ich sollte die Stelle meines Codes kennen, an dem die Log-Infos assembliert werden.
Jein. Das trifft auf kleine Programme zu. Sobald das Projekt etwas
größer wird, weißt du das evtl. nicht mehr so ohne weiteres.
Wie oben beschrieben, bist du mit einer Exception auf jeden Fall
schneller am Ziel. Vermutlich brauchst du nicht mal einen Debugger.
Aber ich gebe dir recht. Es dürfte sich vom Aufwand nicht zu sehr
unterscheiden.
Fazit: Der Cast ist schneller und während der Entwicklung hilfreich -
auch beim Testen. toString() ist für das fertige Produkt wünschenswert,
weil damit (harmloser) Schrott geloggt wird, das Programm aber nicht
gleich stirbt. Dafür übersieht man den Fehler evtl. beim Testen.
Besser wäre natürlich die konsequente Verwendung von Properties.
Dann könnte sowas gleich gar nicht passieren.
Solange aber hier keine verwendet werden, halte ich meinen Ansatz
persönlich für besser, kann aber auch gut verstehen und nachvollziehen, wenn du deinen für besser hälst. :-)
Gruß
Slyh
Hi Slyh,
bin etwas in Hektik...
Ja, aber der Performancevorteil tritt ja nur dann auf, wenn der
String selbst verändert wird. (Wie ich begründet habe.)
Dann darfst du gerne StringBuffer verwenden. Aber wieso hier? Macht
die Sache doch nur viel aufwendiger. Außerdem hat man nicht den
schönen Vorteil, daß Strings intern effizient verwaltet werden.
Da hätte ich in meiner Antwort evtl nochmals betonen sollen, dass ich mich nicht auf Hannes' ursprüngliches Beispiel (System.out.println(v.get(.....),) sondern auf auf Axel's Antwort/Vorschlag bezog.
Mein Ansatz bestand darin, in der Iteration zunächst mit Hilfe eines StringBuffers den gesamten Ausgabestring zu assemblieren und dann mit einer println-Anweisung auszugeben.
Das Anlegen der String-Objekte ist ca. um den Faktor 4 schneller.
Ich würde außerdem behaupten, daß in diesem - zugegebenermaßen
sehr spezialisiertem Beispiel - weit weniger Speicher verbraucht wird.
Siehe obige Bemerkung meiner ursprünglichen Intention,
Aber das konnte ich jetzt leider nicht nachweisen.
Das geht ohne Profiler (die direkten Zugriff auf die VM haben) leider nicht wirklich.
Richtig. Allerdings änderst du hier wieder einen String. In diesem Fall
verwendet man - wie du und ich ja korrekt gesagt festgestellt haben -
besser einen StringBuffer. Genau dafür ist er ja da.
Darum ging's aber ja nicht.
Siehe oben.
Auch mit JDK 1.4.1 und vermutlich allen vorangegangenen JVMs. :-)
Der Grund ist vermutlich einfach der, daß ein Cast viel weniger
Overhead erzeugt als ein Methodenaufruf (->toString).
Offensichtlich.
Natürlich hängt
das von der VM-Implementierung ab. Aber was hängt nicht von der
Implementierung ab?
Die Tatsache, dass eine Stringverkettung mit .concat() (nochmals: darauf bezog ich mich ;-))) ) unnötige
String-Objekte erzeugt, da es durch die Spezifikation/Core APIs ja vorgegeben ist. Deswegen schrieb ich auch ' ... _besonders_ von der VM-Implementierung abhängen...'.
Wenn du Leute beim Implementieren eines Casts
Schrott programmieren, wird das natürlich langsam. Wenn die Leute
beim Implementieren von StringBuffer.append() Schrott bauen und
beispielsweise temporäre String-Objekte verwenden würden, wäre append()
auch langsamer. ;-)
Dieses Argument schlug mich nun zu Tode.... ;-)
Darum ging es mir aber nicht. Es ging mir allgemein um die Verwendung
von toString statt einem explizitem Cast. Wenn das Programm ne Nummer
größer ist, etwas komplexer und evtl. sogar von fremden Programmierern
verwendet wird, könnte es passieren - und das halte ich nicht für zu
praxisfern - daß statt einem String eben irgend ein anderer Objekt-
Typ versehentlich(!)
Das ist ja die Krux an der Generizität. Kann man das hinzufügen eines Objects zu einem Vector
als versehentlich bezeichen? ;-) Ich bin wirklich gespannt, ob die 'Generics' diesbezüglich insgesamt eine Erleichterung bringen werden oder nicht.
zum Vector geaddet wird. Vielleicht aus Unacht-
samkeit. Vielleicht weil die Namen ähnlich sind. Jedenfalls funktioniert
die toString()-Variante anschließend noch, obwohl sie das nicht
sollte, weil eben kein Cast erfolgt, sondern weil toString() für
jedes Objekt exisiert.
Genau das war ja meine Überlegung - ist so schön OO-isch ;-))
.... das Beispiel an den Haaren herbeigezogen. Aber
ich hoffe, es wurde klar was ich sagen wollte.)
Das war mir von Beginn an klar..
Wenn du einen Setter verwendest, kann sowas natürlich nicht mehr
passieren.
Bei .setVector(Vector a Vector) oder .setErrMsg(String aMsg)?
In der Praxis verwendet man ja sowieso Log4j.....
Jein. Das trifft auf kleine Programme zu. Sobald das Projekt etwas
größer wird, weißt du das evtl. nicht mehr so ohne weiteres.
Theorie: Auch im Team veröffentlichte APIs sollten diesbezüglich wasserdicht sein. Um bei unserem Beispiel zu bleiben: Es darf einfach keine Möglichkiet geben, außerhalb der Klasse etwas anderes als einen String dem Log-Container hinzuzufügen (im Kreise dreh...)
Fazit: Der Cast ist schneller und während der Entwicklung hilfreich -
auch beim Testen. toString() ist für das fertige Produkt wünschenswert,
weil damit (harmloser) Schrott geloggt wird, das Programm aber nicht
gleich stirbt. Dafür übersieht man den Fehler evtl. beim Testen.
Einspruch: Auf meiner Kiste var Typprüfung + cast schneller las .toString() alleine.
also:
private static final NO_MATCH_MESSAGE = "found non-String object in log vector: ";
..//..
if(obj instanceof String) {
msg = (String) v.get(i);
System.ou.println(msg); // wahlweise: buf.append(msg); ;-))
} else {
Object misMatch = v.remove(i);
v.add(i, NO_MATCH_MESSAGE + misMatch.class.getName());
i--;
}
Kleiner Scherz....
Besser wäre natürlich die konsequente Verwendung von Properties.
Dann könnte sowas gleich gar nicht passieren.
Yep.
Solange aber hier keine verwendet werden, halte ich meinen Ansatz
persönlich für besser, kann aber auch gut verstehen und nachvollziehen, wenn du deinen für besser hälst. :-)
Siehe vorher, ich _hatte_ meinen Ansatz ja bereits zu Gunsten eines performanteren verworfen...
Viele Grüße,
Martin Jung
Hallo Martin,
bin etwas in Hektik...
Dito. :-)
Mein Ansatz bestand darin, in der Iteration zunächst mit Hilfe eines StringBuffers den gesamten Ausgabestring zu assemblieren und dann mit einer println-Anweisung auszugeben.
Ooh, tatsächlich, da war ein concat() drin. Das habe ich total über-
sehen. Ups, mein Fehler.
Das ist ja die Krux an der Generizität. Kann man das hinzufügen
eines Objects zu einem Vector als versehentlich bezeichen? ;-)
Naja, in diesem speziellen Fall ja schon irgendwie.
Ich bin wirklich gespannt, ob die 'Generics' diesbezüglich
insgesamt eine Erleichterung bringen werden oder nicht.
Bisher habe ich Templates/Generics noch nie vermisst und mich deshalb
nicht damit beschäftigt (außer in C++). Mir wurde allerdings schon
von Menschen berichtet, die geflucht haben, daß es sowas in Java
nicht gibt. Naja, man wird sehen...
sollte, weil eben kein Cast erfolgt, sondern weil toString() für
jedes Objekt exisiert.
Genau das war ja meine Überlegung - ist so schön OO-isch ;-))
Findest du? Mmh, ich persönlich würde toString() höchstens für
Debug-Ausgabe (bzw. evtl. Logging) verwenden, niemals aber zur
Umsetzung von Funktionalität.
Andererseits ist natürlich richtig, daß toString() irgendwie mehr
mit Objektorientierung zu tun hat, als ein Cast.
Theorie: Auch im Team veröffentlichte APIs sollten diesbezüglich wasserdicht sein. Um bei unserem Beispiel zu bleiben: Es darf einfach keine Möglichkiet geben, außerhalb der Klasse etwas anderes als einen String dem Log-Container hinzuzufügen (im Kreise dreh...)
ACK!
Gruß
Slyh