I was learning Java Silver SE11, and I didn't understand the meaning of "String object is an immutable object", so I added a memorandum.
What is the difference between mutable (variable) and immutable (immutable) in the first place? Simply put, a mutable object is an object ** that can change the value once set ** later. An immutable object is an object that cannot change the value once set **. It is as it is.
The definition method of immutable object is as follows.
--Qualify all fields with private --Do not provide methods (such as setters) that can change the state inside the object --Declare the class in final to ensure that the method is not overridden (do not change from subclass) --If you have a variable object inside, don't provide that object to the outside (getter, etc.)
From the next section, we will check the details of each by creating an immutable class: Hoge. (Other classes are listed, but these are not immutable.)
This is easy to understand, isn't it? If you qualify with public, you can change it as much as you want.
Test.java
public class Test {
public static void main(String args[]){
Hoge hoge = new Hoge("Daigouji", "Guy" ,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; }
}
The access modifiers for the fields, name, age, and foo of class Hoge are private. Yes.
This is also easy to understand. Even if you qualify with private, it doesn't mean anything if you can change it via a method.
Test.java
public class Test {
public static void main(String args[]){
Hoge hoge = new Hoge("Daigouji", "Guy" ,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; }
}
You can no longer make changes via the method.
Class: Let's create a HogeSub that inherits Hoge.
Test.java
public class Test {
public static void main(String args[]){
HogeSub hogesub = new HogeSub("Daigouji", "Guy", 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; }
}
The execution result is as follows.
Execution result
lastName:Daigouji firstName:Guy
-----------------
lastName:Yamada firstName:Jiro
HogeSub overrides Hoge's dummy method and modifies the foo field. To avoid such an implementation, declare Hoge as final.
Test.java
public class Test {
public static void main(String args[]){
Hoge hoge = new Hoge("Daigouji", "Guy", 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; }
}
You can no longer change fields by overriding.
In the previous stage, the value of the object was changed via the getter of the field: foo.
Hoge.getFoo().setXXXName(”xxx”);
If you do this kind of operation, you can't say that it's immutable. Also delete the getter.
Test.java
public class Test {
public static void main(String args[]){
Hoge hoge = new Hoge("Daigouji", "Guy", 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; }
}
You now have an immutable class: Hoge. The finished Hoge can't do anything, but please forgive me as a sample ...
** * This section is a guess. Please point out any mistakes. ** **
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);
}
}
Execution result
Sutoringu 1
-----------------
Sutoringu 2
Certainly the content of str has changed. It's important to note that ** the value of the variable str has changed (referenced to), but the value of the instance hasn't changed **.
I will follow it with a debugger. Set breakpoints as follows:
First of all, from the contents at the first breakpoint.
Next, the content at the second breakpoint.
You can see that the reference destination of str has changed.
The String class is special, and you can instantiate it with the assignment operator without using the new operator.
(str =" Storingu 2 ";
and str = new String ("Storingu 2 ");
are both the same process)
In other words, setting a string in a String type variable with the assignment operator is synonymous with creating an instance each time.
(Strictly speaking, it is not always generated every time)
Depending on how you use it, you may end up consuming more and more memory on the JVM. I presume that the RingBuilder class was created to solve these problems.
After all, I felt that the output would deepen my understanding (although it is speculative). I will continue to do my best to acquire Silver / SE11.
Recommended Posts