字符串常量池:字符串常量池在方法区中

为了优化空间,为了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串池,每当代码创建字符串常量时,JVM会首先检查字符串常量池。如果字符串已经存在池中,就返回池中的实例引用。如果字符串不在池中,就会实例化一个字符串并放到池中。Java能够进行这样的优化是因为字符串是不可变的,可以不用担心数据冲突进行共享。所以,在常量池中的这些字符串不会被垃圾收集器回收

1.String str = new String("hello");此时创建的2个对象,但是引用str只指向堆中的对象,并没有指向常量池中的对象

创建了2个对象,1.检查常量池中有没有hello,没有的话,创建对象放到常量池中,再创建对象放到堆中。如果常量池有hello对象,则只创建一个对象并放到堆中。

2.字符串常量池在方法区

3.String str = "hello";此时创建1个对象,引用str指向常量池中的对象

检查常量池有无hello,如果有,则把指向该对象,如果没有,创建对象放在常量池里。

4.intern()方法。把字符串变成常量池里的字符串,即是:把引用指向常量池中的对象

如果常量池中已经包含了等于该String对象的字符串,则返回该字符串。否则,将该String对象加入常量池,并返回引用。

5.String s1 = "tom";

 String s2 = "cat";

 String s3 = "tomcat";//创建了一个对象,常量池中。

 String s4 = "tom"+"cat";//不创建对象,jvm认为带双引号的字符串拼接就是一个整体,并且常量池中已经存在tomcat,故此处不创建对象

String s5 = s1 + s2;//创建一个对象"tomcat"

s3 == s4;true

 s3 == s5;false

为什么为false呢?

字符串引用的拼接并不等于带双引号的字符串的拼接,原来两个字符串s1, s2的拼接首先会调用 String.valueOf(obj),这个Obj为s1,而String.valueOf(Obj)中的实现是return obj == null ? "null" : obj.toString(), 然后产生StringBuilder, 调用的StringBuilder(s1)构造方法, 把StringBuilder初始化,长度为str1.length()+16。此时的StringBuilder对象是在堆上创建的!, 接下来调用StringBuilder.append(str2), 把第二个字符串拼接进去, 然后调用StringBuilder.toString返回结果。所以会返回false。

调用了String.valueOf(),产生了stringBuilder,调用它的构造方法,在堆上new出了新对象,然后使用append()方法把第二个字符串s2拼接起来。

实例:

public static void main(String[] args) {
String str1 = new String("abc");
String str2 = "abc";
String str3 = new String("abc");
System.out.println(str1 == str2.intern());
System.out.println(str1 == str3.intern());
System.out.println(str2 == str3.intern());
System.out.println(str2 == str1.intern());
}

  结果:false false true true

  首先intern()方法:

  public String intern()返回字符串对象的规范化表示形式。(这句话到底啥意思我也不太清楚)
  当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。 它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。

  也就是说intern()方法返回的字符串对象肯定是池中的对象而且字符串内容和调用该方法的对象的内容一样。那么结果是false false true true也就不难理解了。str3.intern()和str1.intern()返回的对象就是str2所指向的对象呀。所以我们的结论也得以验证。

