为什么要使用String.intern()

最近在阅读《深入理解Jav虚拟机》的运行时常量池章节,看到”java语言并不要求常量池一定只有编译器才能产生…运行期间也可以将新的常量放入常量池,这种特性被开发人员利用得比较多的时String类的intern()方法。”于是我便去深入了解了一下。

1     public static void main(String[] args) {
2         String a="王者";
3         String b="荣耀";
4         String c=a+b;             //编译期常量池不存在"王者荣耀"
5         String d=c.intern();
6         System.out.println(d==c);
7     }

上面为什么是true呢,接下来讲述intern()

为什么要使用String.intern()

JDK1.7后,intern方法先去查询常量池中是否有已经存在,如果存在,则返回常量池中的引用,当字符串常量池中找不到对应的字符串时,而只是生成一个对该字符串的引用在字符串常量池。所以”王者荣耀”本身不会在字符串常量池

前面说了intern可以在程序运行时将新的常量放入运行时常量池,接下来就开始演示intern的强大用处

public static void main(String[]  args) throws Exception {
        long start=System.currentTimeMillis();   //获取开始时间
        String[] arr = new String[10000000];
        Integer[] a= new Integer[10000000];
        for (int i = 0; i < 10000000; i++) {
            a[i] = (int)(1+Math.random()*(3));
        }
        for (int i = 0; i < 10000000; i++) {
            arr[i] = new String(String.valueOf(a[i]));
        }
        long end=System.currentTimeMillis(); //获取结束时间
        System.out.println("程序运行时间: "+(end-start)+"ms");
    }
    //程序运行时间: 14461ms
public static void main(String[]  args) throws Exception {
        long start=System.currentTimeMillis();   //获取开始时间
        String[] arr = new String[10000000];
        Integer[] a= new Integer[10000000];
        for (int i = 0; i < 10000000; i++) {
            a[i] = (int)(1+Math.random()*(3));
        }
        for (int i = 0; i < 10000000; i++) {
            arr[i] = new String(String.valueOf(a[i])).intern();
        }
        long end=System.currentTimeMillis(); //获取结束时间
        System.out.println("程序运行时间: "+(end-start)+"ms");
    }
    //程序运行时间: 1688ms

就是有无调用intern方法,但程序运行时间差了10倍!

我们明确的知道,会有很多重复的相同的字符串产生,但是这些字符串的值都是只有在运行期才能确定的。所以,我们通过intern显示的将其加入运行时常量池

因为随机数是运行期才知道的,假设整个过程只产生”1″,”2″,”3″的字符串,调用了intern()就会把的堆内对象索引放入了运行常量池,下次在看见”1″,”2″,”3″,返回第一次在堆中String的对象地址,不用创建新对象,使用intern()在堆中只会创建6个对象(堆+方法区),而不使用intern则创建100000000个对象,并且常量池里并没有”1″,”2″,”3″

当在编译期知道确定了字面量,new String(“王者荣耀”).intern()没什么意义的,直接就返回了运行时字符串的地址,但intern()并不是这样的初衷,而是为了解决运行时才出现的常量,不是解决编译时在字符串常量池的问题

public class RuntimeConstantPoolOOM {
    public static void main(String[] args) {
        String str1 = new StringBuilder("计算机").append("软件").toString();
        System.out.println(str1.intern() == str1);
        //true

        String str2 = new StringBuilder("ja").append("va").toString();
        System.out.println(str2.intern() == str2);
        //flase
    }
}

最好测试字符串采取选用中文,书中有所描述,防止类加载时,默认加载类加载了字符串导致常量池中以存在真正的字面量

技术有限,如有错误,请指正,谢谢

