参考链接:黑马程序员JVM完整教程,全网超高评价,全程干货不拖沓_哔哩哔哩_bilibili

知识补充

常量池

1、常量池,就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
运行时常量池,常量池是 *.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量
池,并把里面的符号地址变为真实地址

2、程序执行时,常量池中的信息(符号)都会被加载到运行时常量池中,但是加载完之后,这些符号还没有成为java对象,只有执行到具体某一行代码的时候,才会转变为java对象,并将字符常量放进串池(StringTable,是一个哈希表,长度固定且不能扩容)中。

java中的数据类型

java中的数据类型分为基本类型和引用类型

1、java中有八种基本数据类型:

  • 整数型(默认int)

byte - 1字节

short - 2字节
       int - 4字节
       long - 8字节,赋值时一般在数字后加上 l 或 L

  • 浮点型(默认double)

float - 4字节,直接赋值时必须在数字后加上 f 或 F
         double - 8字节,赋值时一般在数字后加 d 或 D

  • 字符型

char - 2字节,存储 Unicode 码,用单引号赋值

  • 布尔型

boolean - 1字节,只有 true 和 false 两个取值,一个字节就够了

2、所有的非基本数据类型都是引用数据类型,除了基本数据类型对应的引用类型外,类、 接口类型、 数组类型、 枚举类型、 注解类型、 字符串型都属于引用类型。

主要有以下区别:

  • 基本变量类型在方法中定义的非全局基本数据类型变量的具体内容是存储在栈中的
  • 引用数据类型变量其具体内容都是存放在堆中的,而栈中存放的是其具体内容所在内存的地址
  • 基本数据类型是按值传递
  • 引用数据类型是按引用传递

有了基础知识的补充之后,我们通过两个例子来学习String的intern方法

使用 intern 方法,主动将串池中还没有的字符串对象放入串池

  • jdk1.8 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串池中的对象返回
  • jdk1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份,放入串池(也就是说串池中的对象和这个字符串对象不是同一个), 会把串池中的对象返回

例一、

        String s1 = new String("a")+new String("b");String s2=s1.intern();System.out.println(s2=="ab");System.out.println(s1=="ab");

第一行代码:

因为"a","b"是常量,被依次放入串池中,此时串池中有["a","b"]

new String("a")  new String("b") 是新的对象,放进堆中,值和串池中的相等,但是对象不是同一个。

s1是通过StringBuilder拼接了"a"和"b",形成一个新对象  new String("ab"),也放入堆中,并没有放入串池中,因为"ab"是动态拼接成的,串池中是放常量字符串。

此时堆中有 [new String("a")  new String("b")  new String("ab")]

串池中有["a","b"]

第二行代码:

如果想将"ab"放入串池中,可以调用String的intern()方法,将s1这个字符串对象尝试放入串池,如果有则不会放入,如果没有则将s1放入串池,并把串池中的对象返回。

所以此时串池中有["a","b","ab"],s2引用的对象是串池中的对象

第三行代码:

执行第三行代码时,会在串池中先看看有没有"ab",结果发现有了,就不会再在串池中引用新的对象了,此时==后的"ab"就是串池中的"ab",因此第三行代码结果返回true

第四行代码:

执行第二行代码时已经把s1对象放入了串池,所以第四行代码返回true

程序执行结果如图:

例二

        String s="ab";String s1 = new String("a")+new String("b");String s2=s1.intern();System.out.println(s2==s);System.out.println(s1==s);

第一行代码:

执行第一行代码前,串池是空的,因此在串池中放入常量"ab"

第二行代码:

同例一,在串池中依次放入"a","b",new String("a")  new String("b")  new String("ab")依次放入堆中

此时串池中有["ab","a,"b"],注意:此时堆中的 new String("ab")和串池中的"ab"不是一个对象

第三行代码:

执行intern方法,但是此时串池中已经有"ab",所以s1对象不会放入串池中,而返回的s2是串池中对象,所以执行第四行代码时,返回的结果是true,而第五行代码返回的是false

程序结果如图所示:

总结

String的intern方法,会将这个字符对象尝试放入串池中,如果串池中已经有这个常量,就不将这个对象放入池中,如果没有就将这个对象放入池中,,并且返回的是串池中的对象,也就是说intern方法返回的对象和调用方法的对象不一定是同一个对象,但是值是相同的。

字符串变量拼接的原理是StringBuilder

字符串常量拼接的原理是编译器优化

附录

另外还有一道面试题

String s1 = "a";
String s2 = "b";
String s3 = "a" + "b";
String s4 = s1 + s2;
String s5 = "ab";
String s6 = s4.intern();
// 问
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s3 == s6);
String x2 = new String("c") + new String("d");
String x1 = "cd";
x2.intern();
// 问,如果调换了【最后两行代码】的位置呢,如果是jdk1.6呢
System.out.println(x1 == x2);

我们不运行程序来看一下执行结果:

前三行代码执行完之后,串池中有["a","b","ab"]

s4,s1+s2实际上是通过StringBuilder方法拼接成"ab",放入堆中

s5的"ab"在串池中已经存在,因此不放入串池中,但是和s3是同一个对象

