Java之String理解

 

一、String在内存中的存储情况

1.Java虚拟机JVM的内存块及其变量、对象内存空间是怎么存储分配的?

1、栈:存放基本数据类型及对象变量的引用,对象本身不存放于栈中而是存放于堆中

             1)、基础类型 byte (8位)、boolean (1位)、char (16位)、int (32位)、short (16位)、float (32位)、double (64位)、long (64位)

             2)、java代码作用域中定义一个变量时,则java就在栈中为这个变量分配内存空间,当该变量退出该作用域时,java会自动释放该变量所占的空间

2、堆:new操作符的对象

             1)、new创建的对象和数组

             2)、在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理

3、静态域:static定义的静态成员变量

4、常量池:存放常量

package terry.java.base;

public class StringTest {
     public static void main(String[] args) {
      String a = "hello";
      String b = "hello";
      
      String newA = new String("hello");
      String newB = new String("hello");
      
      System.out.println("****** Testing Object == ******");
      System.out.println("a==b ? :" + (a==b));
      System.out.println("newA==newB ? :" +(newA==newB));
      System.out.println("a==newA ? :" + (a==newA));
      
      System.out.println("***** Testing String Object intern method******");
      System.out.println("a.intern()==b.intern() ? : " + (a.intern()==b.intern()));
      System.out.println("newA.intern()==newB.intern() ? :" + (newA.intern()==newB.intern()));
      System.out.println("a.intern()==newA.intern() ? :" + (a.intern()==newA.intern()));
      System.out.println("a=a.intern() ? :" + (a==a.intern()));
      System.out.println("newA==newA.intern() ? : " + (newA==newA.intern()));
      
      System.out.println("****** Testing String Object equals method******");
      System.out.println("equals() method :" + a.equals(newA));
      
      String c = "hel";
      String d = "lo";
      final String finalc = "hel";
      final String finalgetc = getc();
      
      System.out.println("****** Testing Object splice ******");
      System.out.println("a==\"hel\"+\"lo\" ? :" + (a=="hel"+"lo"));
      System.out.println("a==c+d ? : " + (a==c+d));
      System.out.println("a==c+\"lo\" ? : " + (a==c+"lo"));
      System.out.println("a==finalc+\"lo\" ? :" + (a==finalc+"lo"));
      System.out.println("a==finalgetc+\"lo\" ? :" + (a==finalgetc+"lo"));
      
     }
     private static String getc(){
      return "hel";
     } 
}

********************Testing Object ************************

(1)a、b 创建的 hello 都存在于方法区中的常量池其中的字符串池,故第一条 true 。

(2) newA、newB 创建的 hello 存在于堆中,指向不同的对象,故 false 。

(3)a 创建的 hello 存在于方法区中的常量池其中的字符串池,而 newA 创建的 hello 存在于堆中,故false 。

******************Testing intern method********************

当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。

(1)都指向字符串常量池中的hello,所以true

(2)都指向字符串常量池中的hello,所以true

(3)都指向字符串常量池中的hello,所以true

(4)都指向字符串常量池中的hello,所以true

(5)newA指向堆中的hello对象,newA.intern()指向字符串常量池中的hello,所以为false;

*********************Testing equals method**********************

equals方法检测两个字符串的内容是否相同,而==运算符检测两个字符串是否放置在同一个位置上。

(1)a和newA内容相同,所以true;

**********************Testing Object splice**************************

(1) "hel" + "lo"的创建是先进行表达式的字符串连接,然后才进行赋值。赋值的时候会搜索池中是否有 hello 字符串,若有则指向该字符串,若没有则在池中新增该字符串。显然 “hel” + "lo" 的创建是用了a 已经创建好的字面量,故 true 。

(2) a == c + d ?; 其实相当于  a== new String(c + d) ?; new String(c + d)  是存放于堆中的,不是字面量。所以 false 。

(3)JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的,所以c+\"lo\"实际是c在栈中保存的地址+字符串"lo"于常量池中指向的地址 所指向的在堆中新分配的一块内存空间,所以false

(4)对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量 池中或嵌入到它的字节码流中,在编译期就已经确定了内存空间地址,所以此类似于2个字符串常量的+ ,所以true

****** Testing Object == ******
a==b ? :true
newA==newB ? :false
a==newA ? :false
***** Testing String Object intern method******
a.intern()==b.intern() ? : true
newA.intern()==newB.intern() ? :true
a.intern()==newA.intern() ? :true
a==a.intern() ? :true
newA==newA.intern() ? : false
****** Testing String Object equals method******
equals() method :true
****** Testing Object splice ******
a=="hel"+"lo" ? :true
a==c+d ? : false
a==c+"lo" ? : false
a==finalc+"lo" ? :true
a==finalgetc+"lo" ? :false

上述各个变量及引用在JVM分配的内存情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值