返回顶部
首页 > 资讯 > 精选 >Java String中intern方法怎么使用
  • 793
分享到

Java String中intern方法怎么使用

2023-06-30 15:06:54 793人浏览 独家记忆
摘要

今天小编给大家分享一下Java String中intern方法怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧

今天小编给大家分享一下Java String中intern方法怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    常量池简介

    在 JAVA 语言中有8种基本类型和一种比较特殊的类型String。这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池(在方法区)的概念。常量池就类似一个JAVA系统级别提供的缓存。8种基本类型的常量池都是系统协调的,String类型的常量池比较特殊。

    String的常量池的主要使用方法有两种:

    直接使用双引号声明出来的String对象会直接存储在常量池中。

    如果不是用双引号声明的String对象,可以使用String提供的intern方法将其放到常量池。

    intern方法简介(jdk7)

    原型:public native String intern();

    说明:

    字符串常量池中查询当前字符串是否存在(通过equals判断)。

    • 如果存在,返回常量池中的字符串引用。

    • 如果不存在,把这个String对象引用存到常量池,然后返回这个String对象的引用。

    返回值:都是返回String变量对应的字符串常量池的引用。

    示例

    package com.example; public class Demo {    public static void main(String argv[]) {        String s = "test";        System.out.println(s == s.intern());    }}

    JDK6及之前:输出false

    JDK7及之后:输出true

    原理(JDK6与JDK7)

    常量池里的字符串的由来

    JDK6及以前调用String.intern()

    • 若常量池中有,则返回常量池中这个字符串的引用

    • 若常量池中没有,则拷贝一份对象,放到常量池(永久代)中;返回值是常量池(永久代)中对应字符串实例的引用。

    JDK7及以后调用String.intern()

    • 若常量池中有,则返回常量池中这个字符串的引用

    • 若常量池中没有,则拷贝一份引用,放到常量池(堆)中;(JDK1.7将String常量池从Perm区移动到了Java Heap区)

    例程测试

    例程1: 

    package org.example.a; public class Demo {    public static void main(String argv[]) {        String s1 = new String("1");        s1.intern();        String s2 = "1";        System.out.println(s1 == s2);         String s3 = new String("1") + new String("1");        s3.intern();        String s4 = "11";        System.out.println(s3 == s4);    }}

    结果

    jdk6:false false
    jdk7:false true
    jdk8:false true

    例程2: 

    package org.example.a; public class Demo {    public static void main(String argv[]) {        String s1 = new String("1");        s1.intern();        String s2 = "1";        System.out.println(s1 == s2);         String s3 = new String("1") + new String("1");        String s4 = "11";        s3.intern();        System.out.println(s3 == s4);    }}

    上述代码第二部分有个对调。

    结果

    jdk6:false false
    jdk7:false false
    jdk8:false false

    例程分析

    下边图中:绿色线条代表 String 对象的内容指向。 红色线条代表地址指向。

    jdk1.6

    例程1与例程2的分析

    Java String中intern方法怎么使用

    如上图所示。首先说一下 jdk6中的情况,在 jdk6中上述的所有打印都是 false 的,因为 jdk6中的常量池是放在 Perm 区中的,Perm区和正常的 JAVA Heap 区域是完全分开的。上面说过如果是使用引号声明的字符串都是会直接在字符串常量池中生成,而 new出来的 String 对象是放在 JAVA Heap 区域。所以拿一个 JAVA Heap 区域的对象地址和字符串常量池的对象地址进行比较肯定是不相同的,即使调用String.intern方法也是没有任何关系的。

    jdk1.7

    在 Jdk6 以及以前的版本中,字符串的常量池是放在堆的Perm区的,Perm区是一个类静态的区域,主要存储一些加载类的信息,常量池,方法片段等内容,默认大小只有4m,一旦常量池中大量使用 intern 会产生java.lang.OutOfMemoryError:PermGen space错误的。在 jdk7 的版本中,字符串常量池已经从Perm区移到正常的Java Heap区域了。为什么要移动,Perm 区域太小是一个主要原因,当然据消息称jdk8已经直接取消了Perm区域,而新建立了一个元区域。应该是jdk开发者认为Perm区域已经不适合现在 JAVA的发展了。字符串常量池移动到JAVA Heap区域,现在解释为什么会有上述的打印结果。

    例程1的分析

    Java String中intern方法怎么使用

    1.String s1 = new String("1"); 

    分析:这行代码生成了2个对象(常量池中的“1” 和 JavaHeap 中的字符串对象)。s.intern(); 这一句是 s1 对象去常量池中寻找后发现 “1” 已经在常量池里了。

    此时s1指向的是Java Heap中的字符串对象。

    2.String s2 = "1"; 

    分析:这行代码生成一个 s2的引用指向常量池中的“1”对象。 结果就是 s1 和 s2 的引用地址不同。

    3.String s3 = new String("1") + new String("1");

    分析:这行代码生成了2个对象(字符串常量池中的“1” 和 Java Heap中的 s3 引用指向的对象“11”(中间还有2个匿名的new String("1")我们不讨论它)。
    此时s3 是Java Heap中的字符串对象的引用,对象内容是”11″,此时常量池中是没有 “11”对象的。

    4.s3.intern();

    分析:这行代码将 s3中的"11"字符串放入String 常量池中,因为此时常量池中不存在"11"字符串,因此常规做法是跟 jdk6 图中表示的那样,在常量池中生成一个"11"的对象,关键点是 jdk7 中常量池不在Perm区域,而是在堆中了。常量池中不需再存储一份对象了,可以直接存储堆中的引用。这份引用指向s3引用的对象。 也就是说引用地址是相同的。

    此时,s3是Java Heap中的字符串对象的引用,对象内容是”11″,此时常量池中是有 “11”对象,它保存的就是s3引用地址。

    5.String s4 = "11"; 

    这行代码”11″是显式声明的,因此会直接去常量池中创建,创建时发现已经有这个对象了。

    此时:s4 == 常量池的“11”对象引用 == s3引用对象的引用

    例程2的分析

    Java String中intern方法怎么使用

    String s1 = new String("1");

    s1.intern();

    String s2 = "1";

    分析:s1.intern();,这一句往后放也不会有什么影响了,因为对象池中在执行第一句代码String s = new String("1");的时候已经生成“1”对象了。下边的s2声明都是直接从常量池中取地址引用的。 s1 和 s2 的引用地址是不会相等的。

    String s3 = new String("1") + new String("1");

    分析:这行代码生成了2个对象(字符串常量池中的“1” 和 Java Heap中的 s3 引用指向的对象“11”(中间还有2个匿名的new String("1")我们不讨论它)。

    此时s3 是Java Heap中的字符串对象的引用,对象内容是”11″,此时常量池中是没有 “11”对象的。

    String s4 = "11";

    分析:声明 s4 的时候常量池中是不存在“11”对象的,执行完后,s4是常量池里“11“对象的引用。

    s3.intern(); 

    分析:此时常量池中“11”对象已经存在了,不会有任何操作,s3仍然是堆中String对象的引用。因此 s3 != s4

    应用实例

    package org.example.a; import java.util.Random; public class Demo {    static final  int MAX = 1000 * 10000;    static final String[] arr = new String[MAX];    public static void main(String argv[]) {        Integer[] DB_DATA = new Integer[10];        Random random = new Random(10 * 10000);        for(int i = 0; i < DB_DATA.length; i++){            DB_DATA[i] = random.nextInt();        }         long t = System.currentTimeMillis();        for(int i = 0; i < MAX; i++){            //arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length]));            arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length])).intern();        }         System.out.println((System.currentTimeMillis() -t) + "ms");        System.GC();    }}

    上述代码是一个演示代码,其中有两条语句不一样,一条是使用 intern,一条是未使用 intern。

    运行的参数是:-Xmx2g -Xms2g -Xmn1500M

    不用intern

    2160ms

    Java String中intern方法怎么使用

    使用intern

    826ms

    Java String中intern方法怎么使用

    通过上述结果,我们发现不使用 intern 的代码生成了1000w 个字符串,占用了大约640m 空间。 使用了 intern 的代码生成了1345个字符串,占用总空间 133k 左右。其实通过观察程序中只是用到了10个字符串,所以准确计算后应该是正好相差100w 倍。虽然例子有些极端,但确实能准确反应出 intern 使用后产生的巨大空间节省。

    细心的同学会发现使用了 intern 方法后时间上有了一些增长。这是因为程序中每次都是用了 new String 后, 然后又进行 intern 操作的耗时时间,这一点如果在内存空间充足的情况下确实是无法避免的,但我们平时使用时,内存空间肯定不是无限大的,不使用 intern占用空间导致 JVM 垃圾回收的时间是要远远大于这点时间的。 毕竟这里使用了1000w次intern 才多出来1秒钟多的时间。

    以上就是“Java String中intern方法怎么使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网精选频道。

    --结束END--

    本文标题: Java String中intern方法怎么使用

    本文链接: https://lsjlt.com/news/329734.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • Java String中intern方法怎么使用
      今天小编给大家分享一下Java String中intern方法怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧...
      99+
      2023-06-30
    • JDK8中String的intern()方法实例详细解读
      目录一、前言二、图文理解String创建对象1.例子一2.例子二3.例子三4.例子四5.例子五6.例子六三、深入理解intern()方法1. 源码查看2. 例子一3. 例子二4. 例...
      99+
      2024-04-02
    • Java string中的compareTo方法怎么使用
      这篇文章主要讲解了“Java string中的compareTo方法怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java string中的compareTo方法怎么使用”吧!一,j...
      99+
      2023-06-22
    • Java main方法中的String[] args怎么使用
      这篇文章主要介绍了Java main方法中的String[] args怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java main方法中的String[] args怎么使用文章都会有所收获,下面我们...
      99+
      2023-06-27
    • 详解JavaString中intern方法的原理与使用
      目录简介常量池简介intern方法简介(JDK7)原理(JDK6与JDK7)例程测试例程分析jdk1.6jdk1.7应用实例简介 本文介绍Java的String的intern方法的原...
      99+
      2024-04-02
    • java中string的使用方法是什么
      在Java中,String是一个类,用于表示字符串。String类提供了丰富的方法来处理字符串,包括以下常用方法: 创建字符串:...
      99+
      2024-04-08
      java
    • java中string的方法怎么应用
      在Java中,String类是一个常用的类,提供了许多可以对字符串进行操作的方法。下面是一些常见的String方法及其应用:1. l...
      99+
      2023-09-23
      java
    • Java中String怎么使用
      今天小编给大家分享一下Java中String怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1.String概述Str...
      99+
      2023-06-29
    • string怎么在java中使用
      这篇文章给大家介绍string怎么在java中使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序。1.创...
      99+
      2023-06-14
    • string在java中怎么使用
      在Java中,字符串(String)是一个类,用于表示文本数据。你可以使用字符串类型来存储和操作文本。以下是一些在Java中使用字符...
      99+
      2023-09-25
      string java
    • Java中String类有哪些使用方法
      这篇文章给大家分享的是有关Java中String类有哪些使用方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。StringString类:代表字符串,提供了开发中常用的字符串处理的方法,如:求字符串的长度、截取字...
      99+
      2023-06-29
    • string compareto方法怎么使用
      String类的compareTo方法用于比较两个字符串的大小关系。它的使用方法如下: 语法: int compareTo(Stri...
      99+
      2023-10-25
      string
    • Java中String类常用方法使用详解
      目录一、length()二、equals三、charAt()四、indexOf()五、trim()六、compareTo()七、toLowerCase()八、toUpper...
      99+
      2022-11-13
      Java String类 常用方法 Java String类 方法 Java String类
    • Java中String类的使用方法有哪些
      这篇文章主要介绍“Java中String类的使用方法有哪些”,在日常操作中,相信很多人在Java中String类的使用方法有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中String类的使用方法...
      99+
      2023-06-25
    • Java中的String类使用方法有哪些
      今天小编给大家分享一下Java中的String类使用方法有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。StringSt...
      99+
      2023-07-06
    • java中getstring方法怎么使用
      在Java中,`getString()`方法通常是指从用户输入的控制台读取字符串的方法。它可以使用`Scanner`类来实现。下面是...
      99+
      2023-09-23
      java
    • java中trim方法怎么使用
      在Java中,`trim()`方法是用于去除字符串两端的空白字符(包括空格,制表符,换行符等)的方法。使用`tri ...
      99+
      2023-08-31
      java trim
    • java中getdescription()方法怎么使用
      在Java中,`getDescription()`方法通常用于获取对象的描述信息。此方法的具体使用方式取决于具体的对象类型和实现。一...
      99+
      2023-09-22
      java
    • java中wait方法怎么使用
      在Java中,wait()方法是Object类的一个方法,用于使当前线程进入等待状态,直到其他线程调用notify()或notify...
      99+
      2023-09-16
      java
    • Java中containsKey方法怎么使用
      在Java中,containsKey方法用于判断一个Map集合中是否包含指定的key。其使用方法如下:1. 导入Map类所在的包:`...
      99+
      2023-09-12
      Java
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作