s6行代码执行了intern方法,因为串池中已经有"ab"对象了,所以s4并不放入串池中,凡是返回的是串池中的"ab",因此s6和s3是同一个对象

综上,s3==s4结果为false

s3==s5结果为true

s3==s6结果为true

同理 x1==x2返回false,如果两行代码调换顺序,结果为true

如果是jdk1.6,无论代码换不换,结果都为false,因为在1.6中的intern方法返回的对象和调用方法的对象不是同一个

详解String的intern方法相关推荐

  1. java源码详解——String类

    java源码详解--String类目录: Java String 类 下面开始介绍主要方法: Java charAt() 方法 Java compareTo() 方法 int compareTo(St ...

  2. python expandtabs_详解Python中expandtabs()方法的使用

    详解Python中expandtabs()方法的使用 expandtabs()方法返回制表符,即该字符串的一个副本. '\t'已经使用的空间,可选择使用给定的tabsize(默认8)扩展. 语法 以下 ...

  3. indesign图片规定在左下角_详解InDesign基本使用方法

    详解InDesign基本使用方法 为了使朋友们尽快掌握InDesign的使用方法,下面,我们通过一个例子来说明它的操作过程.做之前,先要说两句.乍一接触Indesign,许多朋友会觉得很不熟悉,很不适 ...

  4. python获取屏幕文字_详解:四种方法教你对Python获取屏幕截图(PyQt , pyautogui)...

    前言: 今天为大家带来的内容是详解:四种方法教你对Python获取屏幕截图(PyQt , pyautogui)本文具有不错的参考意义,希望能够帮助到大家! Python获取电脑截图有多种方式,具体如下 ...

  5. 处理对象(toString()方法详解和==与equals方法的区别)

    处理对象(toString()方法详解和==与equals方法的区别) toString()是一个非常特殊的方法,它是一个自我描述的方法.当程序员直接打印该对象的时候,系统会输出该对象的"自 ...

  6. python导入模块介绍_详解Python模块导入方法

    python常被昵称为胶水语言,它能很轻松的把用其他语言制作的各种模块(尤其是C/C++)轻松联结在一起.python包含子目录中的模块方法比较简单,关键是能够在sys.path里面找到通向模块文件的 ...

  7. ubuntu 文件权限命令详解使用格式和方法

    为什么80%的码农都做不了架构师?>>>    在 Ubuntu Linux 中用源码文件安装软件时经常都会用到chmod命令来更改文件的权限使其在安装时有执行的权限.由于 Ubun ...

  8. 5 获取窗口位置_详解:四种方法教你对Python获取屏幕截图(PyQt , pyautogui)

    前言: 今天为大家带来的内容是详解:四种方法教你对Python获取屏幕截图(PyQt , pyautogui)本文具有不错的参考意义,希望能够帮助到大家! Python获取电脑截图有多种方式,具体如下 ...

  9. Java之String系列--intern方法的作用及原理

    原文网址:Java之String系列--intern方法的作用及原理_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java的String的intern方法的原理. 常量池简介 在 JAVA 语言中 ...

  10. Java String的intern方法

    1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ne ...

最新文章

  1. DSP-SLAM:具有深度形状先验的面向对象SLAM
  2. 【常见问题】Can not perform this action after onSaveInstanceState
  3. 部署及配置Lync Server 2013存档功能
  4. Ajax的get与post的区别,什么时候使用post?
  5. Expression Blend 定义RadioButton行为动画
  6. iOS一些推荐的学习路径发展
  7. 【MFC系列-第10天】非模式对话框开发
  8. android 揭示动画_如何使用意图揭示函数名称使代码更好
  9. linux下安装两个tomcat,linux安装两个tomcat-Go语言中文社区
  10. CTex + Texmaker
  11. 【Python】PyMuPDF模块将PDF转换为图片
  12. MySQL裸机性能测试(2021)
  13. php rpc调用,PHP远程调用, 为什么需要使用RPC
  14. 软件测试项目实战案例ppt,一个自动测试实战项目案例.ppt
  15. 彭国伦Fortran95学习笔记(一)第一至七章
  16. solr面试题_查看您的Solr缓存大小:Eclipse Memory Analyzer
  17. android 微信输入法表情,分析Android 搜狗输入法在微信和QQ中发送图片和表情
  18. ps 毛发 边缘_PS技巧:毛发抠图调整边缘法
  19. YOLOv5、v7改进之三十九:引入改进遮挡检测的Tri-Layer插件 | BMVC 2022
  20. 苹果笔记本显卡性能测试软件,苹果Mac Pro性能测试:好厉害的“垃圾桶”

热门文章

  1. 虫虫 HTML5::初学者使用 Application Cache 指南
  2. GPRS-PDP上下文的激活过程
  3. 文章详情页面评论功能添加及实现原理
  4. 内网端口映射软件之80端口映射全端口映射
  5. [渝粤教育] 宁波财经学院 金融工程学 参考 资料
  6. 【软件架构文档之SOC篇】
  7. 一个电商网站设计方案
  8. c语言判断闰年次数,C语言判断闰年,即判断年份是否为闰年
  9. php token过期时间,token过期是什么意思
  10. 昆明理工大学计算机考研资料汇总