Archief - JAVA: Reflection gebruiken bij casten?

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

Forum

Legacy Member
Hallo,

Ik zou een aantal objecten van de klasse Object naar een specifieke klasse willen casten bij het deserializen, dus:

A a = (A) objectInputStream.readObject();

Alleen weet ik nog niet dat dit de klasse "A" gaat zijn op het moment van implementatie. Hoe kan ik dynamisch casten met reflection? of bestaat er een andere, betere manier? De klasse waarnaar gecast moet worden, wordt bijgehouden in een String. Alvast bedankt.

NeverwinterX

Legacy Member
Forum zei:
Hallo,

Ik zou een aantal objecten van de klasse Object naar een specifieke klasse willen casten bij het deserializen, dus:

A a = (A) objectInputStream.readObject();

Alleen weet ik nog niet dat dit de klasse "A" gaat zijn op het moment van implementatie. Hoe kan ik dynamisch casten met reflection? of bestaat er een andere, betere manier? De klasse waarnaar gecast moet worden, wordt bijgehouden in een String. Alvast bedankt.

Als je weet in welke volgorde je de objecten serialized opslaat dan weet je ook hoe je ze moet casten bij het uitlezen.

Tenzij je hier een zeer dynamisch serializatie framework aan het uitbouwen bent, maar dan ben je het wiel aan het heruitvinden en kan je beter zoeken naar bestaande persistentie frameworks.

NeverwinterX

Legacy Member
Forum zei:
Ik ben het wiel aan het heruitvinden :) Dit is de bedoeling.

Dan gaat het op die manier niet lukken. Een dergelijke cast is niet mogelijk in java tenzij je de VM gaat hacken. Je moet met een ander design op de proppen komen.

Wolf2000me

Legacy Member
Je wil dus zoals Hibernate (JPA) je objecten omzetten, niet casten, naar hun juist objecttype.

Reflection wil dan wel zeggen dat je op een externe manier de methods van je Object via Reflection gaat benaderen. Dit is niet hetzelfde als casten, verre van.

Ik zou, om het simpel te houden, je houden aan dit gameplan (al is dit maar iets dat ik nu ter plaatse bekokstoof).

Zoals Hibernate kan je een soort van persistence context vragen van je gebruiker in xml. Je zet daar bv. de class name & package in voor elke type object dat je wil gebruiken.
Vervolgens gebruik je Reflection (voorbeelden genoeg te vinden) om met trial en error deze objecten te proberen instantiëren. Lukt het niet de eerste keer dan probeer je een volgend object vanuit de persistence context.
Uiteraard is er dan wel problematiek met afgeleide classes, maar da's iets om dan later te gaan fine tunen.

Of.

Tijdens runtime wanneer een user een object wenst te persisteren roep je achter de schermen de methode van Object aan:
objectInstance.getClass().getName()

en persisteer je deze gegevens ook. Je kan dit in combinatie met de persistence context die ik hierboven aanhaal gebruiken om geen trial en error te moeten doen.

Ik geef toe dat daar dan nog steeds kosten aan zijn maar ja, dat is wat je krijgt wanneer je het wiel probeert te heruitvinden.
Als gewone Java oefening is dit mogelijk wel nuttig, maar niet meer dan dat. Proberen het wiel te heruitvinden wanneer je toepassingen maakt is echt geen goed idee (imho)

NeverwinterX

Legacy Member
Wolf2000me zei:
Ik zie niet direct in wat je nu met Reflection in dit topic bedoelt. Je bedoelt de Serializable interface in Java.

Maar on the other hand... Gangbare persistence frameworks zoals Hibernate (JPA) gebruiken effectief Reflection om hun gepersisteerde gegevens naar Objecten om te zetten. De kunst voor jou zal eruit bestaan om op een dynamische manier te weten te komen welk soort object data nu aangeboden wordt vanuit de DB.

