JAVA你真的了解String类型吗(String类型经典内存位置问题深入解读)

你真的了解String类型吗(String类型经典内存位置问题深入解读)

本文讲解一下String的基本情况,对于对应API方法不做涉及,本文所指JAVA环境为JAVA8

主要讲解内容:

public class StringTest {
    public static void main(String[] args) {
        String hello = "Hello";
        String world = "World";
        String hello_world1 = new String("HelloWorld");
        String hello_world2 = hello + world;
        String hello_world3 = "Hello"+"World";
        String hello_world4 = "HelloWorld";
        System.out.println(hello_world1 == hello_world2);
        System.out.println(hello_world1 == hello_world3);
        System.out.println(hello_world1 == hello_world4);


        System.out.println(hello_world2 == hello_world3);
        System.out.println(hello_world2 == hello_world4);


        System.out.println(hello_world3 == hello_world4);
    }
}

在说以上问题之前,我们先了解一下JVM的基本结构(Java8)

在这里插入图片描述
方法区:保存类的结构信息(XXX.Class)的区域

栈:保存程序运行时临时变量、对象的引用和方法的区域

本地方法栈:保存java调用本地方法的区域

程序计数器:进行程序运行指令选择的区域

元空间:HotSpot虚拟机对于方法区的实现

堆:保存我们new对象的区域

以上描述为简易描述,详细内容这里不做重点

String类型在内存中的存储位置有两处

  • StringTable

有了以上的了解,我们就可以基本解决文章开头的问题了

  • String hello = “Hello”;

执行本语句时会先去StringTable中查看是否存在"Hello",如果不存在会在StringTable中创建一个

  • String world = “World”;

同上

  • String hello_world1 = new String(“HelloWorld”);

new 出一个String对象,该语句会在堆内存中创建一个"HelloWorld"的字符串对象

  • String hello_world2 = hello + world;

这一个就有点意思了。它是由两个StringTable变量组合而成的,反编译一下看看

在这里插入图片描述

红框内的代码就是String hello_world2 = hello + world;的运行情况,下面我们来进行一下解读

第6行 new了一个StringBuilder类型的对象

第10行 执行StringBuilder的init方法进行初始化

第14行 执行append方法参数为String类型,没错这就是我们的append(hello)

第18行 执行append方法参数为String类型,这就是我们的append(world)

第21行 执行StringBuilder的toString()方法,来看下源码

在这里插入图片描述

他又new了一个String类型的对象

所以由上可以看出String hello_world2 = hello + world;其实就是相当于

String hello_world2 = new StringBuilder().append(hello).append(world).toString();

也是在堆中新建了一个String对象

  • String hello_world3 = “Hello”+“World”;

那直接取StringTable中的字符串呢?又会是怎样的?

这里就不得不提JAVA8的编译期优化机制了,在编译期间,由于"Hello"与"World"都已经是确定不变的,所以java会直接将"Hello"+"World"变为"HelloWorld"常量,在常量池中查找,找不到在常量池中创建新的常量

  • String hello_world4 = “HelloWorld”;

这个就很明白了,直接在StringTable中查找"HelloWorld"常量,因为之前已经创建过了,所以一定能找到。

最终以上代码在内存中的情况如下图:

在这里插入图片描述

至此,以上问题的答案就算非常明晰了。

答案公布:

hello_world1 == hello_world2 false
hello_world1 == hello_world3 false
hello_world1 == hello_world4 false
hello_world2 == hello_world3 false
hello_world2 == hello_world4 false
hello_world3 == hello_world4 true

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值