Dynamisch ein Objekt einer bestimmten Subklasse erstellen

Fant

Bekanntes Mitglied
Hallo zusammen..

folgendes Szenario: Ich habe eine Basisklasse von der mehrere andere Klassen erben. Eine bestimmte Methode erwartet ein Objekt der Basisklasse, bekommt aber in der Regel ein Objekt einer der Subklassen übergeben. Ich denke an einem CodeSchnipsel wird deutlicher, was ich möchte, als bei einer ausschweifenden Erklärung:

Java:
public class A {...}
public class B extends A { ... }
public class C extends A { ... }

public class Test {
   private A a;
   public void macheEtwas(A a) {
      // ...
      // hier möchte ich this.a ein neues Objekt vom tatsächlich übergebenen Typ zuweisen.
   }

   public void main(String [] args) {
      a = new B();
      macheEtwas(a);
      // Jetzt soll a ein neues Objekt vom Typ B sein 
      a = new C();
      macheEtwas(a);
      // Jetzt soll a ein neues Objekt vom Typ C sein
}

Ich kann natürlich mit instanceof jeden potentiellen Subtyp abklappern und dann entsprechend ein neues Objekt erstellen. Ich würde das aber ganz gerne allgemeiner halten, wenn das irgendwie geht, da die Liste an Subtypen relativ groß ist und ich nicht ständig diese Methode anpacken möchte, wenn neue hinzu kommen.
Wie kann man das eleganter lösen? (Die Lösung sollte auch noch unter Java 1.5 laufen)

Viele Grüße
Fant
 
Falls deine Subklassen alle einen default Konstruktor haben kannst du folgendes machen:

Java:
public class Test {
	private static A a;

	public static void macheEtwas(A a) {
		try {
			Test.a = a.getClass().newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		a = new B();
		System.out.println(a);
		macheEtwas(a);
		System.out.println(a);
	}
}

class A {
}

class B extends A {
}
 
Zuletzt bearbeitet von einem Moderator:
Wenn klar ist das ALLE erbenden Klassen solche (auf diesem "unbekannten" Weg) erzeugte Instanzen erzeugen können müssen, sollte man dies auch mit einer abstrakten Methode in A bzw. via einem Interface vorschreiben!
Reflection dient, zumindest für mein Verständnis, eigentlich mehr der Objekt- oder Codeanalyse für Debugger, Generatoren etc.. Irgendwo "auf dunklem Wege" Objekte zu erzeugen ist m.E. ein "So schonmal gar nicht" 😉
 
Mir ist nicht klar, was du meinst? Die Klassen erzeugen ja keine Instanz von sich selbst, sondern in einer separate Klasse, welche nun eine Instanzvariable der Basisklasse besitzt, möchte ich ein neues Objekt (des aktuellen tatsächlichen Subtyps) erzeugen und eben dieser Instanzvariablen zuordnen.
 
andreT meint so was:
Java:
public class Test {
	private static A a;

	public static void macheEtwas(A a) {
		Test.a = a.newInstance();
	}

	public static void main(String[] args) {
		a = new B();
		System.out.println(a);
		macheEtwas(a);
		System.out.println(a);
	}
}

interface Instantiable<T> {
	public T newInstance();
}

abstract class A implements Instantiable<A>{
}

class B extends A {
	@Override
	public A newInstance() {
		return new B();
	}
}
Damit lagerst du die Logik zum erzeugen eines Objekts in die jeweilige Klasse aus und sparst dir Reflection. Hat beides seine Vor- und Nachteile.
 
Kommt ja auch immer auf die "Umgebung" an. Für mein kleines Home-Projekt würd ich ggf. auch Reflection benutzen, aber in größeren Projekten ist das nach meiner Erfahrung "nicht so gern gesehen". Schon aus dem Grund daß nicht mal eben alle Stellen der Erzeugung von Objekten von der IDE gefunden werden können. Reflection macht ja keine konkrete Referenz auf den Konstruktor o.ä.! Plötzlich schwirren da unerwartete Objekte im Debugger rum und keiner will's nachher gewesen sein 😀
Wie gesagt: Reflection ist schon eine feine Sache, aber um die Fehlersuche und Wartbarkeit des Codes (übrigens auch für die Kollegen/die Nachwelt!!!) leichter zu machen, lieber sowas (siehe Bsp. von EikeB) wie ein Interface benutzen.
 
Reflection hat nur dann den Vorteil wenn man die abstraktion und implementierung getrennt hat, so dass zur compilezeit sie sich nicht kennen.

ansonsten wuerde ich immer den Interface weg gehen - siehe andreTs Beitrag
 

Neue Themen


Zurück
Oben