这篇是补上昨天的,内容说的比较笼统,方便大家理解。
String 类
String类 是 java.long 包中最常用的一个类
先来一个简单的例子
1 public class ClassTest { 2 public static void classTest() { 3 String str1; 4 5 str1 = "Hello Java"; 6 7 String str2 = "Hello Java"; 8 9 String str3 = new String("Hello Java"); 10 11 String str4 = str2; 12 13 System.out.println("str1==str2=>" + (str1 == str2)); 14 System.out.println("str2==str3=>" + (str2 == str3)); 15 System.out.println("str1==str3=>" + (str1 == str3)); 16 System.out.println("str1==str4=>" + (str1 == str4)); 17 System.out.println("str2==str4=>" + (str2 == str4)); 18 System.out.println("str3==str4=>" + (str3 == str4)); 19 } 20 21 public static void main(String args[]) { 22 classTest(); 23 } 24 }
简单的猜测一下结果。感觉貌似都相等。但是实际结果是:
str1==str2=>true
str2==str3=>false
str1==str3=>false
str1==str4=>true
str2==str4=>true
str3==str4=>false
这里需要借助几个简单的表格来说明问题:
整理了个图片格式的,但是现在上传不上来。
现在先文字说明一下。
String str1 在栈中开辟了一个空间来存放这个名字。
"Hello Java" 在堆中开辟内存空间来存放内容。
当用str1="Hello Java";命令时,str1指向的地址,指向了"Hello Java"所在的地址。
同理str2也是这样的过程。所以在最终输出结果的时候,str1==str2。
这里涉及到了几个小的知识点:
1.Java中String对象,如果内容是重复的话,不会开辟多个堆空间。就如str1和str2相等是来自于这个。
2."Hello Java" 其实是一个匿名对象。
str3 的内容有些复杂,首先是在堆空间中,开辟了一块"Hello Java"的空间。然后在栈空间开辟了一块str3的空间。
由于使用了new标识符,这样,又会在堆空间开辟了一块"Hello Java"的空间,而此时,这两块堆的地址是不同的,并且,此时str3指向了第二块堆空间。导致最后用==判断的时候,结果显示为false。
str4最好理解了,即在栈空间开辟了str4空间,指向了str2所指向的地址。
此时在引出一个问题。即,由上面"Hello Java" 为一个匿名对象而引出的。
因为"Hello Java"这个字符串可以调用String对象的所有方法。那么其实,说的宽泛一点,其实,"Hello Java" 可以看作是一个String类型的变量。
那么比如说
现在代码是这样:
String str5 = "Hello"; str5 += " Java"; System.out.println("str2==str5=>" + (str2 == str5));
这样返回的结果也是false
简单来说,首先是在栈中开辟了str5,然后在堆中开辟"Hello",假设地址为0x001,然后在堆中开辟" Java",假设地址为0x002,由于加等的关系,在内存中开辟"Hello Java",假设内存地址为0x003,然后将栈中的str5指向了地址0x003。然后地址0x001,0x002,成为垃圾数据,被java垃圾回收机制回收。
如此说来,String对象的内容是不会发生改变的,改变的只是引用的地址。。。纠结。
此外其实还引出了一个问题,就是相如刚才str5这样的,不断的+=的过程,其实是非常浪费资源或者效率低下的,至于怎么处理,以后几篇里我觉得应该会有答案,我也在不断探索啊,估计还会单独拿出堆栈这个问题来说事。