Kopierkonstruktor

Hallo allerseits. Ich möchte in einem Kopierkonstruktor einen anderen Konstruktor nutzen. Das Problem ist, ich habe 2 weitere Konstruktoren, einen mit int[] als Datentyp und einen als char. Wie wähle ich den Array aus?

Normalerweise würde ich z. B. machen


publice klasse(int[] test])
{
}

public klasse (char ads)
{
}

//So nun der Kopierkonstruktor
public klasse(klasse test)
{
this(test);
}
Normalerweise würde ich einfach this machen und der würde schon eine Konstruktor aufrufen,. Aber in dem Fall ist es halt bisschen komplex, wie lenke ich denn darauf, dass er direkt den Array nimmt und was muss ich schreibe, damit es korrekt ist?
 
Beste Antwort
K
Ein Copy Constructor ist vor allem im C++ Umfeld bekannt und üblich - aber auch in Java kann man natürlich einen Konstruktor bauen, der eine Instanz der eigenen Klasse entgegen nimmt.

Und das dies geht, sieht man ja auch an Klassen wie String - das wäre ein gutes Beispiel für eine Klasse mit einem Copy Constructor im Java Umfeld..

Und die Frage ist, was denn hier als Problem gesehen wurde. Hat @temi da schon geholfen? Oder ist das Problem, dass Du eigentlich zwei Konstruktoren hast, die Du da aufrufen möchtest?

Also etwa sowas (was so nicht geht):
Java:
public class KonstruktorDemo {
    private char ads;
    private int[] test;
    
    public KonstruktorDemo(final char ads) {
        this.ads = ads;
    }

    public...

temi

Top Contributor
Die Auswahl erfolgt automatisch aufgrund des Parametertyps, d. h., wenn du einen char Parameter angibst, dann wird der zweite Konstruktor verwendet. Du musst dem this() also ein int Array übergeben. Das Array kannst du evtl. dem übergebenen Parameter vom Typ Klasse entnehmen, wenn du z. B. Zugriff auf eine Instanzvariable hast oder einen entsprechenden Getter. Edit: Das Letzte ist natürlich Blödsinn, da es sich um die Definition der Klasse an sich handelt, hat sie natürlich vollen Zugriff auf alle Instanzvariablen und Methoden darin.
Java:
public class Foo {
    private int[] data;
    
    public Foo(int[] data) {
        this.data = data;
    }
    
    public Foo(Foo foo) {
        this(foo.data);
    }
}
 
Zuletzt bearbeitet:

Jw456

Top Contributor
Was meist du mit Kopierkonstruktor.
Ein Konstruktor der sich selbst als Parameter übergibt wie du es gemacht hat geht nicht.

Der Konstruktor erstellt ja erst das Objekt. Du das jabekt ja noch nicht übergeben wenn es noch nicht existiert.
Das hat mit rekusion wenn es das werden soll nichts zu tun.
 
K

kneitzel

Gast
Ein Copy Constructor ist vor allem im C++ Umfeld bekannt und üblich - aber auch in Java kann man natürlich einen Konstruktor bauen, der eine Instanz der eigenen Klasse entgegen nimmt.

Und das dies geht, sieht man ja auch an Klassen wie String - das wäre ein gutes Beispiel für eine Klasse mit einem Copy Constructor im Java Umfeld..

Und die Frage ist, was denn hier als Problem gesehen wurde. Hat @temi da schon geholfen? Oder ist das Problem, dass Du eigentlich zwei Konstruktoren hast, die Du da aufrufen möchtest?

Also etwa sowas (was so nicht geht):
Java:
public class KonstruktorDemo {
    private char ads;
    private int[] test;
    
    public KonstruktorDemo(final char ads) {
        this.ads = ads;
    }

    public KonstruktorDemo(final int[] test) {
        this.test = test;
    }

    public KonstruktorDemo(final KonstruktorDemo demo) {
        this(demo.ads);
        this(demo.test);
    }
}

Eine Möglichkeit ist bei sowas, die Funktionalität, die benötigt wird, zusammen zu ziehen in eine Methode. Das haben wir hier in Form eines Konstruktors, der ads und test setzt. Die anderen Konstruktoren rufen den dann auf. Das sähe dann z.B. so aus:
Java:
public class KonstruktorDemo {

    public static char DEFAULT_ADS = 0;
    public static int[] DEFAULT_TEST = null;

    private char ads;
    private int[] test;

    public KonstruktorDemo(final char ads) {
        this(ads, DEFAULT_TEST);
    }

