[JAVA] objets mutables et immuables

J'apprenais Java Silver SE11, et je ne comprenais pas la signification de "String object is an immutable object", j'ai donc ajouté un mémorandum.

Différence entre mutable et immuable

Quelle est la différence entre mutable (variable) et immuable (immuable) en premier lieu? En termes simples, un objet mutable est un objet qui peut changer la valeur une fois définie ** plus tard. Les objets immuables sont des objets qui ** ne peuvent pas modifier la valeur une fois définie **. C'est comme il est.

La méthode de définition de l'objet immuable est la suivante.

--Tous les champs sont qualifiés avec privé

Dans la section suivante, nous vérifierons les détails de chacun en créant une classe immuable: Hoge. (D'autres classes sont répertoriées, mais elles ne sont pas immuables)

Qualifiez tous les champs avec privé

C'est facile à comprendre, n'est-ce pas? Si vous vous qualifiez avec public, vous pouvez le modifier autant que vous le souhaitez.

Test.java


public class Test {
    public static void main(String args[]){
        Hoge hoge = new Hoge("Daigouji", "Gars" ,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; }
}

Les modificateurs d'accès pour les champs, nom, âge et toto de la classe Hoge sont privés. Oui.

Ne fournissez pas de méthodes (telles que les setters) qui peuvent changer l'état à l'intérieur de l'objet

Ceci est également facile à comprendre. Même si vous vous qualifiez avec privé, cela ne veut rien dire si vous pouvez le changer via une méthode.

Test.java


public class Test {
    public static void main(String args[]){
        Hoge hoge = new Hoge("Daigouji", "Gars" ,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; }
}

Vous ne pouvez plus apporter de modifications via la méthode.

Déclarez la classe en final pour vous assurer que la méthode n'est pas remplacée (ne changez pas de sous-classe)

Classe: Créons un HogeSub qui hérite de Hoge.

Test.java


public class Test {
    public static void main(String args[]){
        HogeSub hogesub = new HogeSub("Daigouji", "Gars", 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; }
}

Le résultat de l'exécution est le suivant.

Résultat d'exécution


lastName:Prénom Daigouji:Gars
-----------------
lastName:Prénom Yamada:Jiro

HogeSub remplace la méthode factice de Hoge et modifie le champ foo. Pour éviter une telle implémentation, déclarez Hoge comme final.

Test.java


public class Test {
    public static void main(String args[]){
        Hoge hoge = new Hoge("Daigouji", "Gars", 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; }
}

Vous ne pouvez plus modifier les champs en les remplaçant.

Si vous avez un objet variable à l'intérieur, ne fournissez pas cet objet à l'extérieur (getter, etc.)

Dans l'étape précédente, la valeur de l'objet a été modifiée via le getter du champ: foo. Hoge.getFoo().setXXXName(”xxx”); Si vous faites ce genre d'opération, vous ne pouvez pas dire que c'est immuable. Supprimez également getter.

Test.java


public class Test {
    public static void main(String args[]){
        Hoge hoge = new Hoge("Daigouji", "Gars", 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; }
}

Vous avez maintenant une classe immuable: Hoge. Le Hoge fini ne peut rien faire, mais veuillez me pardonner comme échantillon ...

Vous pouvez modifier le contenu de la variable de type String

** * Cette section est une estimation. Veuillez signaler toute erreur. ** **

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);
    }
}

Résultat d'exécution


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

Le contenu de str a certainement changé. Il est à noter que ** la valeur de la variable str a changé (référencée à), mais la valeur de l'instance n'a pas changé **.

Je vais le suivre avec un débogueur. Définissez le point d'arrêt comme suit: image.png

Tout d'abord, à partir du contenu au premier point d'arrêt. image.png

Ensuite, le contenu au deuxième point d'arrêt. image.png

Vous pouvez voir que la destination de référence de str a changé.

La classe String est spéciale et vous pouvez créer une instance avec l'opérateur d'affectation sans utiliser l'opérateur new. (str =" Storingu 2 "; et str = new String (" Storingu 2 "); sont tous les deux le même processus) En d'autres termes, définir une chaîne de caractères dans une variable de type String avec l'opérateur d'affectation est synonyme de création d'une instance à chaque fois. (Strictement parlant, il n'est pas toujours généré à chaque fois)

Selon la façon dont vous l'utilisez, vous risquez de consommer de plus en plus de mémoire sur la JVM. Je suppose que la classe RingBuilder a été créée pour résoudre ces problèmes.

finalement

Après tout, j'ai senti que la sortie approfondirait ma compréhension (bien que ce soit spéculatif). Je continuerai à faire de mon mieux pour acquérir Silver / SE11.

Recommended Posts

objets mutables et immuables
Comparable et Comparator (commande d'objets)
Types primitifs Java, types de référence, immuable, mutable
À propos de la classification et du concept de Immutable / Mutable / Const / Variable de Java et Kotlin.
Convertir des objets Java org.w3c.dom.Document et des chaînes XML
Différence entre final et immuable en Java
Explication des objets Ruby Time et Date
Comparaison des objets JavaScript et des classes Ruby