Problem mit java.lang.reflect.Field

Status
Nicht offen für weitere Antworten.
G

Guvnor

Gast
Hallo!

Ich versuche gerade, ein Objekt komplett zu klonen. Da dies aber mit mehreren unterschiedlichen Objekten passieren muß, dachte ich, es wäre wohl am sinnvollsten, per Reflection sich alle Felder zu holen und diese dann entsprechend zu setzen.

Nur habe ich das Gefühl, die Field.get()-Methode tut nicht das, was sie tun sollte.

Laut Javadoc gibt sie mir den Wert des Feldes zurück, ich bekomme aber immer nur den Namen. Ein kleines Codebeispiel:

Code:
Field[] fields = ((Auftraege)currentRow).getClass().getFields();
                    	
for(int i=0; i<fields.length; i++)
{
    try
    {	
        System.out.println("---------------   " + fields[i].get(currentRow));
        System.out.println("---------------   " + fields[i].get(currentRow).getClass());
        System.out.println("");
    }
//  catch...
}

Okay, nun werden also alle Felder des Objekts currentRow in einem Array gespeichert. Das geh ich durch und gib mir den Wert und danach den Typ aus. Eigentlich könnte man - laut Dokumentation - nun solch eine Ausgabe erwarten:

--------------- 17
--------------- class java.lang.Integer

--------------- 23.5
--------------- class java.lang.Float

--------------- hallo wie gehts
--------------- class java.lang.String

Tatsächlich gibt er aber nicht den Wert aus, sondern den Namen des Feldes. Und folglich in der jeweils zweiten Zeile, wo die Klasse des gewünschten Wertes angezeigt werden soll, immer java.lang.String. Aber das sollte doch eigentlich gar nicht der Fall sein?

Ist nun die Doku im Eimer oder verstehe ich was falsch?
 

SnooP

Top Contributor
Ich glaub bei dir ist irgendwas im Eimer ;) ... - bei mir funktioniert folgendes wunderbar:

Code:
import java.lang.reflect.Field;

public class Test2 {

	public int x = 7;

	public String test = "testy!";


	public static void main  (String[] args) throws Exception {
		Test2 test2 = new Test2();


		Field[] fields = test2.getClass().getFields();

		for(int i=0; i<fields.length; i++)
		{
			System.out.println("---------------   " + fields[i].get(test2));
			System.out.println("---------------   " + fields[i].get(test2).getClass());
			System.out.println("");
		}
	}
}

check also mal dein originäres objekt... evtl. auch was da tatsächlich für werte drin sind...

einige Hinweise zum clonen: Achtung ;) ... - da ich das gerade gemacht hab, weiß ich, dass das nicht soo trivial ist:
1.) mit getFields bekommst du nur die public Felder deiner Klasse - beim Kopieren sollten aber vermutlich auch die anderen Felder relevant sein - da hilft getDeclaredFields.
2.) Auch diese Methode liefert leider nur die Felder der aktuellen Klasse, sollten Felder existieren, die durch Vererbung mitgenommen wurden, können die so nicht gefunden werden. Da hilft nur ne eigene kleine Methode zu schreiben, die in der Vererbungshierarchie hoch geht und alle Felder der Klasse und aller Superklassen in ein entsprechendes Field[] Array sammelt.
3.) willst du deep-copy oder shallow-copy machen? Wenn manche Felder in deiner zu kopierenden Klasse nicht primitiv sind, werden bei einer shallow-copy lediglich die Referenzen kopiert, d.h. die Objekte (inkl. all dessen Felder die ebenfalls nicht primitiv sein könnten) werden nicht auch kopiert... falls nur primitive Felder auftreten können ist das ganze dann nicht soo schwierig.
4.) Du musst beim Instanziieren von den Objektkopien (die du ja vermutlich zurückgeben willst) gucken ob die Klasse nen parameterlosen Konstruktor besitzt... - wenn nicht, hast du ein Problem (die Lösung dazu hab ich hier aber auch schonmal gepostet - funktioniert mit der ReflectionFactory aus sun.reflect...)...
5.) Aufpassen bei deep-copy und Zyklen in der Objektstruktur... da musst du dir was geeignetes überlegen - z.B. alle zu kopierenden objekte und deren kopie in einer map speichern (achtung bei klassen die hashcode() überschreiben).

