[JAVA] veränderliche und unveränderliche Objekte

Ich habe Java Silver SE11 gelernt und die Bedeutung von "String-Objekt ist ein unveränderliches Objekt" nicht verstanden. Deshalb habe ich ein Memorandum hinzugefügt.

Unterschied zwischen veränderlich und unveränderlich

Was ist überhaupt der Unterschied zwischen veränderlich (variabel) und unveränderlich (unveränderlich)? Einfach ausgedrückt ist ein veränderliches Objekt ein Objekt, das den Wert ändern kann, sobald es ** später festgelegt wurde. Unveränderliche Objekte sind Objekte, die ** den einmal festgelegten Wert ** nicht ändern können **. Es ist so wie es ist.

Die Definitionsmethode für unveränderliche Objekte lautet wie folgt.

Ab dem nächsten Abschnitt werden wir die Details der einzelnen Klassen überprüfen, indem wir eine unveränderliche Klasse erstellen: Hoge. (Andere Klassen sind aufgeführt, aber diese sind nicht unveränderlich)

Qualifizieren Sie alle Felder mit privat

Das ist leicht zu verstehen, nicht wahr? Wenn Sie sich für die Öffentlichkeit qualifizieren, können Sie diese beliebig ändern.

Test.java


public class Test {
    public static void main(String args[]){
        Hoge hoge = new Hoge("Daigouji", "Kerl" ,18);
    }
}

class Hoge{
    private String name;
    private int age;
    private Foo foo;

    Hoge(){}
    Hoge(String lastName, String firstName, int age){
        foo = new Foo(lastName, firstName);
        this.name = lastName + firstName;
        this.age = age;
    }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

    public Foo getFoo() { return foo; }
    public void setFoo(Foo foo) { this.foo = foo; }

    public void dummy(){}
}

class Foo{
    private String lastName;
    private String firstName;
    Foo(String lastName, String firstName){ this.lastName = lastName; this.firstName = firstName; }

    public void setLastName(String lastName) { this.lastName = lastName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public String getFirstName() { return firstName; }
}

Die Zugriffsmodifikatoren für die Felder, Namen, Alter und Foo der Klasse Hoge sind privat. Ja.

Stellen Sie keine Methoden (z. B. Setter) bereit, die den Status innerhalb des Objekts ändern können

Das ist auch leicht zu verstehen. Selbst wenn Sie sich für privat qualifizieren, bedeutet dies nichts, wenn Sie es über eine Methode ändern können.

Test.java


public class Test {
    public static void main(String args[]){
        Hoge hoge = new Hoge("Daigouji", "Kerl" ,18);
    }
}

class Hoge{
    private String name;
    private int age;
    private Foo foo;

    Hoge(){}
    Hoge(String lastName, String firstName, int age){
        foo = new Foo(lastName, firstName);
        this.name = lastName + firstName;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }
    public Foo getFoo() { return foo; }

    public void dummy(){}
}

class Foo{
    private String lastName;
    private String firstName;
    Foo(String lastName, String firstName){ this.lastName = lastName; this.firstName = firstName; }

    public void setLastName(String lastName) { this.lastName = lastName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public String getFirstName() { return firstName; }
}

Über die Methode können Sie keine Änderungen mehr vornehmen.

Deklarieren Sie das Klassenfinale und stellen Sie sicher, dass die Methode nicht überschrieben wird (nicht von der Unterklasse ändern).

Klasse: Erstellen wir einen HogeSub, der Hoge erbt.

Test.java


public class Test {
    public static void main(String args[]){
        HogeSub hogesub = new HogeSub("Daigouji", "Kerl", 18);
        System.out.println("lastName:" + hogesub.getFoo().getLastName() + " firstName:" + hogesub.getFoo().getFirstName());
        System.out.println("-----------------");
        hogesub.setLastName("Yamada");
        hogesub.setFirstName("Jiro");
        hogesub.dummy();
        System.out.println("lastName:" + hogesub.getFoo().getLastName() + " firstName:" + hogesub.getFoo().getFirstName());
    }
}

class Hoge{
    private String name;
    private int age;
    private Foo foo;

    Hoge(){}
    Hoge(String lastName, String firstName, int age){
        foo = new Foo(lastName, firstName);
        this.name = lastName + firstName;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }
    public Foo getFoo() { return foo; }
    public void dummy(){}
}

class HogeSub extends Hoge {
    private String lastName;
    private String firstName;

    HogeSub(String lastName, String firstName, int age) {
        super(lastName, firstName, age);
        this.lastName = lastName;
        this.firstName = firstName;
    }

    @Override
    public void dummy() {
        super.getFoo().setFirstName(this.firstName);
        super.getFoo().setLastName(this.lastName);
    }

    public void setLastName(String lastName) { this.lastName = lastName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
}

class Foo{
    private String lastName;
    private String firstName;
    Foo(String lastName, String firstName){ this.lastName = lastName; this.firstName = firstName; }