Original: https://www.cnblogs.com/Dear-John/p/15935714.html
Author: 今晚螃蟹下酒
Title: 为什么要使用String.intern()

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/579328/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • java8 .stream().filter() 代替for循环 lambda表达式

    先说一下lambda表达式:lambda 表达式的语法格式如下:(parameters) -> expression (parameters) ->{ statemen…

    Java 2023年5月29日
    078
  • 稀疏数组

    基本介绍 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。 稀疏数组的处理方法是: 1、记录数组一共有几行几列,有多少个不同的值 2、把具有不同值…

    Java 2023年6月6日
    087
  • Java: 子类和父类实现相同的接口 (转)

    在阅读ArrayList源码的时候看到ArrayList 和 AbstractList 两个类的声明都分别实现了List的接口 可是ArrayList本身就继承自AbstractL…

    Java 2023年5月29日
    089
  • 创建一个springbootcloud项目

    前提软件安装 nacos 服务治理: github下载地址:https://github.com/alibaba/nacos/tags 码云下载地址:https://gitee.c…

    Java 2023年6月9日
    070
  • 从-1开始实现一个中间件

    别人都写从0开始实现xxx,我先从-1开始就显得更牛逼一些。 今天,先开个头,来教大家怎么实现一个中间件。 新建项目 首先,我们新建一个多 module 的项目用于测试。 项目包含…

    Java 2023年6月13日
    074
  • 修改linux系统history命令的条数和格式

    原生的history命令,只能看到输入的命令历史,看不到什么时候,谁输入的。 特此在网上找到修改history命令的办法: 1.用root用户打开系统环境变量设置的文件 vim /…

    Java 2023年6月9日
    0108
  • 老码农的Java干货资源

    https://lingsui.github.io/ Original: https://www.cnblogs.com/zengkefu/p/9081860.htmlAuthor…

    Java 2023年5月29日
    092
  • elasticsearch按URL查询

    排序查询:localhost:9200/get-together/_search?sort=date:asc, 排序以及按字段查询:localhost:9200/get-toget…

    Java 2023年6月7日
    079
  • 三种反射得到对象的方法

    测试用例 public class Example01 { private String name; private int age; public Example01(){} p…

    Java 2023年6月14日
    063
  • 如何运营好技术相关的自媒体?

    一、前言 今天带来的分享是:如何运营好技术相关的自媒体? 这次我会从「理论」和「实践」两块去小小分享: 「理论」分享清楚里面的商业底层逻辑和框架。对于每个赚钱的案例,底层逻辑和理论…

    Java 2023年6月13日
    091
  • RabbitMQ——整合SpringAMQP

    一。什么是Spring-AMQP? 1.Spring框架的AMQP消息解决方案,提供模板化的发送和接收消息的抽象层,提供基于消息驱动的POJO(Plain Ordinary Jav…

    Java 2023年5月30日
    087
  • Java设计模式-单例模式

    Java设计模式——单例模式 描述:确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例 特点:1、单例类只能有一个实例2、单例类必须自己创建自己的唯一实例3、单例类必须…

    Java 2023年6月7日
    079
  • 小数点的几种精确方法

    小数点的几种精确方法 1.直接用格式化输出String.format() double b=123.4; System.out.println(String.format(&quo…

    Java 2023年6月5日
    077
  • 24种设计模式介绍与6大设计原则(PHP版)之工厂方法模式

    女娲补天的故事大家都听说过吧,今天不说这个,说女娲创造人的故事,可不是”造人”的工作,这个词被现代人滥用了。这个故事是说,女娲在补了天后,下到凡间一看,哇塞…

    Java 2023年6月9日
    069
  • Bootstrap相关方法,事件整理

    相关方法 这些方法的调用方法主要是 $(‘#bsTableTest’).bootstrap(”,) 常用的方法有以下: 获取表格的一些基本属性,返回一个 object, key有…

    Java 2023年6月9日
    081
  • 如何 在博客插入 视频 和网页?

    1.插入一个视频* 2.插入一个网页 ** posted @2022-05-02 14:46 且吃茶去 阅读(24 ) 评论() 编辑 //my Original: https:/…

    Java 2023年6月8日
    090
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球