Érdekes kísérlet volt, a klasszikus GreenHouseControl példát újra elővenni, és átírni, csinosítani.
Kíváncsi voltam, hogy menne reflexióval, ha osztály objektumokat és konstruktor objektumokat használok.
A buktató a dologban az volt, hogy példányosítani kívánt objektumom belső osztály, így egy láthatatlan referenciát tárolnia kell az őt tartó osztályról.
A kód írásánál erre kifejezetten nincs szükség, mivel a compiler elvégzi helyettünk a feladatot, de példányosításnál kell hivatkoznunk erre a referenciára.
Erre kicsit később azért rájöttem magam is.
Íme a kis kódrészlet:
...
class Event {
public Event(long value) { i = value; }
private long i;
// ...a többit elhagytuk.
}
class WaterOn extends Event {
public WaterOn(long value) { super(value); }
}
...
GreenHouseControls osztályon belül pedig...
...
try {
HashMap<String, Event> entities = new HashMap<String, Event>();
entities.put("WaterOn", WaterOn.class);
// entities.put... stb.,stb. Event osztály további leszármazottait..
String typeName = "WaterOn";
// .....
Class evnt = null;
if ((evnt = entities.get(typeName)) != null) {
Constructor<? extends Event> c =
evnt.getConstructor(
new Class[] {GreenHouseControl.class, long.class}
);
// GreenHouseControl.class a belső 'láthatatlan' osztályreferencia,
// mivel Event-nek egyetlen egy konstruktora van, ami így fest:
// public Event(long value) { ... }
return
(Event) c.newInstance(GreenHouseControl.this, System.currentTimeMillis());
}
}
catch (NoSuchMethodException nsme) { }
catch (IllegalArgumentException iae) { }
...
Megjegyzem, hogy ilyet soha ne csináljunk, hogy a hiba elkapásának helyén nem iratjuk ki legalább a stackTrace-t!
A régi kód többszörös if-else elágazásokból állt, és mindegyik ág egy konkrét példányt hozott létre a megfelelő osztályból.