我们在Java语言中,String类算是用得最频繁的一个类之一了。今天就简单的总结一下String的知识点。
先给出两道题吧:
1. 字符串"我爱java"在内存中占用几个字节?
2. 给出下面程序的运行结果。
1 public class Test { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 String s1 = "abc"; 6 String s2 = "abc"; 7 8 String s3 = new String("abc"); 9 String s4 = s1; 10 11 String s5 = new String(s1); 12 String s6 = "ab"+‘c‘; 13 14 System.out.println(s1 == s2); 15 System.out.println(s1 == s3); 16 System.out.println(s1 == s4); 17 System.out.println(s1 == s5); 18 System.out.println(s1 == s6); 19 20 System.out.println(s1.equals(s3)); 21 System.out.println(s1.equals(s5)); 22 23 } 24 }
个人觉得问题1出得其实并不是特别好,有些误导。按照Java中,字符串都是以String类的来表示的,而String的实现内部由char数组来实现。所有在内存中占的字节数应该是
字符占用的字节数*字符串长度;那么答案出来了:6*2=12;
为什么说这个问题是有些误导倾向,那是因为同样的字符串在不同的编码格式中,占用的字节数是不同的,但是注意,那是经过编码后,才会这样说。所以在utf-8的编码格式下,占用3*2+4 = 10字节;那是因为中文在utf-8占3个字节。而在GBK编码格式下,中文占用2个字节,英文占用1个字节,此时占用2*2+4 = 8字节;
第二题,也是基础题,我们要有以下的概念,对于这种问题就很容易了:
1. 栈区:所有对象的引用都存放在栈区上,栈区的内存由系统管理,脱离生命周期范围,就会自动释放。
2. 堆区:使用new操作符创建的对象,存放在此区域。内存由GC来进行回收。
3. 常量数据区:保存程序中的常量类型,如"abc", 3.14f, 10之类;所有的常量只保留一份;
那么我们现在来分析一下:
String s1 = "abc";
s1为引用,指向字符串对象"abc"; 那么自然s1存放在栈区上,而"abc"是一个字符串常量(也是一个String对象),存放在常量数据区;
String s2 = "abc";
s2为引用,也指向字符串对象"abc", 可以知道s2也存放在栈区,而"abc"在常量区;
因为s1和s2都是为指向"abc"字符串的引用,而s1==s2就是比较s1和s2指向的字符串地址是否相等,所以s1==s2是成立的;
至于s3
String s3 = new String("abc");
s3依然位于栈区,而s3指向的对象则是通过new操作符生成的,那么s3指向的字符串对象是存放在堆上面的。所以s1==s3是不成立。
s4和s6都很简单,s6因为"ab"+‘c‘被JAVA先进行连接操作,得到常量字符串"abc";所以s6 == s1是成立的;
s5也是通过new操作符生成,所以结果和s3类似;
运行结果为:
true false true false true true true
注:因能力所限,欢迎指正,共同进步!