`

String的疑惑-String对象在内存中的位置

    博客分类:
  • java
 
阅读更多
“String倒底奇特在哪里?”关于这个问题本来想放过它的,但听说java面试经常考它,而且博友又给我提了不少珍贵的意见,所以准备在尽点力。

废话到此,下面正式开始



1.请看下面这幅图片:



         是否觉得奇怪,在1处为true,2处为false!对java有所了解都知道“s1==s2"比较的并非它们在的值(那时该用:s1.equals(s2)),而是比较他们在内存中的地址!难道s1,s2引用的是内存中的同一个数据,呵呵,正是如此!

        由于String对象在编程中使用的极为平凡,故而随着程序的增长,势必造成String常量占有了大量的内存,而且往往包含这大量的冗余。假设String与其他类的特性相同,势必造成如下局面:



         从中不难看到,内存中充斥这大量的冗余常量"pig","dog",而实际上我们只需要两个常量就可以了。为了解决这个问题,从而使java更高效的使用内存,JVM留出一块特殊的内存区域——“String常量池”。(对String够优待吧)

        所以当编译器遇到String s1 = "pig";时,首先检查String常量池中是否有存在"pig", 如果没有,则将pig放入常量池中,如下图:



      继续,当编译器遇到String s2 = "pig";时,首先检查String常量池中是否有存在"pig", 如果发现相同的常量"pig", 则只是把指向常量池中现有的,而不创建任何新的String对象。如下:



     到此,我们应该可以弄明白为什么1处运行的结果是true了吧!

     同时,我们也可以弄明白我上一篇文章的疑惑了,如果常量池中的发生了变化,则s1,s2将会同时变化,这也太可怕了吧,所以java绝对不允许出现这种情况!这也是我们常说的那句话:String对象不可改变!
         PS:由于担心String常量池出现问题,String类被标识为final。

        下面这个例子可能更加让你无法质疑,我就不在这里废话了:


public class Test {

  public static void main(String[] args) {

    String s1 = "pig";

    Person person = new Person();
    person.name = "pig";

    System.out.println(person.name == s1);// 输出为true

  }

}


Person.java



public class Person    {
  public String name;

}



    至于2处为false,这表明在String s3 = new String("pig")这种情况下,因为我们使用了new 关键字,所以将在常规内存(非String常量池)中创建了一个新的String对象,并且将引用它(到此和普通的对象一样)。此外,常量"pig"将放置在池内。

    众多面试答案中所说的String s3 = new String("pig");创建了两个对象,一个引用(句柄)是否指如下状态:(这里只是猜测,希望哪位高人给个正确答案,或者验证方法,小弟在此先行谢过!)





s3==s4比较的是s3,s4引用对象的地址,自然不相同,所以2处运行为false。



参考资料:《SCJP学习指南》

本文出自 “sunfish 翻车鱼” 博客,请务必保留此出处http://sunfish.blog.51cto.com/417500/113108
分享到:
评论

相关推荐

    java string用法详解

    String 在 Java 中使用过于频繁,为了避免在系统中产生大量的 String 对象,Java 的设计者引入了“字符串常量池”的概念。当使用双引号创建一个字符串时,首先会检查字符串常量池中是否有相同的字符串对象,如果有,...

    JAVA初学者在学习的过程中总是会遇到一些很疑惑的问题

    在JAVA学习过程中,初学者总是会遇到一些很疑惑的问题,往往是知其然不知其所以然。下面针对这些基础的问题进行一个详细的解答,以便后来者少走弯路,知其然知其所以然。 问题一:String 声明和引用 JAVA 语言中,...

    浅谈JavaScript中的string拥有方法的原因

    例如,通过`new String("hello")`创建一个String对象,此时变量`str1`的类型是`object`,而直接赋值的字符串`str2`类型则是`string`。这样的区别在处理方法调用时尤其需要注意,因为对象方法和原始值方法的行为可能...

    java 基础问题集

    在Java中,局部变量(在方法内部声明的变量)存储在堆栈中,而对象引用和实例变量存储在堆内存中。堆栈内存管理快速高效,适用于生命周期短、创建和销毁频繁的变量。例如,当一个方法被调用时,一个新的堆栈帧会被...

    解决java中的疑惑

    在Java编程语言中,有很多细节和特性可能会让初学者感到困惑。本文将深入探讨几个常见的问题,以帮助初学者更好地理解和使用Java。 1. **内存管理与垃圾回收**:Java引入了自动内存管理机制,即垃圾回收(Garbage ...

    鸡啄米:C++编程入门系列教程

    学习过程中,作者特别标记了一些重难点问题,这将有助于读者在实践中解决常见的编程疑惑。总的来说,这是一个适合初学者的全面而系统的C++入门教程,对于想要踏入C++编程世界的人来说,是一份宝贵的资源。

    每个Java初学者都应该搞懂的六个问题

    虽然`a`和`b`都指向了内容为"foo"的字符串对象,但由于它们是由不同的`new String()`语句创建的,所以它们实际上位于内存的不同位置。因此,使用`==`进行比较返回`false`;而使用`equals()`则会比较字符串的内容,...

    Python基础——笔试面试利器

    在Python中,所有变量都被视为内存中对象的“引用”。这一点非常重要,因为理解这一点有助于我们掌握Python中的参数传递机制。 - **不可更改对象**(Immutable Objects): 在Python中,字符串(string)、元组...

    最新scjp310-065题库

    13. **标准库API**:对Java标准库中的常用类和方法的理解和应用,如String、Date、Calendar等。 备考SCJP 310-065时,考生需要通过题库进行反复练习,理解和掌握这些知识点。提供的两个文件"310-065.exe"和...

    C++程序设计

    此外,实验中提到在使用类和主函数调用时存在疑惑。这通常涉及到类的对象实例化、成员函数调用的语法,以及如何正确地传递和管理数据。解决这类问题的最佳方法是多阅读相关教材,理解C++的面向对象编程基础,同时多...

    数据结构与算法常见问题解答

    **:在数据库索引中,一级索引通常指向具体的记录位置或扇区,具体实现取决于索引的设计和存储系统的特性。 - **B树/B+树为什么那样定义?**:B树和B+树的设计目的是为了提高数据访问速度,尤其是在磁盘等慢速存储...

    java解惑(包括pdf和答案)

    同时,解答疑惑的部分将帮助他们解决学习过程中遇到的具体问题,加速他们的学习进度。在学习过程中,不断实践和总结是掌握任何编程语言的关键,"java解惑"提供的资源无疑是这样的一个实践和学习的优秀工具。

    C++程序设计语言题解

    根据提供的标题“C++程序设计语言题解”和描述“C++程序设计语言题解,解决更多的疑惑”,我们可以推断出这份资料主要聚焦于解答与C++编程相关的各种问题和练习题。C++是一种广泛使用的面向对象的编程语言,由Bjarne...

    《你必须知道的495个C语言问题》

    *2.5 在C语言中是否有模拟继承等面向对象程序设计特性的好方法? 22 2.6 为什么声明extern f(struct x *p); 给我报了一个晦涩难懂的警告信息? 23 2.7 我遇到这样声明结构的代码:struct name {int namelen; ...

    C++primer第四版附带的代码(习题用)

    《C++ Primer Plus》第四版是一本广受欢迎的C++编程教材,旨在帮助读者深入理解和掌握C++语言。书中的代码示例和习题是学习过程中不可或缺的...在实践中遇到问题时,别忘了查阅书籍或在线资源,以加深理解和解决疑惑。

    JAVA解惑

    《JAVA解惑》是一本专为Java初学者和开发者设计的电子书,旨在解决他们在学习和实践Java过程中遇到的各种疑惑。这本书深入浅出地讲解了Java编程语言的关键概念和技术,帮助读者建立扎实的基础,并提升解决问题的能力...

    LUA脚本编程中文教程.zip

    6. **垃圾回收**:Lua自动管理内存,使用引用计数和弱引用策略回收不再使用的对象。 ### 四、 Lua 在游戏开发中的应用 1. **逻辑控制**:Lua脚本可以编写游戏逻辑,如角色行为、事件响应等,便于游戏逻辑的调试和...

    C,C++,JAVA,MFC,WIN32API函数查询工具chm

    同时,对于C语言的函数,如stdio、stdlib、string等头文件中的函数,也有详尽的解释和示例。 Java是一种跨平台的面向对象编程语言,它的标准类库JDK(Java Development Kit)提供了丰富的API,包括I/O流、网络编程...

Global site tag (gtag.js) - Google Analytics