在java中,String a="123";  String b=new String("123");为什么他们所引用的地址不同呢?请用堆和栈来解释。

解决方案 »

  1.   

    a是栈内变量,它的内存保存的是常量池的常量字符串对象对象"123"的地址
    b是栈内变量,它的内存保存的是堆中的new String对象的地址,new String在堆中生成对象,并用常量池的字符串对象"123"初始化堆中的对象,所以堆中的对象的内存的内容和常量池对象的内存的内容一样,但是是不同的两个对象
      

  2.   

    针对前者:
    123在常量池里,a是一个直接指针。b在句柄池包含两个句柄:
    一个对象实例数据句柄指向java堆实例池String实例,包含char数组等数据。一个对象类型句柄指向方法区,包含String.class和serialVersionUID等等数据。
      

  3.   

    首先要分清楚java的内存机制了,总共分为三种,也即堆、栈、方法区。
    堆:连续的内存空间,用于存放new出来的东西
    栈:不连续的内存空间,用于存放局部变量。
    方法去:存放成员变量、类代码、静态语句块。
    a变量表示的在栈区,b变量存放在堆区。不知道你理解了没?
      

  4.   

    第一个在String pool里,第二个是堆。
      

  5.   

    顶1楼
    引用http://blog.csdn.net/zhangerqing/article/details/8093919
    一般初始化方式:String s = "hello world";经过这条语句,JVM的栈内存中产生一个s变量,堆内存中产生hello world字符串对象。s指向了hello world的地址。像上面这种方式产生的字符串属于直接量字符串对象,JVM在处理这类字符串的时候,会进行缓存,产生时放入字符串池,当程序需要再次使用的时候,无需重新创建一个新的字符串,而是直接指向已存在的字符串。引用jdk api
    public String(String original)初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。由于 String 是不可变的,所以无需使用此构造方法,除非需要 original 的显式副本。
      

  6.   


    这是sun的规范,想实现我的虚拟机 内存模型必须分方法区 栈(虚拟机栈、本地方法栈) 堆 程序计数器栈存放的是一个方法中的局部变量 方法出口等信息,每一个方法都对应一个栈帧一个方法从执行开始到执行结束 对应着一个栈帧的入栈和出栈,站里存基础类型int short long double byte char boolean float 和 引用地址long和double 64位站2个spot其余的都站一个spot战中存的引用地址 那引用的地址存放的数据 代表的就是堆里的一个内存地址 堆里存对象实例 和 数组。 明白了吧。这样的作法有利于垃圾的收集。