... und und und ;) - da meine lösung Bestandteil eines Frameworks ist, welches ich nicht einfach posten darf, kann ich leider auch keinen Beispielcode posten, wie man das machen könnte, daher nur die paar Punkte oben...
evtl. solltest du dir dann sowas angucken: das ganze geht erheblich einfacher zu implementieren ;) - mein ReflectionCopier ist immerhin inzwischen über 300 Zeilen groß.
 
G

Guvnor

Gast
SnooP hat gesagt.:
[doppelpost... - Server ist bei mir grad ziemlich hangy! ;) - kann das sein?]

Tja, der ist wohl auch im Eimer :D

Hmm okay, das scheint ja echt kein einfaches Unterfangen zu sein. Es wundert mich aber irgendwie, daß es da nicht standardmäßig schon was in Java gibt - ich glaub kaum, daß ich der einzige bin, der Objekte kopieren will :)

Ich hab jetzt ein Beispiel gefunden, wie man über einen ByteStream das Objekt kopieren kann, es muß dafür aber Serializable sein. Naja werde mir das wohl mal anschauen müssen.

Das Objekt selbst besteht eigentlich nur aus primitiven Typen (soweit ich weiß), denn das ist so eine Art Datensatz der dann komplett in 'ne DB geschrieben wird. Und da ich gerade eine Zumüll-Funktion basteln will, wo ich einen einzigen Datensatz (der zunächst mal als Java-Objekt vorliegt) z.b. 25000x kopieren können will, muß ich eben (in der momentanen Implementierung der kompletten Anwendung) eine 1:1-Kopie des Datensatzes haben und diesen dann nochmal in den Bestand einfügen.

Gibt es denn noch völlig andere Möglichkeiten, Objekte zu kopieren?
 

SnooP

Top Contributor
also es gibt imho vier möglichkeiten:
1. java objektserialisierung (ObjectOutputStream über ByteStream - siehe link von mir) - geht am schnellsten
2. cloneable implementieren und clone() aufrufen lassen - problem ist, dass die klassen eine vernünftige clone methode implementieren müssen.
3. reflections nutzen... - aber nich soo einfach
4. eine andere serialisierung z.B. mit xml. Siehe XStream: http://xstream.codehaus.org/

letztere hat den Vorteil wie die Reflection Geschichte, dass keine Voraussetzungen an die zu kopierenden klassen gestellt werden, sprich nix Serializable implementieren etc. - zudem kopiert der Kopierer als transient deklarierte Felder nicht mit - das geht bei den Reflections so ohne weiteres nicht, da man ansonsten zentrale Sachen wie ArrayLists oder sowas nicht kopieren könnte.

Von der Geschwindigkeit ist mein ReflectionKopierer inzwischen fast vier mal so schnell wie der Ansatz über XStream wobei die objektserialisierung etwas weniger als doppelt so schnell ist wie bei mir...

wenn man nur shallow-copies braucht, weil man nur primitive Felder hat (wobei man gucken muss, ob Strings als primitiv gezählt werden können...), dann geht die Geschichte sicher einfacher... - dann entfällt nämlich der rekursive Durchlauf und man kann halt einfach alle Felder 1:1 kopieren, das wird dann auch nicht mehr soo komplex.

