The String Pool
    Sun made an optimization(优化) that is rather confusing to many new Java programmers called the String Pool. It allows for Strings, which are one of the most used Objects to optimize themselves and save space. An important point to make is that the String Pool only applies to String literals(字符常量), meaning their value was assigned(分配), not constructed using a String constructor. Let me start off with an example:

public class Main {public static void main(String[] args) {String s1 = "abc";String s2 = "abc";System.out.println("s1 = " + s1);System.out.println("s2 = " + s2);System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s1.equals(s2)? " + (s1.equals(s2)));      }}

If you run this program, you get this:

Quote

s1 = abc
s2 = abc
s1 == s2? true
s1.equals(s2)? true

Most beginners are told to only compare strings using the .equals() method, simply because it is safer for beginners, however, what is confusing about my program above is that the == operator actually said those two were the same memory location too. How is s1 == s2? I clearly defined 2 different variables! An important concept(概念) about Java that you may not know is that symbols(变量名) (variable names) aren't actually the object that they are defined as. They actually hold a reference to the spot in memory where the actual object is kept. Since Strings are SO commonly (那么频繁)used, Strings literals that are the same are given the same address so that it saves memory and doesn't have to make another. Think about it as if there can only be one of each String in there and anything matching is assigned a reference to that String. However, once all references are gone, then the object is erased(清除). However, once they change, the addresses are different:

ps: 也就是说串池好像是在缓存中存在,最后还是要被清除。

public class Main {public static void main(String[] args) {String s1 = "abc";String s2 = "abc";System.out.println("s1 = " + s1);System.out.println("s2 = " + s2);System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s1.equals(s2)? " + (s1.equals(s2)));s2 += "abc";System.out.println("s1 = " + s1);System.out.println("s2 = " + s2);System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s1.equals(s2)? " + (s1.equals(s2)));}}

This outputs this:

Quote

s1 = abc
s2 = abc
s1 == s2? true
s1.equals(s2)? true
s1 = abc
s2 = abcabc
s1 == s2? false
s1.equals(s2)? false

HOWEVER, if for any reason you want the variables to not occupy(占据) the same location in memory, there are two ways to do this. First, you can use the String constructor, since those are not put into the pool:

public class Main {public static void main(String[] args) {String s1 = "abc";String s2 = new String("abc");System.out.println("s1 = " + s1);System.out.println("s2 = " + s2);System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s1.equals(s2)? " + (s1.equals(s2)));}}

This code says that == is false. And just to prove a point, let's make both of them use constructors:

public class Main {public static void main(String[] args) {String s1 = new String("abc");String s2 = new String("abc");System.out.println("s1 = " + s1);System.out.println("s2 = " + s2);System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s1.equals(s2)? " + (s1.equals(s2)));}}

That code yields:

Quote

s1 = abc
s2 = abc
s1 == s2? false
s1.equals(s2)? true

OR you can assign them in different steps, forcing it to occupy a diffent address for each addition. (First they are the same, then s1 is moved to another spot to add on the "c" and the same for s2):

public class Main {public static void main(String[] args) {String s1 = "ab";String s2 = "a";s1 += "c";s2 += "bc";System.out.println("s1 = " + s1);System.out.println("s2 = " + s2);System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s1.equals(s2)? " + (s1.equals(s2)));}}

Quote

s1 = abc
s2 = abc
s1 == s2? false
s1.equals(s2)? true

However, there is a way for a literal and a constructor value (assuming value is the same) to == each other. cfoley introduced me to the intern() method of the String class. What this method does is it looks at its value, and if it matches a value ALREADY IN the String pool, it returns a reference to the object in the pool, else it adds itself to the pool. Observe:

public class Main {public static void main(String[] args) {String s1 = "abc";String s2 = new String("abc");s2 = s2.intern();System.out.println("s1 = " + s1);System.out.println("s2 = " + s2);System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s1.equals(s2)? " + (s1.equals(s2)));}}

This returns:

Quote

s1 = abc
s2 = abc
s1 == s2? true
s1.equals(s2)? true

Cool huh? This happens because s1 is ASSIGNED to "abc" and is added to the pool. s2, however, is constructed to "abc", but not added to the pool. But the intern() method sees that the VALUE "abc" is already in the pool and thus returns the reference to s1. I got a challenge problem for you now. Will s1 == s2 in the following code?

public class Main {public static void main(String[] args) {String s1 = new String("abc");String s2 = new String("abc");s2 = s2.intern();System.out.println("s1 = " + s1);System.out.println("s2 = " + s2);System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s1.equals(s2)? " + (s1.equals(s2)));}}

... The answer is no. The intern() method is called, but neither s1 nor s2 is in the pool so all the intern() method does is add it to the pool. To make THESE ==, you must call intern() twice so that there is already a reference in the pool (from the first call).

public class Main {public static void main(String[] args) {String s1 = new String("abc");String s2 = new String("abc");s2 = s2.intern();s1 = s1.intern();System.out.println("s1 = " + s1);System.out.println("s2 = " + s2);System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s1.equals(s2)? " + (s1.equals(s2)));}}

Quote

s1 = abc
s2 = abc
s1 == s2? true
s1.equals(s2)? true

That's all I have on that for now! Make sure to give cfoley kudos for helping me study the intern() method! I encourage you all to experiment with this, as I'm sure there is SOMETHING that I missed in this huge concept.

转载于:https://blog.51cto.com/5628811/1066485

java String pool相关推荐

