一、设计思想
  为字符串开辟一个字符串常量池,创建字符串常量时,首先检测字符串常量池是否存在该字符串。如存在该字符串对象,返回其引用;若不存在,实例化该字符串并放入常量池中,并返回其引用。
二、实现基础
  (1)String类字符串实例化后的对象是不可变的,初始化是什么则这个对象就永远是什么,相当于是常量,因此String的对象们可以维护成一个常量池。
  (2)运行时字符串常量池中有一个表,总是为池中所有的字符串对象维护一个引用,所以常量池中的这些字符串不会被GC回收。
三、操作常量池的情况

  凡是" "形式定义的字符串一定会操作常量池。
  不满足上面的情况,但是被编译成String str = " "形式的,会操纵常量池(从中取该常量,如果取不到,就创建一个)

  (1)直接赋值
String str = "Java";

  当"Java"字符串对象已经存在于常量池中时,str直接指向常量池中的对象。如果不存在,在常量池中创建"Java",令str指向它。
  (2)运算符重载
String str = "Ja" + "va";

  Java中可以使用+进行两个字符串的拼接。会被直接编译成str = "Java",会操作常量池。事实上这句话在常量池中创建了3个对象:"Ja"、"va"、"Java"(如果常量池中原本没有这些对象)。
  注意,如果是下面的情况:
String temp = "va";
String str = "Ja" + temp;

  或者:
String str = "Ja" + new String("va");

  此时str不会在编译时不会被自动拼接,即不会被编译成str = "Java"的形式,也就不会在常量池中创建"Java"的对象。但是还是会在常量池中创建"Ja"和"va"。
四、图形化的例子
String m = "hello,world";
String n = "hello,world";
String u = new String(m);
String v = new String("hello,world");

1.会分配一个11长度的char[ ]对象['h','e','l','l','o',',','w','o','r','l','d'],并在常量池分配一个由这个char数组组成的字符串对象"hello,world",然后由m去引用这个字符串。
2.用n去引用常量池里边的字符串"hello,world",所以和m引用的是同一个对象。
3.在堆中生成一个新的字符串,但内部的字符数组引用着m内部的字符数组。看一下源码就比较直观了:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/* The value is used for character storage. /
private final char value[];

/** Cache the hash code for the string */
private int hash; // Default to 0

/**

  • Initializes a newly created {@code String} object so that it represents
  • the same sequence of characters as the argument; in other words, the
  • newly created string is a copy of the argument string. Unless an
  • explicit copy of {@code original} is needed, use of this constructor is
  • unnecessary since Strings are immutable.
  • @param original
  • A {@code String}
    */
    public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
    }

4.同样会在堆中生成一个新的字符串,但内部的字符数组引用常量池里边的字符串"hello,world"内部的字符数组,也就是m/n内部字符数组。
  使用图来表示的话,情况就大概是这样的(使用虚线只是表示两者其实没什么特别的关系):

  测试:

String m = "hello,world";
String n = "hello,world";
String u = new String(m);
String v = new String("hello,world");

System.out.println(m == n); //true
System.out.println(m == u); //false
System.out.println(m == v); //false
System.out.println(u == v); //false

五、String的equals()和intern()
  (1)在Java中用==判断左右两边非基本数据类型的引用,是指判断两个引用是否是引用同一个对象。String的equals()方法则是判断两个字符串内部引用的字符数组对象的值是否相同(注意不要求是引用同一个数组对象)。源码如下:
/**

  • Compares this string to the specified object. The result is {@code
  • true} if and only if the argument is not {@code null} and is a {@code
  • String} object that represents the same sequence of characters as this
  • object.
  • @param anObject
  • The object to compare this {@code String} against
  • @return {@code true} if the given object represents a {@code String}
  • equivalent to this string, {@code false} otherwise
  • @see #compareTo(String)
  • @see #equalsIgnoreCase(String)
    */
    public boolean equals(Object anObject) {
    if (this == anObject) {
    return true;
    }
    if (anObject instanceof String) {
    String anotherString = (String)anObject;
    int n = value.length;
    if (n == anotherString.value.length) {
    char v1[] = value;
    char v2[] = anotherString.value;
    int i = 0;
    while (n-- != 0) {
    if (v1[i] != v2[i])
    return false;
    i++;
    }
    return true;
    }
    }
    return false;
    }

  (2)intern()方法:如果常量池中有与本字符串相同的(equals)字符串,就直接返回池中对象的引用,如果没有就在常量池中创建该对象并返回其引用。源码的注释:
