String的存储和赋值

可能很多java的初学者对String的存储和赋值有迷惑,以下是一个很简单的测试用例,你只需要花几分钟时间便可理解。

1.在看例子之前,确保你理解以下几个术语:

栈 :由JVM分配区域,用于保存线程执行的动作和数据引用。栈是一个运行的单位,Java中一个线程就会相应有一个线程栈与之对应。

堆 :由JVM分配的,用于存储对象等数据的区域。

常量池 :在堆中分配出来的一块存储区域,用于存储显式 的String,float或者integer.例如String str="abc"; abc这个字符串是显式声明,所以存储在常量池。



2.看这个例子,用JDK5+junit4.5写的例子,完全通过测试

import static org.junit.Assert.assertNotSame;  
import static org.junit.Assert.assertSame;  
 
import org.junit.Test;  
 
/** 
* @author Heis 

*/ 
public class StringTest{  
 
    @Test 
    public void testTheSameReference1(){  
        String str1="abc";  
        String str2="abc";  
        String str3="ab"+"c";  
        String str4=new String(str2);  
          
        //str1和str2引用自常量池里的同一个string对象  
        assertSame(str1,str2);  
        //str3通过编译优化,与str1引用自同一个对象  
        assertSame(str1,str3);  
        //str4因为是在堆中重新分配的另一个对象,所以它的引用与str1不同  
        assertNotSame(str1,str4);  
    }  
      

 

这个程序很好理解,因为在解析的时候,"abc"被存储在常量池中,str1和str2的引用都是指向常量池中的"abc"。所以str1和str2引用是相同的。

import static org.junit.Assert.assertNotSame; 
import static org.junit.Assert.assertSame; 

import org.junit.Test; 

/** 
* @author Heis 
* 
*/ 
public class StringTest{ 

@Test 
public void testTheSameReference1(){ 
String str1="abc"; 
String str2="abc"; 
String str3="ab"+"c"; 
String str4=new String(str2); 

//str1和str2引用自常量池里的同一个string对象 
assertSame(str1,str2); 
//str3通过编译优化,与str1引用自同一个对象 
assertSame(str1,str3); 
//str4因为是在堆中重新分配的另一个对象,所以它的引用与str1不同 
assertNotSame(str1,str4); 
} 

} 

  
这里由于编译器做了优化,编译器会先把字符串拼接,再在常量池中查找这个字符串是否存在,如果存在,则让变量直接引用该字符串。所以str1和str3引用也是相同的。
str4的对象不是显式赋值的,编译器会在堆中重新分配一个区域来存储它的对象数据。所以str1和str4的引用是不一样的。


3.知道字符串怎么存储和赋值的,就不难理解在下面这些例子到底创建了几个String对象了

例1:

String str = "abc";

 这里毫无疑问是一个对象

例2:

String a = "abc";
String b = "abc";

 这里呢?有的人可能会说有两个,但是这里其实只有一个对象.这里a和b都应用对象池里的同一个对象.

例3:

String str = "ab" + "cd";

 这里也只有一个,因为这里是字面量的连接,它被优化了,在Java编译的时候就可以确定,然后直接在对象池取,它等同于

String str = "abcd";

例4:

String str1 = "ab";
String str2 = str1 + "cd";

 这里总共有3个对象

例5:

String str = new String("abc");

 这里是两个对象,一个是String类型的引用对象,一个是引用对象所指向的实例对象

 

引用\[1\]和\[2\]中提到,将指向NULL的char型指针赋值string对象会导致段错误。这是因为NULL指针并不指向任何有效的内存空间,而string对象需要有效的内存空间来存储字符串。因此,将NULL赋值string对象会导致访问无效的内存地址,从而引发段错误。引用\[3\]中提到,虽然有时候可以将不使用的对象手动赋值为null,但这并不是一个普遍适用的规则,也不应过度依赖这种做法。所以,在C++中,将NULL赋值string对象是不被推荐的做法。 #### 引用[.reference_title] - *1* [c++中给string对象赋值null会导致程序崩溃](https://blog.csdn.net/m0_37876242/article/details/124339366)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [C++ 给string对象赋值指向NULL的char型指针变量问题](https://blog.csdn.net/sj_djw/article/details/104818373)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Java中当对象不再使用时,不赋值为null会导致什么后果 ?](https://blog.csdn.net/sihai12345/article/details/109465567)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值