1.不变性
这里说的不变性指的是类值一旦被初始化,就不能再被改变了,如果被修改,将会是新的类,如程序1-1所示。
//程序1-1
public class App {
public static void main(String[] args) {
String str = "hello steven";
System.out.println(str);
str = "hello mike";
System.out.println(str);
}
}
从代码上来看,str的值好像由"hello steven"被修改为"hello mike",但从debug的日志来看,其实是str的内存地址被修改了。也就说str="hello mike"这个看似简单的赋值,其实已经把str的引用指向了新的String,debug的截图如下所示,str的内存地址已经由507被修改为509。
源码
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
//该值用于字符存储
private final char value[];
}
源码解析
- String被final关键字修饰,说明String类不可能被继承,也就是说String的任何方法,都不会被继承或覆写;
- String中保存数据的是一个char型数组value,value也是被final修饰的,也就是说value一旦被赋值,内存地址便无法修改。此外,value的权限修饰符是private,外部不可访问,并且String也没有开放出可以对value进行赋值的方法,所以说value一旦产生,内存地址就无法修改。
总结
在自定义类时,如果希望类是不可变的,可以参考String类的源码,充分利用final关键字的特性。
2.相等判断
源码
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
public boolean equals(Object anObject) {
//判断内存地址是否相同
if (this == anObject) {
return true;
}
//判断待比较的对象是否是String类型,如果不是直接返回不相等
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
//判断两个字符串的长度是否相等,如果不等则直接返回不相等
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
//依次比较每个字符是否相等,如果有一个不等,直接返回不相等
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
}
源码解析
判断两个String是否相等,首先判断内存地址是否相等,如果相等则两者相等。如果不相等则判断两者长度,长度不一则不相等,否则就挨个比较char数组中的字符是否相等,如果全部相等则两者相等,若有一个不等则两者不相等。