/**

  • When the intern method is invoked, if the pool already contains a
  • string equal to this {@code String} object as determined by
  • the {@link #equals(Object)} method, then the string from the pool is
  • returned. Otherwise, this {@code String} object is added to the
  • pool and a reference to this {@code String} object is returned.
    */

  因此对两个字符串使用intern()和==,也可以起到和equals()一样的功能:
String m = new String("xixi");
String n = new String("xixi");
System.out.println(m.intern() == n.intern()); // true
System.out.println(m.equals(n)); // true

来源:https://www.jianshu.com/p/f83a0402e6a0

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

转载于:https://blog.51cto.com/jiaxiaoxu/2371855

String:字符串常量池相关推荐

  1. String 字符串常量池

    java.lang.String类的使用 1.概述 String:字符串,使用一对""引起来表示. 1.String声明为final的,不可被继承 2.String实现了Seria ...

  2. 什么是字符串常量池?

    一.什么是常量池 为了提高性能和减少开销,JVM提供了一个特殊的内存--常量池 常量池,顾名思义:就是存储常量的内存空间,有String字符串常量池.包装类常量池等 String对象的创建形式: St ...

  3. 常量池之字符串常量池String.intern()

    运行时常量池是方法区(PermGen)的一部分. 需要提前了解: 1. JVM内存模型. 2. JAVA对象在JVM中内存分配 常量池的好处 常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现 ...

  4. java string 常量池_用了这么久Java String,你真的懂字符串常量池吗?

    字符串问题可谓是 Java 中经久不衰的问题,尤其是字符串常量池经常作为面试题出现.可即便是看似简单而又经常被提起的问题,还是有好多同学一知半解,看上去懂了,仔细分析起来却又发现不太明白. 本文以 J ...

  5. 1、如何进行字符串常量中的字符定位_Java String:字符串常量池,我相信会有很多朋友不很理解这部分...

    作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池: 字符串常量池的设计意图是什么? ...

  6. 字符串equal_Java String:字符串常量池

    作者:Seven_Nee 来自:https://segmentfault.com/a/1190000009888357 作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以 ...

  7. Java中String类、字符串常量池、字符串常用方法

    String类: String代表字符串类,java中所有双引号中的内容都称为字符串,如:"hello".字符串是不可改变的,因此字符串是可以共享使用的,相当于char字符数组,但 ...

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

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

  9. 【java进阶之路】(Java基础篇)[扩展]深入解析String.intern()及字符串常量池问题

    申明 : 此文仅仅作为个人学习使用 , 如果有人对于String.intern() 十分想要究其原理 , 请参考此文深入解析String#intern - 美团技术团队 8种基本类型的常量池都是系统协 ...

最新文章

  1. 《信息安全系统设计基础》实验四 外设驱动程序设计
  2. 在离线环境中使用.NET Core
  3. STM32F1笔记(十)PWM
  4. web前端java script BOM学习笔记2017.8.1
  5. mui ajax 文件上传,MUI的图片上传和压缩
  6. python 读取txt文件没读到400行_400行Python代码实现文语处理助手(3) - 音频显示-嵌入式系统-与非网...
  7. Maven将jar包install到本地仓库deploy到远程仓库命令
  8. C++ 抛出异常与传递参数的区别
  9. 虚函数 动态绑定 实现方式是:虚函数表
  10. dnf全部使用_DNF:1.13拍卖最后1天物价,花瓣礼箱破千万,果然人人都是黑商
  11. java拦截器_Java拦截器
  12. dos命令远程重启计算机,简单DOS命令实现局域网Windows远程关机
  13. 素数表(Eratosthenes)
  14. kali linux 64bit 2019.1a下启动bbqsql:No module named coros
  15. 计算机四级网络工程师
  16. U盘容量变小?这儿有解决方法!
  17. 《万万没想到》读书笔记及读后感作文3500字
  18. NFC对于大家真的实用吗
  19. java虚拟机win10_主编解读win10系统Java虚拟机错误的详尽解决方法
  20. Centos 7--pdf2htmlEX安装和配置

热门文章

  1. 图解系列之JAVA执行过程
  2. 微信小程序之验证码短信倒计时
  3. 【leetcode】726. Number of Atoms
  4. 在git上面找开源项目遇到的坑
  5. 第四:Pytest框架之命令行参数(二)
  6. Java自动化测试框架-12 - TestNG之xml文件详解篇 (详细教程)
  7. 超实用的微信图片转换工具
  8. MySQL常见的存储引擎的区别?
  9. [Android5 系列—] 2. 开始另外一个活动
  10. mysql mac版_MAMP Pro—PHP/MySQL开发环境