Java字符串常量池示例详解

作者:FhToday 时间:2021-10-11 10:55:02 

为什么会有常量池的概念?

不知道小伙伴们是否有思考过这个问题? 没有思考也无所谓,小编在这里类比一下,大家就会清晰了。什么是池? 我们听的最多的池,应该是数据库连接池. 为什么会有数据库连接池,其实就是为了节省资源,提高性能,防止重复创建连接,避免占用内存和网络资源。

常量池其实就是跟数据库连接池的目的都是一样的。那么他是如何实现的呢? 因为常量池是JVM的概念,源码我们也不好看,所以我们还以连接池来类比。

池化的目标就是缓存和管理

稍微提一点池化的概念,其实就是对资源做一个包装,在包装层来加一些对这个资源的属性信息,比如使用次数,最后操作时间,最长生命周期一样。然后通过后台线程对资源包装层的扫描,来对真实资源的做一个管理。Google的Guava的Cache就是这么做的,我们自己也可以利用 common-pool2 工具包自己来做,或者说池化。

Java字符串常量池

在 JDK 1.7 之前,HotSpot 虚拟机中的字符串常量池都在方法区中,用永生代实现。JDK 1.7 及以后的版本,字符串常量池移到了堆里。

JDK 1.6 的 String.intern 方法会将首次遇到的 String 对象复制到永久代,并返回这个对象的引用。

JDK 1.7 的 String.intern 方法不再复制,而是记录首次出现的 String 对象的引用。

以下用 JDK 1.8 实验探究字符串常量池。


// test1
String s1 = "red";
String s2 = "red";
System.out.println(s1 == s2); // true

// test2
String s3 = new String("red");
String s4 = new String("red");
System.out.println(s3 == s4); // false

// test3
System.out.println(s1 == s3); // false

// test4
System.out.println(s3.intern() == s1); // true
System.out.println(s3.intern() == s3); // false
System.out.println(s3.intern() == s4); // false

// test5
String s5 = new String("thunder");
String s6 = s5.intern();
String s7 = "thunder";
System.out.println(s5 == s6); // false
System.out.println(s6 == s7); // true

// test6
String s8 = new String("1") + new String("1");
// String s8 = new StringBuilder().append().toString()
String s9 = s8.intern();
String s10 = "11";
System.out.println(s8 == s9); // true
System.out.println(s9 == s10); // true

常量池可以看作是一个集合,没有重复的元素。用双引号创建的对象直接放到常量池,new 一定会在堆中创建一个新的对象,如果常量池没有值相同的对象那么会在常量池也创建一个对象。intern 的作用是判断常量池是否包含值相同的字符串,是则返回这个字符串对象的引用,否则将当前实例的引用放到常量池并返回当前实例的引用。

另外,字符串的拼接实际上是用了 StringBuilder,所以字符串 s8 的创建会伴随以下对象的创建:

  • 堆中两个不同的 String 对象 1

  • 字符串常量池中一个 String 对象 1

  • 一个 StringBuilder 对象

  • 堆中的 String 对象 11

由于 s8 的创建方式不是 new String 而是拼接,所以不会在常量池中创建值为“11”的对象,这也是 test5 和 test6 要对比的问题。

总结

来源:https://juejin.cn/post/6989609445785337870

标签:java,字符串,常量池
0
投稿

猜你喜欢

  • 从java中调用matlab详细介绍

    2023-08-01 14:04:17
  • Spring实战之ResourceLoader接口资源加载用法示例

    2023-11-20 12:16:49
  • Android为View添加拖放效果的方法实例

    2023-06-25 18:53:45
  • 详解springboot集成mybatis xml方式

    2022-08-05 09:04:54
  • 使用Nexus搭建Maven私服教程的方法步骤

    2023-03-05 18:56:58
  • spring中的FactoryBean代码示例

    2023-11-11 18:37:20
  • java读取xml配置参数代码实例

    2023-11-25 03:03:17
  • MyBatis-Plus 查询返回实体对象还是map

    2023-11-28 03:20:19
  • Spring Security实现自动登陆功能示例

    2023-01-29 15:31:55
  • spring cloud gateway请求跨域问题解决方案

    2021-11-05 11:19:25
  • java锁synchronized面试常问总结

    2023-08-01 05:11:37
  • Java Socket实现单线程通信的方法示例

    2022-04-22 15:43:02
  • 详解Android Flutter中SliverAppBar的使用教程

    2023-06-23 12:11:27
  • 为什么Java开发需要配置环境变量

    2023-08-13 13:11:03
  • IntelliJ IDEA 下载安装超详细教程(推荐)

    2023-11-19 23:50:16
  • Netty实现简易版的RPC框架过程详解

    2023-05-23 23:19:58
  • 一文带你了解RabbitMQ消息转换器

    2023-11-15 23:22:28
  • 利用POI生成EXCEL文件的方法实例

    2023-11-23 21:44:14
  • SpringBoot @Validated注解实现参数分组校验的方法实例

    2023-01-02 11:18:50
  • Android编程开发之TextView单击链接弹出Activity的方法

    2023-08-06 18:27:11
  • asp之家 软件编程 m.aspxhome.com