    public KonstruktorDemo(final int[] test) {
        this(DEFAULT_ADS, test);
    }

    private KonstruktorDemo(final char ads, final int[] test) {
        this.ads = ads;
        this.test = test;
    }

    public KonstruktorDemo(final KonstruktorDemo demo) {
        this(demo.ads, demo.test);
    }
}
 
Beste Antwort

Jw456

Top Contributor
Ein Copy Constructor ist vor allem im C++ Umfeld bekannt und üblich - aber auch in Java kann man natürlich einen Konstruktor bauen, der eine Instanz der eigenen Klasse entgegen nimmt.

Und das dies geht, sieht man ja auch an Klassen wie String - das wäre ein gutes Beispiel für eine Klasse mit einem Copy Constructor im Java Umfeld..

Und die Frage ist, was denn hier als Problem gesehen wurde. Hat @temi da schon geholfen? Oder ist das Problem, dass Du eigentlich zwei Konstruktoren hast, die Du da aufrufen möchtest?

Also etwa sowas (was so nicht geht):
Java:
public class KonstruktorDemo {
    private char ads;
    private int[] test;
   
    public KonstruktorDemo(final char ads) {
        this.ads = ads;
    }

    public KonstruktorDemo(final int[] test) {
        this.test = test;
    }

    public KonstruktorDemo(final KonstruktorDemo demo) {
        this(demo.ads);
        this(demo.test);
    }
}

Eine Möglichkeit ist bei sowas, die Funktionalität, die benötigt wird, zusammen zu ziehen in eine Methode. Das haben wir hier in Form eines Konstruktors, der ads und test setzt. Die anderen Konstruktoren rufen den dann auf. Das sähe dann z.B. so aus:
Java:
public class KonstruktorDemo {

    public static char DEFAULT_ADS = 0;
    public static int[] DEFAULT_TEST = null;

    private char ads;
    private int[] test;

    public KonstruktorDemo(final char ads) {
        this(ads, DEFAULT_TEST);
    }

    public KonstruktorDemo(final int[] test) {
        this(DEFAULT_ADS, test);
    }

    private KonstruktorDemo(final char ads, final int[] test) {
        this.ads = ads;
        this.test = test;
    }

    public KonstruktorDemo(final KonstruktorDemo demo) {
        this(demo.ads, demo.test);
    }
}
Ja ok zeige bitte wie der copy con dann in einer Methode aufgrufen wird.

Im Endeffekt werden ja die defaukt werde für die Argumente benutzt.
 

Jw456

Top Contributor
Hoffe ich habe es richtig verstanden der CopyCon. Wird gar nicht aus einer Methode zur Instanz Bildung aufgrufen. Er dient nur dazu die nicht mit übergeben Argumente mit den defaut Werten zu setzen.
 

temi

Top Contributor
K

kneitzel

Gast
Nein, es werden keine default Werte beim Copy Constructor benutzt. Der Inhalt der übergebenen Referenz wird in der neuen Referenz gesetzt.

Der Copy Constructor dient dazu, eine zweite Instanz zu bekommen, die genau die gleichen Werte hat. Das geht also etwas Richtung clone, wobei es bei dem clone() Ansatz gewisse Dinge gibt, die es verkomplizieren können / die beachtet werden sollten.

Erweitern wir das Beispiel von mir mit einer main Methode:
Java:
import java.util.Arrays;

public class KonstruktorDemo {

    public static char DEFAULT_ADS = 0;
    public static int[] DEFAULT_TEST = null;

    private char ads;
    private int[] test;

    public KonstruktorDemo(final char ads) {
        this(ads, DEFAULT_TEST);
    }

    public KonstruktorDemo(final int[] test) {
        this(DEFAULT_ADS, test);
    }

    private KonstruktorDemo(final char ads, final int[] test) {
        this.ads = ads;
        this.test = test.clone();
    }

    public KonstruktorDemo(final KonstruktorDemo demo) {
        this(demo.ads, demo.test);
    }

    public static void main(String[] args) {
        KonstruktorDemo demo1 = new KonstruktorDemo('a', new int [] { 1, 2, 3 } );
        KonstruktorDemo demo2 = new KonstruktorDemo(demo1);

        demo2.test[1] = 7;
        System.out.println(demo1);
        System.out.println(demo2);
    }