  1. [java]The String Pool

    The String Pool     Sun made an optimization(优化) that is rather confusing to many new Java programme ...

  2. java builder pool_每周10道Java面试题:String, String Pool, StringBuilder

    每周10道 Java 面试题由 ImportNew 整理编译自网络. 1. 写出下面代码的运行结果. int src = 65536; Integer dst = new Integer(65536) ...

  3. Java字符串池(String Pool)深度解析

    在工作中,String类是我们使用频率非常高的一种对象类型.JVM为了提升性能和减少内存开销,避免字符串的重复创建,其维护了一块特殊的内存空间,这就是我们今天要讨论的核心,即字符串池(String P ...

  4. java字符串常量池长度_Java String类相关知识梳理(含字符串常量池(String Pool)知识)...

    目录 1. String类是什么 1.1 定义 1.2 类结构 1.3 所在的包 2. String类的底层数据结构 3. 关于 intern() 方法(重点) 3.1 作用 3.2 字符串常量池(S ...

  5. 深入理解Java String 池概念(String pool concept)

    String 池(pool) 是一个特殊的内存区域,它有别于传统能够存储字符串常量的栈(heap)区.在应用程序的生命周期内,这些对象应用string变量.在Java中,String能够使用多种方式被 ...

  6. java string改变的影响_为什么Java的string类要设成immutable(不可变的)

    最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String类为什么要设成immutable类 ...

  7. java --String类解决面试问题

    2019独角兽企业重金招聘Python工程师标准>>> 1.概述 字符串对象是一种特殊的对象.String类是一个不可变的类..也就说,String对象一旦创建就不允许修改 Stri ...

  8. java: String的==与equals

    string 是对象,所以==对于string来说,是对比的内存地址: 解释第一个:a==c//为true. 因为b被final修饰,那么它本身是一个常量,如果你原意的话,你可去看看编译后的class ...

  9. java const string_深入研究Java String

    开始写 Java 一年来,一直都是遇到什么问题再去解决,还没有主动的深入的去学习过 Java 语言的特性和深入阅读 JDK 的源码.既然决定今后靠 Java 吃饭,还是得花些心思在上面,放弃一些打游戏 ...

最新文章

  1. 第十六届全国大学生智能车竞赛全国总决赛报名信息汇总
  2. join为什么每个字符都分割了 js_JS截取与分割字符串常用技巧总结
  3. 网络配置之ifconfig及Ip命令详解
  4. 关于有限自动机的一篇不错的文章
  5. 会计期间的开关(T-code:OB52)
  6. r语言 c 函数返回值,R语言入门 输出函数 cat、print、paste等区别理解
  7. 热成像成像不清楚是什么时候_「从零搞机」热成像仪查看 分形工艺Node 202 机箱 风道散热情况...
  8. 36个非常有趣的互动网站设计作品范例
  9. 方立勋_30天掌握JavaWeb_JavaBean、mvc开发模式、el表达式、jstl标签
  10. thinkphp [数据分页]
  11. IT小知识:文件扩展名小知识大全(A~Z)文件扩展名大全
  12. 互联网寒冬怎么过?一程序员裸辞之后,找不到理想的工作,慌的很
  13. java汉字转拼音,pinyin4j简单介绍
  14. CAD图纸打印时如何去掉图纸边框的白边?
  15. 系统论、控制论和信息论
  16. Vue上传文件 iview Upload UI 组件上传组件
  17. RGB24 To Yuv420 C语言 +汇编实现(windows平台)
  18. [Unity3D]用C#在unity里面写一个简单的红绿灯
  19. DDIA读书笔记 | 第七章:事务
  20. 万用表多功能校准仪TD1850多表校准系统

热门文章

  1. day3.python 学习之列表
  2. Solaris10 for x86网卡替换配置
  3. css中的三种基本定位机制
  4. CCF201612-1 中间数(100分)
  5. DIY一个DNS查询器:了解DNS协议
  6. /usr/lib/x86_64-linux-gnu/libopencv_highgui.so.2.4.9: undefined reference toTIFFIsTiled@LIBTIFF_4.0'
  7. sed线上经典案例之-同时替换多个字符串
  8. 受损骨骼可能在类似地球的重力条件下更快愈合
  9. Laravel深入学习5 - 应用架构
  10. activiti源码编译