    public void setLastName(String lastName) { this.lastName = lastName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public String getFirstName() { return firstName; }
}

Das Ausführungsergebnis ist wie folgt.

Ausführungsergebnis


lastName:Daigouji Vorname:Kerl
-----------------
lastName:Yamada Vorname:Jiro

HogeSub überschreibt die Dummy-Methode von Hoge und ändert das foo-Feld. Um eine solche Implementierung zu vermeiden, erklären Sie Hoge als endgültig.

Test.java


public class Test {
    public static void main(String args[]){
        Hoge hoge = new Hoge("Daigouji", "Kerl", 18);
    }
}

final class Hoge{
    private String name;
    private int age;
    private Foo foo;

    Hoge(){}
    Hoge(String lastName, String firstName, int age){
        foo = new Foo(lastName, firstName);
        this.name = lastName + firstName;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }
    public Foo getFoo() { return foo; }
    public void dummy(){}
}

class Foo{
    private String lastName;
    private String firstName;
    Foo(String lastName, String firstName){ this.lastName = lastName; this.firstName = firstName; }

    public void setLastName(String lastName) { this.lastName = lastName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public String getFirstName() { return firstName; }
}

Sie können Felder nicht mehr durch Überschreiben ändern.

Wenn Sie ein variables Objekt im Inneren haben, geben Sie dieses Objekt nicht nach außen (Getter usw.).

In der vorherigen Phase wurde der Wert des Objekts über den Getter des Feldes geändert: foo. Hoge.getFoo().setXXXName(”xxx”); Wenn Sie diese Art von Operation ausführen, können Sie nicht sagen, dass sie unveränderlich ist. Löschen Sie auch Getter.

Test.java


public class Test {
    public static void main(String args[]){
        Hoge hoge = new Hoge("Daigouji", "Kerl", 18);
    }
}

final class Hoge{
    private String name;
    private int age;
    private Foo foo;

    Hoge(){}
    Hoge(String lastName, String firstName, int age){
        foo = new Foo(lastName, firstName);
        this.name = lastName + firstName;
        this.age = age;
    }
    public void dummy(){}
}

class Foo{
    private String lastName;
    private String firstName;
    Foo(String lastName, String firstName){ this.lastName = lastName; this.firstName = firstName; }

    public void setLastName(String lastName) { this.lastName = lastName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public String getFirstName() { return firstName; }
}

Sie haben jetzt eine unveränderliche Klasse: Hoge. Der fertige Hoge kann nichts, aber bitte verzeihen Sie mir als Probe ...

Sie können den Inhalt der Variablen vom Typ String ändern

** * Dieser Abschnitt ist eine Vermutung. Bitte weisen Sie auf Fehler hin. ** **.

Test2.java


public class Test2 {
    public static void main(String args[]){
        String str = "Sutoringu 1";
        System.out.println(str);
        System.out.println("-----------------");
        str = "Sutoringu 2";
        System.out.println(str);
    }
}

Ausführungsergebnis


Sutoringu 1
-----------------
Sutoringu 2

Sicher hat sich der Inhalt von str geändert. Es ist zu beachten, dass sich ** der Wert der Variablen str geändert hat (auf den verwiesen wird), der Wert der Instanz sich jedoch nicht geändert hat **.

Ich werde es mit einem Debugger folgen. Stellen Sie den Haltepunkt wie folgt ein: image.png

Zunächst aus dem Inhalt am ersten Haltepunkt. image.png

Als nächstes der Inhalt am zweiten Haltepunkt. image.png

Sie können sehen, dass sich das Referenzziel von str geändert hat.

Die String-Klasse ist etwas Besonderes, und Sie können mit dem Zuweisungsoperator eine Instanz erstellen, ohne den neuen Operator zu verwenden. (str =" Storingu 2 "; und str = new String (" Storingu 2 "); sind beide der gleiche Prozess) Mit anderen Worten, das Festlegen einer Zeichenfolge in einer Variablen vom Typ "Zeichenfolge" mit dem Zuweisungsoperator ist gleichbedeutend mit dem Erstellen einer Instanz jedes Mal. (Genau genommen wird es nicht immer jedes Mal generiert)

Je nachdem, wie Sie es verwenden, verbrauchen Sie möglicherweise immer mehr Speicher in der JVM. Ich gehe davon aus, dass die RingBuilder-Klasse erstellt wurde, um diese Probleme zu lösen.

Schließlich

Immerhin hatte ich das Gefühl, dass die Ausgabe mein Verständnis vertiefen würde (obwohl es spekulativ ist). Ich werde weiterhin mein Bestes geben, um Silver / SE11 zu erwerben.

Recommended Posts

veränderliche und unveränderliche Objekte
Vergleichbar und Komparator (Objekte bestellen)
Java primitive Typen, Referenztypen, unveränderlich, veränderlich
Über die Klassifizierung und das Konzept von Immutable / Mutable / Const / Variable von Java und Kotlin.
Konvertieren Sie Java org.w3c.dom.Document-Objekte und XML-Zeichenfolgen
Unterschied zwischen final und Immutable in Java
Erläuterung der Ruby Time- und Date-Objekte
Vergleich von JavaScript-Objekten und Ruby-Klassen