Warum es da nix fertiges gibt? .. gute Frage ;) ... - das einfache Kopieren bei java soll halt über den clone ansatz laufen. Wenn man eigene Datenstrukturen hat, geht das ja auch... aber manchmal kommt man halt in die Verlegenheit und muss über komplett fremde Klassen operieren und da gibts tatsächlich noch nix. Und so weit ich gesehen hab, wurde auch noch kein ReflectionCopier irgendwo veröffentlicht... - werde also demnachst mal nachhaken, ob ich das Ding aus dem Projekt auslösen kann und hier mal posten darf ;)
 
G

Guvnor

Gast
Mir ist jetzt eine andere Lösung eingefallen, auch wenn die auf den ersten Blick nicht optimal aussieht - aber ich hab mir jetzt die Klassen mal etwas genauer angeschaut und ich glaube, daß es damit genügen sollte.

Und zwar hat jede Eigenschaft, die in meinem Fall von Bedeutung ist, eine set- und get-Methode, und bei beiden hab ich eigentlich eine Garantie, daß sie immer exakt gleich heißen (bis auf das set und get natürlich :D). Somit werd ich mir wohl einfach alle Methoden holen, diese parsen und aussortieren, und dann eben ein neues Objekt erstellen und alle set-Methoden aufrufen und als Wert den der entsprechenden get-Methode übergeben.

Wie gesagt, es klingt komisch, aber in diesem Fall dürfte das völlig ausreichen. Ich werd's mal versuchen und dann Bescheid sagen, ob das ging oder nicht.

---

Das mit dem Serializable kann ich leider vergessen, hab es vorhin versucht, aber gerade WEIL in den Klassen noch so viele Referenzen usw sind (die aber in meinem Fall unwichtig sind), müßte ja jedes dieser Objekte serializable sein, und ich glaub kaum, daß das in Ordnung geht, wenn ich jetzt alle möglichen Klassen einfach mal serializable mach ;) denn eigentlich geht es nur drum, ein kleines Test-Tool in die Anwendung zu bauen, und dafür wollte ich möglichst wenig am vorhandenen Code rumbasteln.

Das XML-Teil werd ich mir dennoch mal anschauen, vielleicht nützt das in meinem Fall ja doch was. Wenn's allerdings zu langsam ist, ist das auch wieder nicht gut, denn das Kopieren sollte schon recht flott von der Hand gehen (weil ja massenweise Datensätze erstellt werden sollen).
 

SnooP

Top Contributor
Jo klingt doch gut... - ne javabean-Eigenschaft wollte ich vorhin schon nach fragen. Das kann man doch ausnutzen, wobei die Komplexität dadurch nicht besser oder schlechter wird ;) ... ob du jetzt nun per Reflection die Felder ausliest und neu setzt oder aber per get/set Methoden (die du ja letztlich auch per reflection auslesen musst? oder gibt es nen Interface auf das du zurückgreifen kannst?) ... das einzige, was du dabei nicht machen musst, ist die private bzw. final Felder vorher mit der Methode setAccessible(true) verfügbar zu machen und das ist immer abhängig von jeweiligem SecurityManager ob das geht oder nicht (geht allerdings schon in den meisten Fällen).

Der xml-ansatz dauert bei mir bei 250 Objekten, die ich 1000 mal hintereinander kopiere rund 7 Sekunden. Mein Ansatz braucht dafür knapp 3 Sekunden und die Objektserialisierung 1,6 Sekunden... - ein deepclone mit clone-Methoden würde sich übrigens noch deutlich unter einer Sekunde befinden...
 
G

Guvnor

Gast
Okay, es funktioniert jetzt. Ich ermittle alle set- und get-Methoden, prüfe dann, ob es zu jeder set eine passende get gibt, wenn ja, wird die invoked mit dem entsprechenden Wert. Noch funktioniert es aber nicht bei allen Datensätzen, wobei es aber sein kann, daß das jetzt nicht speziell an meinem Zeugs liegt sondern an anderen Umständen, aber das werd ich noch rausfinden :)
 

Wildcard