    @Override
    public String toString() {
        return "KonstruktorDemo{" +
                "ads=" + ads +
                ", test=" + Arrays.toString(test) +
                '}';
    }
}

(Habe auch noch beim Array ein clone() eingefügt, so dass es sozusagen ein deep copy ist.)
 

Jw456

Top Contributor
Nein, es werden keine default Werte beim Copy Constructor benutzt. Der Inhalt der übergebenen Referenz wird in der neuen Referenz gesetzt.

Der Copy Constructor dient dazu, eine zweite Instanz zu bekommen, die genau die gleichen Werte hat. Das geht also etwas Richtung clone, wobei es bei dem clone() Ansatz gewisse Dinge gibt, die es verkomplizieren können / die beachtet werden sollten.

Erweitern wir das Beispiel von mir mit einer main Methode:
Java:
import java.util.Arrays;

public class KonstruktorDemo {

    public static char DEFAULT_ADS = 0;
    public static int[] DEFAULT_TEST = null;

    private char ads;
    private int[] test;

    public KonstruktorDemo(final char ads) {
        this(ads, DEFAULT_TEST);
    }

    public KonstruktorDemo(final int[] test) {
        this(DEFAULT_ADS, test);
    }

    private KonstruktorDemo(final char ads, final int[] test) {
        this.ads = ads;
        this.test = test.clone();
    }

    public KonstruktorDemo(final KonstruktorDemo demo) {
        this(demo.ads, demo.test);
    }

    public static void main(String[] args) {
        KonstruktorDemo demo1 = new KonstruktorDemo('a', new int [] { 1, 2, 3 } );
        KonstruktorDemo demo2 = new KonstruktorDemo(demo1);

        demo2.test[1] = 7;
        System.out.println(demo1);
        System.out.println(demo2);
    }

