Java中字符串的创建与储存(附:常见笔试面试题)

常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "java"这种申明方式;当然也可扩充,执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间。

一、字符串的创建与初始化

java中创建并初始化一个String对象,最常见的有两种方式

(1)String str 1= “hello”

JVM会先去字符串池中找有没有"hello",有的话就把str1指向常量池中的"hello"(也就是获取对hello的引用没有就会先在创建一个字符串对象并将其放入到字符串常量池,再让str1指向常量池中的"hello" 

hello放在常量区中,在编译时产生

String str 1= “hello”创建了几个对象?

创建时常量池中没有相同字符串则1个否则0个。

(2)String str1 = new String(“hello”)

      new String(“hello”)此语句等价于“abc”和new String()两个操作。

如果在字符串常量池中不存在“hello”字符串,创建一个字符串常量“hello,并将其添加到字符串常量池中;若存在,则不创建;

new String()会在堆里创建一个新的对象。

str1指向堆中创建的对象

String str1 = new String(“hello”)创建了几个对象?

创建时常量池中没有相同字符串则2个否则1


 常见面试题:

(1)字符串的创建与存储问题

	      public static void main(String[] args)
<span style="white-space:pre">	</span>    {
		String s1 = "abc";//常量池中没有"abc",创建字符串常量"abc"biang放入常量池,让s1指向常量池中的"abc"
		String s2 = "abc";//常量池中已经存在"abc",直接让s2指向常量池中的"abc",s1和s2指向常量池中的同一个对象
		System.out.println(s1 == s2);//true  “==“对你是否指向同一个对象,输出true
		System.out.println(s1.equals(s2));//true  equals方法对比的是指向的对象中的字符串内容是否相同
		
		String s3 = new String("abc");//常量池中已经存在"abc",运行时在堆中生成一个字符串对象,s3指向堆中的对象
		String s4 =  new String("abc");//常量池中已经存在"abc",运行时在堆中新生成生成一个字符串对象,s4指向堆中的对象
		System.out.println(s3 == s4);//false  s3、s4指向对堆中不同的字符串对象
		System.out.println(s3.equals(s4));//true 指向的对象中的字符串内容相同
		
		System.out.println(s1 == s3);// false s1是指向字符串常量区 s3指向的是堆区
		System.out.println(s1.equals(s3));//true 指向的对象中的字符串内容相同
		
	  }


内存空间如下:



(2)字符串的拼接

  1)

	        String str1 = "aaa";  
		String str2 = "bbb";  
		String str3 = "aaabbb";  
		  
		String str4 = "aaa" + "bbb";//两个字面字符串常量直接相加在编译时就str4确定为aaabbb,不会产生新的字符串对象  
		System.out.println(str3 == str4);//true  str4与str3都是指向aaabbb
		  
		str4 = str1 + "bbb";//会产生新的字符串对象  
		System.out.println(str3 == str4);//false  
		  
		str4 = str1 + str2;//会产生新的字符串对象  
		System.out.println(str3 == str4);//false 
		 
		/*
		 * 使用“+”连接的两个字符串本身就是字面常量字符串时,如果池中存在这样连接后的字符串,
		 * 则是不会重新创建对象,而是直接引用池中的字符串对象;如果“+”连接的两字符串中只要
		 * 有一个不是字面常量串(即定义过的),是会产生新的字符串对象。
		 */

2)若在定义字符串变量时加final关键字修饰并且在声明时就赋予初始值

final String str1 = "aaa";  
final String str2 = "bbb";  
String str3 = "aaabbb";  
String str4 = str1 + str2;  
System.out.println(str3 == str4);//true
解析:
  因为str1与str2都定义成了常量,在编译时就能确定,编译时就会将常量替换,等同于 
  str4 = "aaa"+"bbb",因此不产生新对象 
   

3)

final static String str1;    
    final static String str2;  <span style="font-family: Arial, Helvetica, sans-serif;"> </span>
    static {    
        str1 ="aaa";    
        str2 ="bbb";    //此时str1与str2相当于变量,而不是常,因为块是在运行时才能确定,在编译时不能确定 
    }  
    public static void main(String[] args){    
        String str3 = str1 + str2;  
        String str4 ="aaabbb";    
        System.out.println(str3==str4);   //输出为false  
    } 

 

 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值