java 创建string对象机制 字符串缓冲池 字符串拼接机制 字符串中intern()方法的更多相关文章

  1. java 创建string对象机制 字符串缓冲池 字符串拼接机制

    对于创建String对象的机制,在这一过程中涉及的东西还是值得探究一番的. 首先看通过new String对象和直接赋值的方式有什么区别,看如下代码: public static void main( ...

  2. Java 关于创建String对象过程的内存分配

    一.String s = "abc"  和 String s = new String("abc") 的区别 1.String s = "abc&qu ...

  3. java笔试中创建String对象的思考

    题目是这样的下面那些生成新的String对象() A . String  s = new String(); B . String  s = new String("A"); C. ...

  4. 创建String对象过程的内存分配

      转载自  https://blog.csdn.net/xiabing082/article/details/49759071       常量池(Constant Pool):指的是在编译期被确定 ...

  5. Java:String对象小记

    Java:String对象小记 对 Java 中的 String 对象,做一个微不足道的小小小小记 字节和字符的区别 字节 byte: 一个字节包含8个位(bit),因此byte的取值范围为-128~ ...

  6. 【Java】Java创建String时,什么情况放进String Pool?

    对Java创建String是否放入String pool作代码性的试验. 参考的优秀文章 JAVA面试题解惑系列(二)——到底创建了几个String对象? public String(String o ...

  7. java 创建匿名对象及声明map list时初始化

    java 创建匿名对象 类似于c# 中的 new { a:"aaa",b:"bbb"}; 1 创建匿名对象Object myobj = new Object() ...

  8. 从HotSpot VM源码看字符串常量池(StringTable)和intern()方法

    引言 字符串常量池(StringTable)是JVM中一个重要的结构,它有助于避免重复创建相同内容的String对象.那么StringTable是怎么实现的?"把字符串加入到字符串常量池中& ...

  9. String类中intern方法的原理分析

    一,前言 ​ 昨天简单整理了JVM内存分配和String类常用方法,遇到了String中的intern()方法.本来想一并总结起来,但是intern方法还涉及到JDK版本的问题,内容也相对较多,所以今 ...

随机推荐

  1. UVA 11582 Colossal Fibonacci Numbers(数学)

    Colossal Fibonacci Numbers 想先说下最近的状态吧,已经考完试了,这个暑假也应该是最后刷题的暑假了,打完今年acm就应该会退了,但是还什么都不会呢? +_+ 所以这个暑假,一定 ...

  2. 转载 Unity Text 插入超链接

    using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressi ...

  3. Unicode编码与中文互转

    /** * unicode编码转换为汉字 * @param unicodeStr 待转化的编码 * @return 返回转化后的汉子 */ public static String UnicodeTo ...

  4. 6.MongoDB4.0在Windows环境的下载、安装、配置

    简单来说:MongoDB4.0在Windows下已经不需要再次配置db文件夹之类操作,安装完成直接进行连接测试即可,以下是具体过程(此前网上很多的教程都已经过时) 1.下载:https://www.m ...

  5. Kubernetes-Host网络模式应用

    目录贴:Kubernetes学习系列 在实际生产环境中,有些容器内应用(比如编码器)需要用到物理层面的网络资源(比如组播流).这就要求Kubernetes中的该Pod以HOST模式来启动.以下实验了K ...

  6. liunx 常用命令学习笔记

    通过linux 命令pwd:显示当前所在的目录ls:显示当前目录下的文件cd:切换路径 cd..返回上一级路径mkdir:新建目录rmdir:删除目录 touch:新建文件rm:删除文件 gedit: ...

  7. KVO的使用一

    概述 KVO即Key-Value Observing,它允许一个对象被另一个对象在改变指定的属性值后进行通知.iOS中的应用场景很多,比如model的值发生变化,controller里对model进行 ...

  8. final修饰符与多态

    知识点一.final 最终的可以修饰属性.方法.类1.final修饰的属性,表示常量,初始化以后值不能改变.final修饰引用数据类型的变量,引用地址不能改变.2.final修饰类,不能被继承.比如: ...

  9. 01:云计算三种服务模式SaaS、PaaS和IaaS

    1.1 云计算 1.什么是云计算 1. 云计算服务是指将大量用网络连接的计算资源统一管理和调度,构成一个计算资源池向用户按需服务. 2. 用户通过网络以按需.易扩展的方式获得所需资源和服务(资源包括网 ...

  10. Python将list中的string批量转化成int/float

    data = ['] data = map(eval, data) print data 输出:[1, 3.2, 2] 但是在Python3下我们输入: ls=[1,2,3] rs=map(str,l ...