1.String 类型不可改变
String类型是public final class String,而其实现主要是private final char value[],
这里 final 修饰基本数据类型,不可被更改,
修饰引用数据类型不可指向其他对象,
修饰方法,该方法不可被重写,
修饰类,不可被继承。
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
s1 = "def";
System.out.println(s1 == s2);
System.out.println(s1);
System.out.println(s2);
}
第一个问题 为什么String不可变,s1却可以被重新赋值?
主要原因还是String里的final修饰的数组不可指向其他对象,而String类只是不可被继承。仿照String自己实现OOO类。
import java.util.Arrays;
public final class OOO {
private final char value[];
public OOO(char[] value) {
this.value = value;
}
@Override
public String toString() {
return "OOO{" +
"value=" + Arrays.toString(value) +
'}';
}
}
String代表不可变的字符序列
当字符串重新赋值,需要重写指定内存区域赋值,不能使用原有的value进行赋值
当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能对使用原有的value进行赋值
当调用String的replace方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
一道面试题
public class StringTest {
String str = new String("good");
char[] ch = {'t', 'e', 's', 't'};
public void change(String str, char ch[]) {
str = "test ok";
ch[0] = 'b';
}
public static void main(String[] args) {
StringTest ex = new StringTest();
ex.change(ex.str, ex.ch);
System.out.println(ex.str);//good
System.out.println(ex.ch);//best
}
}
这里char ch[]是一定会变化的,因为Java的值传递。
对于基本类型 ,赋值运算符会直接改变变量的值,原来的值被覆盖。
对于引用类型,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变。
这里ch[]是引用数据类型,所以是一定会改变的,但如果是下面这样ch[]也是不会改变的。
也就是说 change
方法的参数拷贝的是 ch[](实参)的地址,因此,它和 ch 指向的是同一个数组对象。这也就说明了为什么方法内部对形参的修改会影响到实参。
这里建议观看guide哥 为什么java中只有值传递https://javaguide.cn/java/basis/why-there-only-value-passing-in-java.html#%E6%A1%88%E4%BE%8B2-%E4%BC%A0%E9%80%92%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E5%8F%82%E6%95%B01
今天在看Java设计模式时,在享元模式中,作者说了这样一段
这也就对应了