zoukankan      html  css  js  c++  java
  • Java中String对象创建机制详解

    Java中String对象创建机制总是令人困惑,我会尝试阐述清楚这一机制。额,太粗心把 Stack 拼作 Strack 了,我会尽快把图片和文章校对好。

    1.创建方法

    1、  直接使用""双引号创建:

    String s1 = "first";

    2、  使用newString()创建:

    String s2 = new String();

    3、使用newString("string")创建  :

    String s3 = new String("string");

    4、采用重载的字符串连接符创建:   

    String s4 ="first" + "second";

    2.知识准备

    1. JVM


    先需要了解下JVM 的内存区域组成,如果想要深入了解,可以参考深入理解JVM之JVM内存区域与内存分配– HelloCsl[1]

    在Java中String对象创建过程中,所用到的为这三者:


    其中,Heap(堆)是JVM的内存数据区。Heap 的管理很复杂,是被所有线程共享的内存区域,在JVM启动时候创建,专门用来保存对象的实例。

    MethodArea中有个区域被称为Constant Pool,是一个由数组组成的表,用来存储程序中的各种常量,包括Class、String、Integer等各种Java基本数据类型;String Pool是Constant Pool中存储String常量的区域;

    而 VM Strack 中放置了对象的引用(reference类型,不等同于对象本身,根据不同的虚拟机实现,可能是一个指向对象起始地址的引用指针,也可能是一个代表对象的句柄或者其他与对象相关的位置)和 returnAdress类型(指向下一条字节码指令的地址)。

    所以以上三者可以在此简单看作以下三者:


    3.讲解[2]

    注意了,每次讲解创建机制时三者的初始状态都是空白的。


    还有,String的==和equals是不同的,==比较的是两个String在内存中的地址是否相同,equals比较的是两个String的值是否相同。所以,如果String是用双引号方式创建,则两个String都指向常量池中的同一个位置,这时==是成立的,equals也成立。如果String是用new方式创建的,两个String如果不是指向堆上的同一个String对象,则==不成立,而如果值相同,则equals成立[4]

    1. 直接使用" "双引号的创建机制

    Strings1 = "first"; 

    Stirngs2 = "first"; 

    System.out.println(s1== s2); 


    Strings1 = "first";

     

    Stirngs2 = "first";

    1、编译期:"first"是编译期常量,编译期就能确认它的值,在编译好的.class字节码文件中,"first"就已经存在String Pool中了;

    2、运行期:JVM仅仅会查找维护常量池,拿着"first"在String Pool中查找是否存在内容相同的字符串(用equals()方法确认),如果存在,返回String Pool中相应内存单元的引用,赋值给s1(s1即是String Pool中存放"first"内存单元的地址);如果不存在,则创建一个"first"放在String Pool中,返回引用,赋值给s1;s2同理;

    这个过程实际是调用intern()方法实现的;

    此过程中,JVM绝不会在 Strack 创建String对象;

    所以,上述代码,s1与s2指向String Pool中同一块内存区域,是同一个对象,故返回true

    2. 使用new String()创建

    String s3 = new String();


    String s3 = new String()

     

     

    在Java中,使用new关键字创建一个新对象,不管在Constant Pool中是否有值相同的对象,总会创建一个新的String对象存储在堆区(Strack)中,然后返回堆区(Strack)中相应内存单元的引用,赋值给s3;

    3. 使用newString("string")创建;

    String s4 = newString("string");

    String s5 = newString("string");

    System.out.println(s1 == s2);

     

    String s4 = new String("string");

    解释一下这行代码涉及的实例,一共两个,一个是字符串字面量" String "所对应的、驻留(intern)在一个全局共享的字符串常量池中的实例,另一个是通过new String(“String”)创建并初始化的、内容与" String "相同的实例。

    变量就只有一个, String s4[3]

    String s5 = new String("string");

    那么很明显,s4 !=s5;

    4.采用重载的字符串连接符创建

        Stringa="ab"+"cd";

        Stringb="abcd";


    String a="ab"+"cd";

    "ab"和"cd"分别创建了一个对象,它们经过“+”连接后又创建了一个对象"abcd",因此一共三个,并且它们都被保存在字符串池里了[5]

    那么你认为 String b="abcd";会如何呢?


    String b="abcd";

    明白了吧。


     

    参考网页:

    [1] http://www.tuicool.com/articles/b6jUVn深入理解JVM之JVM内存区域与内存分配– HelloCsl

    [2] http://blog.csdn.net/zhangliangzi/article/details/50075281Java中String对象创建机制详解(面试必问)

    [3] http://www.cnblogs.com/YLsY/p/5729113.htmlJava中String两种不同创建方式的区别及intern的用法

    [4] http://www.iteye.com/topic/774673 请别再拿“String s= new String("xyz");创建了多少个String实例”来面试了吧

    [5] http://www.cnblogs.com/alexlo/archive/2013/02/21/2920209.htmlJava 由浅及深之 String 对象的创建及堆、栈的解释

    时间:2017年5月26日22:28:35

  • 相关阅读:
    哈希表,开放地址法之线性探测代码(JAVA)
    Java中几个关键字的意思
    java学习——File类操作
    Map三种遍历方法
    Spring Data Binding
    哈希表的基础理解
    选择排序
    map集合使用
    排序
    关于LinkedList
  • 原文地址:https://www.cnblogs.com/Sherlock-J/p/12926010.html
Copyright © 2011-2022 走看看