Top Contributor
Bist du in der Lage die Klassen der zu kopierenden Objekte selbst zu ändern, oder sind die extern?
Wenn du sie ändern kannst, währe ein Copy-Konstruktor vermutlich der richtige Ansatz.
 
G

Guvnor

Gast
Ja das könnte ich schon machen, aber es sind sehr viele und zudem sehr umfangreiche, und da aber diese Funktionalität nur für mich zum Testen benutzt wird, ist es fraglich, ob der Rest der Firma das so gern sieht, wenn da (in deren Augen dann) "unnötige" und ebenfalls sehr umfangreiche Methoden / Konstruktoren auftauchen... werde aber mal mit jemand sprechen, evtl. gibt's ja doch Bedarf an solchen Funktionen ;)
 
B

Beni

Gast
Und "clone" könnt ihr nicht implementieren? Das wäre auf jeden Fall weniger Aufwand als ein Copy-Constructor.

Code:
public class A implements Cloneable{
  int a, b, c, d;
  String e, f, g, h;
  ...

  public A clone(){
    try{
      return (A)super.clone();  // reine Magie im Hintergrund :-)
    }
    catch( CloneNotSupportedException ex ){
      ex.printStackTrace();
    }
  }
}
 

byte

Top Contributor
Naja, ganz so einfach ists mit clone() doch auch nicht. Denn Du musst die Felder ja - wenn es sich um Objektreferenzen handelt - dann per Hand selbst kopieren, indem Du explizit per Hand die clone() der Member aufrufst und die Kopien neu zuweist. Und bei komplexeren Strukturen, wenn die Referenzen z.B. Zyklen erzeugen, dann ist das auch nicht mehr ganz so trivial implementiert.
 

SnooP

Top Contributor
wobei es sich ja wohl nur um primitive Typen handelt? Und wenn es nur fürs Testen geht, dann sollte man ne Lösung nehmen, die möglichst nix mit den Originalklassen anstellt und nen copy-Konstruktor macht imho nur Sinn, wenn wenige Felder für eine Kopie tatsächlich relevant sind... beispielsweise bei String. Aber wenn ich mehr als 5 Felder habe zum Kopieren, dann wird son Konstruktor doch arg unhandlich ;)

also ich würde schon Reflection nehmen... oder aber evtl. mal xstream ausprobieren, weil das wenige zeilen code sind und man hat fix nen ergebnis, vor allem nen Referenzergebnis, mit dem man dann eigene Ansätze vergleichen kann.
 
G

Guvnor

Gast
Für clone() müßte ich doch die Methode komplett selbst schreiben, oder? Oder reicht da etwa das Codebeispiel von Dir (Beni) völlig aus?

Weil ich hab versucht, eine Klasse Cloneable zu machen, und dann hieß es halt, ich soll die clone()-Methode implementieren. Also muß ich dafür doch eigentlich jede einzelne Eigenschaft "übertragen" oder nicht?
 

byte