    @Override
    public String toString() {
        return "KonstruktorDemo{" +
                "ads=" + ads +
                ", test=" + Arrays.toString(test) +
                '}';
    }
}

(Habe auch noch beim Array ein clone() eingefügt, so dass es sozusagen ein deep copy ist.)
Ich habe mich Vileicht falsch ausgedrückt. Es sind drei const.
Einer mit beiden Parametern. Und zwei nur einen. Alle rufen den CopyCon auf.
Werden zei Werte übergeben wird natürlich kein defaut Wert benutz. Bei den a derb beiden ja immer der der nicht als Parameter übergeben wurde.

Wie gesagt mit den Code von kneitzel
War es einleuchtend.
 
K

kneitzel

Gast
Also der Copy Constructor dient dazu, dass man eine neue Instanz erzeugen kann (klar - ist ja ein Konstruktor!), welches aber eine Kopie einer schon vorhandenen Instanz ist.

Da @Jw456 meines Wissens auch etwas C++ Wissen hat / da evtl. etwas unterwegs ist, versuche ich es mal auf die Schnelle auszuführen:

In Java eigentlich nur interessant wenn es darum geht, dass man eine Kopie haben will. Also sehr vergleichbar mit dem Clone Ansatz was die Anwendung angeht. Java hat ein wichtiges Detail: Alle Instanzen liegen im Heap. Es gibt keine Variable, die eine Instanz halten könnte. Eine Variable hat immer nur eine Referenz, welche dann auf die Instanz zeigt.

Das ist in C++ nicht ganz so. Da kann eine Variable eine Pointer halten oder die Instanz selbst. Ich kann also innerhalb eine Methode eine neue Instanz erzeugen:
Java:
void func() {
  SomeClass something();
  ...
}

Es wird eine Instanz von SomeClass erzeugt und die liegt auf dem Stack. Der Speicher wird daher direkt freigegeben, wenn die Methode sich beendet.

Nun geben wir diese Instanz zurück:
Java:
SomeClass func() {
  SomeClass something();
  ...
  return something;
}

Jetzt wird bei der Rückgabe eine neue Instanz von SomeClass erzeugt. Dazu wird (in der Theorie) der Copy Constructor aufgerufen.

Das Gleiche findet man bei Parametern, die so übergeben werden. (Ein Grund, warum da gerne mit Referenzen gearbeitet wird - da entfällt der Aufruf).

Jetzt bliebt nur noch: Was meinte ich mit "in der Theorie" - ist es so oder ist es nicht so? Die Compiler optimieren natürlich, wo sie nur können. Der dort angesprochene Bereich ist dann das, was man als "copy elision" im Netz finden kann: https://en.cppreference.com/w/cpp/language/copy_elision

Wenn man mehrere Compiler / Plattformen zur Hand hat, dann kann man recht schön damit spielen und schauen, wie oft denn der Copy Constructor aufgerufen wird und bei welchen Konstellationen. Das kann also von Compiler zu Compiler unterschiedlich sein. (Habe da z.B. schon AIX / xlc++ mit Linux / gcc verglichen und so)
 

mrBrown

Super-Moderator
Mitarbeiter
Es sind drei const.
Einer mit beiden Parametern. Und zwei nur einen. Alle rufen den CopyCon auf.
Nein, es sind vier Konstruktoren – und nur der, der einen Parameter der eigenen Klasse hat ist der "Copy-Constructor", eben weil er das übergeben Objekt "kopiert".

Die anderen drei Konstruktoren sind einfach nur ganz normale Kosntruktoren ohne besondere Bezeichnung.
 
K

kneitzel

Gast
Alle rufen den CopyCon auf.
Nein, der Copy Constructor wird von keinem anderen Constructor aufgerufen. Die Aufrufe erkennst Du ja am this:

Die beiden Konstruktoren mit nur einem Parameter rufen den Konstruktor mit den beiden Parametern auf und ergänzen dabei noch ein default Wert.

Der Copy Construktor ruft ebenfalls den mit den zwei Parametern auf.

Da geht es also schlicht darum, dass ich den Code zur Initialisierung nur an einer einzigen Stelle haben will. Also kein doppelter Code.

Das ist also das 08/15 Schema, das man auch bei default Parametern hat. Da es die in Java nicht gibt, muss ich dann überladene Methoden machen.
 

Jw456

Top Contributor
Ok ich habe denn Sinn verstanden danke. Ja es rufen nur die ersten beiden den copicon auf.
Ja es sind genau genommen vier.

Es ist wohl besser es nicht mit eigenen Worten wider zugeben. Da ich im Moment am Handy bin und nicht so viel tippen will.

Ich weiß jetzt worum es geht.
Der Vergleich zu C und den Speicher Modellen war sinnvoll. Da sehe ich auch eine echten sinn. Bei Java weniger.

Ok habe etwas gelernt.
 

mrBrown

Super-Moderator
Mitarbeiter
Ok ich habe denn Sinn verstanden danke. Ja es rufen nur die ersten beiden den copicon auf.
NEIN! Keiner der anderen ruft den Copy-Constructor auf. Die beiden ersten Konstruktoren rufen den dritten Konstruktor auf, das ist aber ein ganz normaler Konstruktor. Nur der vierte ist ein Copy-Konstruktor, der wird aber von keinem anderem Konstruktor aufgerufen - geht auch nichtt, da man dazu schon ein Objekt der Klasse bräuchte.

Ich weiß jetzt worum es geht.
Der Vergleich zu C und den Speicher Modellen war sinnvoll. Da sehe ich auch eine echten sinn. Bei Java weniger.
In Java immer dann sinnvoll, wenn man eine "Kopie" eines Objektes braucht, zB um eine Instanz zu verändern, das Original aber trotzdem zu behalten.

Ein Beispiel in Java, was man darunter zählen könnte, sind alle Collections (und Maps), die jeweils einen Konstruktor haben, der andere Collection (bzw Map) als Parameter bekommt und davon eine Kopie erstellt.
 

Jw456

Top Contributor
NEIN! Keiner der anderen ruft den Copy-Constructor auf. Die beiden ersten Konstruktoren rufen den dritten Konstruktor auf, das ist aber ein ganz normaler Konstruktor. Nur der vierte ist ein Copy-Konstruktor, der wird aber von keinem anderem Konstruktor aufgerufen - geht auch nichtt, da man dazu schon ein Objekt der Klasse bräuchte.


In Java immer dann sinnvoll, wenn man eine "Kopie" eines Objektes braucht, zB um eine Instanz zu verändern, das Original aber trotzdem zu behalten.

Ein Beispiel in Java, was man darunter zählen könnte, sind alle Collections (und Maps), die jeweils einen Konstruktor haben, der andere Collection (bzw Map) als Parameter bekommt und davon eine Kopie erstellt.
Alles gut ich weiß das ich es verstanden habe werde keinen Kommentar hierzu mehr schreiben.

Ja der dritte also keine Begriffe sondern Zahlen. Ist in dem Beispiel wohl besser.

Der vierte wird nur zb in der main zum clonen aufgerufen.

Erkannt hatte ich es danke für eure Mühe.
Der Fehler lag an mir besser gesagt an meiner Ausdrucks weiße nicht am Verständnis. Der Sinn war mir klar.
Nur leider habe ich es etwas falsch formuliert.
Danke für die Berichtigung.
 
Zuletzt bearbeitet:

Ähnliche Java Themen

Neue Themen


Oben