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.
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)
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.
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.
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.
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 ...
** * 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:
Tout d'abord, à partir du contenu au premier point d'arrêt.
Ensuite, le contenu au deuxième point d'arrêt.
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.
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