- String类是不可变的,看下源码(JDK 1.7)对类的描述
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
- 不能改变状态的意思是,不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变。String类的外部无法修改String。也就是说一旦初始化就不能修改, 并且在String类的外部不能访问这三个成员
- 对不可变类的代码补充解释
// 创建一个String 对象dstring,让他的值为hello
String dString = "hello";
/**
* 让dstring 的值变为world
* 这里string 只是一个引用,指向了一个具体的对象,当dString = "world"; 这句话执行之后,
* 又创建了一个新对象“world” 原来的“hello”还存在内存中,并没与改变
*/
dString = "world";
- 成员变量的String 声明之后 默认值为null
private static String a;
public static void main(String[] args) {
/**
* 成员变量 自动赋值null
*/
System.out.println(a);
- String 的"" 和 null 的问题
/**
* bstring 是申明一个字符串 给他赋值为空
* ctring 是申请一个字符串,没有给他赋值,而是空引用
* 所以第二个会输出出现NPE问题
*/
String bString = "";
String cString = null;
System.out.println(bString.trim());
System.out.println(cString.trim()); //会有NPE问题
/**
* 判断字符串为空
*/
if("" == bString || null == bString) {
//do somthing
}
- 声明String的内存地址相关
String s0= "hello"; //声明的变量存在栈内存中,会留存在字符串常量中缓存
String s1=new String("hello"); //定义的对象直接存在堆内存中,不会进入字符串常量,两个值也不相等
String s2=new String("hello");
System.out.println( s0==s1 ); //flase
- intern方法
直接使用双引号声明出来的String对象会直接存储在常量池中
如果不是使用双引号声明的String对象,可以使用string的intern方法
intern方法会从字符串常量池中查询当前字符串是否存在,若不存在就会把当前字符串放入到常量池中
String s0= "hello"; //声明的变量存在栈内存中,会留存在字符串常量中缓存
String s1=new String("hello"); //定义的对象直接存在堆内存中,不会进入字符串常量,两个值也不相等
String s2=new String("hello");
s1.intern();
s2=s2.intern();
System.out.println( s0==s1.intern() );//true
System.out.println( s0==s2 ); //true