# Wie neue Instanz einer Klasse erstellen, von der ich nur eine andere Instanz kenne?



## dflasjjs (2. Apr 2009)

Hi,

ich habe folgende Situation.
Ein Interface A,
dann B und C die dieses interface implementieren, sowie 2 Instanzen der beiden Klassen b und c.

Eine dieser beiden Instanzen wird nun ausgewählt (per Pull-Down-Menü).
Ich habe nun also b bzw c und möchte jetzt automatisiert eine neue Instanz der selben Klasse erstellen. Hoffe es ist verständlich.

Beispiel: Wenn Benutzer a auswählt, dann möchte ich noch eine Instanz von a haben, nur habe aber bisher nur a.
Ich weiss, dass getClass() die Klasse zurückgibt, aber ich weiss nicht wie ich damit dann eine neue Instanz erstellen kann.


----------



## maki (2. Apr 2009)

Muss das sein?

Es ginge mit Reflection, ist aber unschön.

Worum geht es dir denn eigentlich?


----------



## Noctarius (2. Apr 2009)

```
public A newInstance(A object) {
	Class<? extends A> clazz = object.getClass();

	if (clazz.equals(B.class) return new B();
	
	return new A();
}
```

Trotzdem stellt sich auch mir die Frage: Was möchtest du denn machen?


----------



## Spacerat (2. Apr 2009)

Bei solchen Geschichten kann es recht ungünstig sein, wenn eine Klasse die A implementiert keineb Standard-Konstruktor deklariert. Dan wird's Essig mit "new B()" oder "new C()". Wenn mann aber dafür sorgt, das Interface A "Cloneable" erweitert und ferner die implementierenden Klassen dazu zwingt "clone()" zu überschreiben, klappts ungefähr so:[highlight=java]A cloneInstance(A obj) {
  return (A) obj.clone();
}[/highlight]


----------



## void (2. Apr 2009)

Eine neue Instanz einer Klasse erstellt man mit http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance()


----------



## Noctarius (2. Apr 2009)

Aber auch nur mit Standard-Constructor.

Was du vielleicht machen solltest wäre sowas wie:

```
public B (B b) { ... }
```

Quasi das zu "kopierende" Objekt direkt als Parameter des Constructors übergeben. Die Frage ist, willst du eine neue LEERE Instanz der Klasse oder eine Kopie der aktuellen Instanz?


----------



## void (2. Apr 2009)

Noctarius hat gesagt.:


> Aber auch nur mit Standard-Constructor.
> 
> Was du vielleicht machen solltest wäre sowas wie:
> 
> ...



Und wie übergibst du da weitere Konstruktorparameter?

edit: und noch interessanterm wie erstellst du das B das du im Konstruktor übergeben willst?


----------



## Spacerat (2. Apr 2009)

Das was Noctarius dort oben meint ist ein sog. Copy-Konstruktor. Diesen kann man über "clone()" aber auch mit z.B. "B.class.getConstructor(new Class[] {B.class}).invoke((B) obj);" aufrufen. ab Java 1.5 kann man sich bei "getConstructor()" sogar das explizite Erstellen eines Class-Arrays sparen (VarArgs).


----------



## void (2. Apr 2009)

Ah ok, verstehen. War ein Denkfehler meinerseits.


----------



## maki (3. Apr 2009)

clone ist keine guter Copy Konstruktor, da er nicht die rechte eines Konstruktors hat.

Eine factory Methode ist meist besser, zB. copy(A a);


----------



## dflasjjs (3. Apr 2009)

Es ist eine Java, Servlet, Jsp-Anwendung
Also es geht konkret um folgendes, ich will das Kapital berechnen.
Allerdings berechnet sich das Kapital überall komplett anders, daher sollte das ganze sehr flexibel sein.
Man kann keine allgemeine Datenstruktur für alle Probleme finden (ich hatte das Problem hier auch schon mal reingestellt).

Deshalb habe ich mich entschieden, ein Interface zu deklarieren, mit eben einer festen Methode getCapital().
Und nun baue ich für jeden "Kunden" eine eigene Klasse die genau das ist was er braucht.
Diese Implementieren dann das Interface und speichern eben die Daten die getCapital() in den unterschiedlichen Kundenfällen braucht.

Grundsätzlich sollen aber den Kunden alle bisher implementierten Interfaces zur Verfügung stehen, er wählt es einfach in einer Formular per Pull-Down-Menü aus. 
Das Pull-Down-Menü bekommt die Daten aus einer Liste, wo jeweils eine Instanz der zur Verfügung stehenden Implementierungen drin sind.

So, nun hat er eine ausgewählt, das Formular abgeschickt und ich möchte nun im Servlet wissen, welche Klasse er sich ausgesucht hat und eine neue Instanz dieser Klasse erstellen, die ich dann für die Kapital-Berechnung wirklich benutze.

Edit: Alle Klassen haben 2 Konstruktoren, einer ist bei allen gleich und dann eben den angepassten...


----------



## faetzminator (3. Apr 2009)

Wie wärs, wenn du einfach eine Map hast, in welcher der Key dem Key in der Combobox (nicht dem Text) entspricht, und die Value jeweils ein Class Objekt ist? Wenn du von einem Interface sprichst, haben ja alle Objekte die gleichen Methoden etc., d.h. du kannst mit dem Interface arbeiten.


----------



## dflasjjs (3. Apr 2009)

Okay, ich habs nun "per Hand" gelöst, also einfach mit If bla.equals("class core.sss"), dann...
Ich wollte ja eigentlich vermeinden, dass ich dort immer jede Klasse hinzufügen muss, aber im Grunde sind es ja nicht viele und ich muss für diese eh neue Formulare erstellen usw, dann kann ich auch eben die Zeile anpassen und bin dann auf jeden Fall auf der sicheren Seite.


----------



## Spacerat (3. Apr 2009)

maki hat gesagt.:


> clone ist keine guter Copy Konstruktor, da er nicht die rechte eines Konstruktors hat.
> 
> Eine factory Methode ist meist besser, zB. copy(A a);


Ja, ne, is klar... "clone()" ist ja nicht mal ein Konstruktor. Das Problem ist, das man Klassen per Interface nicht dazu zwingen kann einen Copy-Konstruktor, wohl aber eine Copy-Methode (in diesem Fall Clone-Methode) zu implementieren. Für deine Version der Copy-Methode sind entweder zwei Instanzen der Klasse A erforderlich oder man übergibt "null" und landet erneut bei "clone()", wie in diesem Fall.[highlight=java]public interface A
extends Cloneable
{
  Object clone();
  A copy(A a);
}

public class B
implements A
{
  B(B original) {
    // copy Original
  }

  public Object clone() {
    // wieman hier eine neue Instanz erstellt ist völlig Wurst
    // Ich bediene mich hier gerne dem besagten Copy-Konstruktor
    return new B(this);
  }

  public A copy(A target)
  {
    if(!(target instanceof B)) return (A) clone();
    // copy this to target
    return target;
  }
}[/highlight]


----------