Top Contributor
Ja, jede Klasse muss cloneable implementieren und eine clone() Methode haben. super.clone() kopiert nur primitive Felder. Wenn die Klasse Referenzen besitzt, dann werden nur die Referenzen kopiert, nicht aber die Objekte, auf die diese zeigen. Das Code-Beispiel von Beni reicht also nur aus, wenn die Klasse entweder nur primitive Member hat oder Du nur eine flache statt einer tiefen Kopie haben willst.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
urmelausdemeis Exception in thread "main" java.lang.Error: Unresolved compilation problem: Allgemeine Java-Themen 7
G jTable-Problem --> java.lang.OutOfMemoryError Allgemeine Java-Themen 5
A Java modul Problem Allgemeine Java-Themen 4
xGh0st2014 Problem mit Java Array Allgemeine Java-Themen 1
J Problem beim Umstellen auf Java jdk 13 Allgemeine Java-Themen 3
J Problem bei Install java 13 Allgemeine Java-Themen 3
A Problem beim öffnen von Java-Installern Allgemeine Java-Themen 1
B Problem zu einem Java Projekt Allgemeine Java-Themen 6
S Java OpenOffice Problem mit Windows-Benutzerwechsel Allgemeine Java-Themen 19
C J2V8 NodeJs Java Bride Problem und Frage!?!? Allgemeine Java-Themen 1
Blender3D Java Swing Programm Windows 10 Autostart Problem Allgemeine Java-Themen 2
F Java Mail Problem: Authentifizierung wird nicht immer mitgeschickt Allgemeine Java-Themen 1
Seikuassi Input/Output Java transferTo ByteArrayOutputStream-Problem Allgemeine Java-Themen 4
K Problem: Java-Klasse mit mehreren Threads als eigenen Prozess starten Allgemeine Java-Themen 3
B Best Practice Java Zugriffsrechte Problem Allgemeine Java-Themen 2
B Java Zahlenausgabe Problem Allgemeine Java-Themen 6
N Problem mit Java Sperrlisten Allgemeine Java-Themen 0
F Java Spiel Sprung problem Allgemeine Java-Themen 5
G JavaFX Problem nach Update auf Java 8 Allgemeine Java-Themen 0
S Java Problem bei der Rückgabe eines Arrays Allgemeine Java-Themen 19
M Problem mit (etwas komplizierterem) Java Programm Allgemeine Java-Themen 14
W Java Logging Problem Allgemeine Java-Themen 3
K java problem Allgemeine Java-Themen 5
B java.io.IOException: Problem reading font data. Allgemeine Java-Themen 9
H Problem mit Java Generics Allgemeine Java-Themen 6
P Eclipse Java Native Interface-Problem Allgemeine Java-Themen 8
I Java als Dienst Problem Allgemeine Java-Themen 2
F Problem mit Java 7 und Proguard Allgemeine Java-Themen 6
L Input/Output Java und CMD Problem Allgemeine Java-Themen 3
C Java Server Pages Problem Allgemeine Java-Themen 6
M Lego Nxt und Java Problem Allgemeine Java-Themen 8
S Perfomance Problem mit Java Applikation Allgemeine Java-Themen 4
G Problem Java Mail API: CC wird nicht berücksichtigt Allgemeine Java-Themen 7
P Problem mit Java Web Start Allgemeine Java-Themen 1
J Eclipse Java Build Path / Java Problem??? Allgemeine Java-Themen 13
B USB-I2C Adapter JAVA problem Allgemeine Java-Themen 6
D Problem mit java.sql.Timestamp Allgemeine Java-Themen 2
L Problem mit Hintergrund bei JAVA Applet Allgemeine Java-Themen 27
D Problem mit Java version? Allgemeine Java-Themen 4
P Zip Problem in Java Allgemeine Java-Themen 4
N Kleines nicht java Problem Allgemeine Java-Themen 7
G Problem mit RSA Verschlüsselung bei .net und Java Allgemeine Java-Themen 1
Chris81T Performance Problem durch mehrfaches Starten eines JAVA Prog Allgemeine Java-Themen 8
V Java heap space Problem Allgemeine Java-Themen 8
T Problem: eclipse / Java / cyrillisch Allgemeine Java-Themen 4
D Problem mit java.util.scanner: Falsche Ergebnisse Allgemeine Java-Themen 4
S Java 5/6 Problem im Classpath Allgemeine Java-Themen 11
F Problem mit Java Listen Allgemeine Java-Themen 4
M Java applet zusammen mit DHTML z-index Problem Allgemeine Java-Themen 2
G problem mit java-editor Allgemeine Java-Themen 4
H Problem mit Java (dsound.dll) Allgemeine Java-Themen 5
E Java.net und Thread-Problem Allgemeine Java-Themen 2
S Problem mit backreference mit java und regex Allgemeine Java-Themen 7
L WindowsTrayIcon in Java 1.4 - Problem beim ausführen der JAR Allgemeine Java-Themen 2
C Java Batch Warte Problem Allgemeine Java-Themen 4
P Java Acces Datenbank Problem ! (Brauche eine Abfrage) Allgemeine Java-Themen 5
G Java-Problem mit Netbeans Allgemeine Java-Themen 2
J Problem mit Java Multimedia Framework Allgemeine Java-Themen 6
G Problem mit Java Fenstern Allgemeine Java-Themen 2
T Problem RSA-Algorithmus in Java? Allgemeine Java-Themen 2
B java problem - speichern Allgemeine Java-Themen 9
G java! Problem mit Chat-Applet Allgemeine Java-Themen 3
S Problem beim Bearbeiten von Java-Dateien unter Linux Allgemeine Java-Themen 3
R Browser-Problem nach Java-Update Allgemeine Java-Themen 9
D (gelöst) Java-Problem bei freemind mit fedora core 4 Allgemeine Java-Themen 9
G Java Server Faces - Problem Allgemeine Java-Themen 2
L-ectron-X Problem mit Collections.sort() mit Java 1.5 Allgemeine Java-Themen 9
C Hilfe! Java Control Panel & Limewire Problem! Allgemeine Java-Themen 3
A Probleme bei der Berechnung von Pi! Java Problem Allgemeine Java-Themen 2
T JAVA+SQL=Mysteriöses Problem Allgemeine Java-Themen 3
P java exe erstellen problem Allgemeine Java-Themen 3
N Java Problem mit WIN ME Allgemeine Java-Themen 2
krgewb Problem mit Umlauten und Eszett bei InputStream Allgemeine Java-Themen 3
Max246Sch Backtracking Problem Box Filler Allgemeine Java-Themen 6
NightVision402 VisualVM Startskript Problem Allgemeine Java-Themen 3
javaBoon86 Email Server Connection Problem Allgemeine Java-Themen 1
F Problem mit PDFBOX Library Allgemeine Java-Themen 1
D Read JSON File Problem Allgemeine Java-Themen 9
J Problem mit JasperReports Allgemeine Java-Themen 8
M log4j Problem mit jlink Allgemeine Java-Themen 19
8u3631984 Problem beim Mocken von Record Klassen Allgemeine Java-Themen 4
torresbig Website login Problem - Jsoup, wie bisher, klappt nicht! Allgemeine Java-Themen 31
P Selenium . getText Problem Allgemeine Java-Themen 9
A Jar zu Exe Problem Allgemeine Java-Themen 13
sserio Variablen Liste erstellt und ein Problem mit dem Index Allgemeine Java-Themen 6
S Folgendes Problem bei einem Programm Allgemeine Java-Themen 1
stormyark Problem beim Klassen erstellen Allgemeine Java-Themen 1
A Thread.sleep Problem Allgemeine Java-Themen 2
A Problem bei der Nachbarschafttest Allgemeine Java-Themen 11
Splayfer Problem: no main manifest attribute Allgemeine Java-Themen 3
G javamail Problem beim Empfangen von Nachrichten Allgemeine Java-Themen 3
Splayfer JDA Problem mit MessageCounter Allgemeine Java-Themen 0
Splayfer Problem mit BufferedWriter Allgemeine Java-Themen 3
F Streams als Alternative für dieses Problem ? Allgemeine Java-Themen 15
N Maven Problem mit Datenbanktreiber (H2 Embedded) Allgemeine Java-Themen 12
T Problem beim Umwandeln in eine Jar-Datei Allgemeine Java-Themen 3
B Einfach Elemente zweier Arraylisten kreuz und quer vergleichen, min und max Problem? Allgemeine Java-Themen 16
C ArrayList Problem Allgemeine Java-Themen 3
kev34 nim-Spiel problem Allgemeine Java-Themen 1
D Firebase retrieve data Problem, Child Element wird nicht angesprochen Allgemeine Java-Themen 0

Ähnliche Java Themen

Neue Themen


Oben