Hij bedoelt op een manier als (exceptions even buiten beschouwing gelaten):
Code:
                // read which class
                String classname = (String) objectInputStream.readObject();
                // get the object
		Object o = objectInputStream.readObject();
                // dynamically cast it to the right type
		Categorie s = Class.forName(classname).cast(o); // error hier
                // and do this for all serialized objects

Wat niet werkt omdat de cast methode niet het correcte type kan afleiden omdat forName het type niet meteen kan raden at compile time. Dus daar is nog altijd een cast naar Categorie nodig :

Code:
Categorie s = (Categorie) Class.forName(classname).cast(o);

Wolf2000me

Legacy Member
NeverwinterX zei:
Hij bedoelt op een manier als (exceptions even buiten beschouwing gelaten):
Code:
                // read which class
                String classname = (String) objectInputStream.readObject();
                // get the object
		Object o = objectInputStream.readObject();
                // dynamically cast it to the right type
		Categorie s = Class.forName(classname ).cast(o);
                // and do this in some loop for all serialized objects

Wat niet werkt omdat de cast methode niet het correcte type kan afleiden omdat forName het type niet meteen kan raden at compile time.

Ja sorry, ik heb mijn post compleet aangepast want ik had het verkeerd begrepen. Zie de edit :)

Forum

Legacy Member
Wolf2000me zei:
Ja sorry, ik heb mijn post compleet aangepast want ik had het verkeerd begrepen. Zie de edit :)

Ja, idd zo zou het moeten zijn...
Ik snap niet dat volgende niet werkt...

A a = Class.forName("A").cast(obj);

Wat doet die cast methode dan eigenlijk?

A a = (A) Class.forName("A").cast(obj);

werkt wel, maar ik kan tijdens compilatie nog niet weten dat (A) moet zijn.

Ik weet niet of dit een goede oplossing is maar ik heb een interface gemaakt met 1 methode:

public Object readObject(ObjectInputstream in);

en dan voor elk klasse die gebruikt wordt moet er een klasse zijn die volgende methode heeft, bijvoorbeeld voor klasse A:

public Object readObject(ObjectInputStream in) {
return (A) in.readObject();

Eventueel zou het ook met een if constructie kunnen opgelost worden maar dan moet de code aangepast worden bij nieuwe objecten/klassen

if (name.equals("A") {
return (A) in.readObject();
} else if (name.equals("B") {
return (B) in.readObject();

..... enz..

forloRn_

Legacy Member
Forum zei:
Ja, idd zo zou het moeten zijn...
Ik snap niet dat volgende niet werkt...

A a = Class.forName("A").cast(obj);

Wat doet die cast methode dan eigenlijk?

A a = (A) Class.forName("A").cast(obj);

werkt wel, maar ik kan tijdens compilatie nog niet weten dat (A) moet zijn.

Ik weet niet of dit een goede oplossing is maar ik heb een interface gemaakt met 1 methode:

public Object readObject(ObjectInputstream in);

en dan voor elk klasse die gebruikt wordt moet er een klasse zijn die volgende methode heeft, bijvoorbeeld voor klasse A:

public Object readObject(ObjectInputStream in) {
return (A) in.readObject();

Eventueel zou het ook met een if constructie kunnen opgelost worden maar dan moet de code aangepast worden bij nieuwe objecten/klassen

if (name.equals("A") {
return (A) in.readObject();
} else if (name.equals("B") {
return (B) in.readObject();

..... enz..

Als forName() een Class<A> zou teruggeven, zou die cast() effectief een A teruggeven, maar forName() geeft een Class<?> terug. Dat is logisch, want at compile time is het resultaat van forName() immers nog niet gekend. De wildcard ? is het beste wat de compiler op dat moment kan garanderen, zodat je nog moet casten om er effectief iets nuttig mee te doen.

Wat je volgens mij moet doen is samen met de klasse A, de code meeleveren die de cast doet en al het overige wat je met een instantie van klasse A wilt doen.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan