java String类 开辟内存问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java String类 开辟内存问题相关的知识,希望对你有一定的参考价值。

第一:
String str = "abc";
String str2 = str.substring(0, 2) + "c";
String str3 = "ab" + "c";

用“==”号两两比较时,只有str ==str3返回true;而str2的表达式中substring返回的是个新开辟的内存地址么,所以str2 !=str 和str3,从str3中可以看出,“+”号貌似没有新开辟地址的作用,我这样理解对么!

第二:
public static void main()

String str="abc";
if (str.substring(0,1)=="a") 不能通过,即条件不成立
if (str.substring(0,3)=="abc") 可以通过
if (str.substring(0,3)==str) 可以通过

我的理解:每一个用“”号引起来的字符串代表String实例,"a"第一次出现,有具体的内存地址,从str获取子字符串"a"的地址和前面的不同?
第二个虽说是从str取子字符串“abc",但==右边的"abc"已经出现过一次,所以左右2个String实例的内存地址是共享的?
第三个substring返回新实例"abc",由于内容和str一样,他们的内存还是共享的么?

求老师指点!

首先你要知道String是怎么分配内存的,如果使用字符串直接赋值,比如str="abc",那么它会先去常量区找,如果常量区已经有abc,那就直接把str指向abc,如果没有,它就在常量区再分配一个abc。使用new String("abc")的话,不管常量区有没有,它都会在堆里分配一个新的"abc"。

现在回答你的问题。

第一个问题,JAVA的常量字符串+,编译器会自动优化,str3="ab"+"c",经过编译器优化后,实际上等于str3="abc",而常量区已经有一个str分配的"abc",因此str3直接指向str指向的"abc",因此str==str3。
subString(0,2)返回的也是一个string,它的分配也符合上述的规则,subString(0,2)返回"ab",ab在常量区没有对应的值,因此它会另外开辟内存,所以str2 != str。

第二个问题,subString的工作方式是,如果截取的是整个字符串,那它不会新new一个返回,而是直接返回原字符串。因此str.substring(0,3)实际上返回的就是str,所以它们是相等的。str.substring(0,1)截取的是第一个字符"a",这时候返回的也不是你想象的常量区的字符,而是一个新new出来的地址。

我们可以试试:
String str = "abc";
String str2 = "a";
System.out.println(str.substring(0,1) == str2);

System.out.println(str.substring(0,1).equals(str2));

第一个输出false,第二个输出true。因为虽然前面str2初始化后常量区已经有一个"a",但subString截取的字串是新new出来的,不是直接指向常量区的"a“的。
参考技术A 先说下+号吧,String类的处理,String str = "abc";String str3 = "ab" + "c";地址为什么一样,因为java处理String的时候"ab" + "c"俩个常量相加,还是常量,在编译成字节码的时候就被转换为“abc”了,这个可以用反射自己看,所以不是+号没有开辟地址,是因为+两边都是常量的原因

java中String是个特殊的类,首先String 常量的值()是不可变的,比如String str = “123”; 然后你修改它的值str = “321”;
内存变换说明:首先看内存中是否有常量 “123”,有的话(比如在上面有 String str2 =“123”;),str指向该内存(str == str2 返回true),没有的话,创建该常量,str指向该常量,
如果用new 的话,肯定是开辟新的内存,查看substring的实现可以看出,
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
这个实现的部分代码,可以看出,当子串是str的全部的时候,返回的还是str本身,所以str.substring(0,3)==str,如果不是的话,则new的新的字符串,第二部分,首先str=“abc”; str指向常量中的“abc” ,所以str.substring(0,3)=="abc",“abc”就是常量,str.substring(0,1)=="a",str.substring(0,1)是new的,在内存中开辟的,“a”在常量中

最后说下,常量所在的内存空间和new数据所在内存空间不同,分开的两个单独的位置

以上是关于java String类 开辟内存问题的主要内容,如果未能解决你的问题,请参考以下文章

Java基础之String类StringBuffer类StringBuilder类

StringBuffer类

java String 类

在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?

用C语言分配开辟内存问题

StringBuffer类