String 类和常量池

  • 一、String 类和常量池
  • 二、String s1 = new String("abc");这句话创建了几个字符串对象?
  • 三、8 种基本类型的包装类和常量池

一、String 类和常量池

String 对象的两种创建方式:

String str1 = "abcd";//先检查字符串常量池中有没有"abcd",如果字符串常量池中没有,则创建一个,然后 str1 指向字符串常量池中的对象,如果有,则直接将 str1 指向"abcd"";
String str2 = new String("abcd");//堆中创建一个新的对象
String str3 = new String("abcd");//堆中创建一个新的对象
System.out.println(str1==str2);//false
System.out.println(str2==str3);//false

这两种不同的创建方法是有差别的。

  • 第一种方式是在常量池中拿对象;
  • 第二种方式是直接在堆内存空间创建一个新的对象。

记住一点:只要使用 new 方法,便需要创建新的对象。
如图:

String 类型的常量池比较特殊。它的主要使用方法有两种:

  • 直接使用双引号声明出来的 String 对象会直接存储在常量池中。
  • 如果不是用双引号声明的 String 对象,可以使用 String 提供的 intern 方法。String.intern() 是一个 Native 方法,它的作用是:如果运行时常量池中已经包含一个等于此 String 对象内容的字符串,则返回常量池中该字符串的引用;如果没有,则在常量池中创建与此 String 内容相同的字符串,并返回常量池中创建的字符串的引用。
String s1 = new String("计算机");String s2 = s1.intern();String s3 = "计算机";
System.out.println(s2);//计算机
System.out.println(s1 == s2);//false,因为一个是堆内存中的 String 对象一个是常量池中的 String 对象,
System.out.println(s3 == s2);//true,因为两个都是常量池中的 String 对象

字符串拼接:

String str1 = "str";
String str2 = "ing";String str3 = "str" + "ing";//常量池中的对象
String str4 = str1 + str2; //在堆上创建的新的对象
String str5 = "string";//常量池中的对象
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false


尽量避免多个字符串拼接,因为这样会重新创建对象。如果需要改变字符串的话,可以使用 StringBuilder 或者 StringBuffer。

二、String s1 = new String(“abc”);这句话创建了几个字符串对象?

将创建 1 或 2 个字符串。如果池中已存在字符串文字“abc”,则池中只会创建一个字符串“s1”。如果池中没有字符串文字“abc”,那么它将首先在池中创建,然后在堆空间中创建,因此将创建总共 2 个字符串对象。

验证:

String s1 = new String("abc");// 堆内存的地址值
String s2 = "abc";
System.out.println(s1 == s2);// 输出 false,因为一个是堆内存,一个是常量池的内存,故两者是不同的。
System.out.println(s1.equals(s2));// 输出 true

结果:

false
true

三、8 种基本类型的包装类和常量池

  • Java 基本类型的包装类的大部分都实现了常量池技术,即 Byte,Short,Integer,Long,Character,Boolean;这 5 种包装类默认创建了数值[-128,127] 的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象。
  • 两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。
Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出 true
Integer i11 = 333;
Integer i22 = 333;
System.out.println(i11 == i22);// 输出 false
Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);// 输出 false

Integer 缓存源代码:

/**
*此方法将始终缓存-128 到 127(包括端点)范围内的值,并可以缓存此范围之外的其他值。
*/public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}

应用场景:

  1. Integer i1=40;Java 在编译的时候会直接将代码封装成 Integer i1=Integer.valueOf(40);,从而使用常量池中的对象。
  2. Integer i1 = new Integer(40);这种情况下会创建新的对象。
  Integer i1 = 40;Integer i2 = new Integer(40);System.out.println(i1==i2);//输出 false

Integer 比较更丰富的一个例子:

  Integer i1 = 40;Integer i2 = 40;Integer i3 = 0;Integer i4 = new Integer(40);Integer i5 = new Integer(40);Integer i6 = new Integer(0);System.out.println("i1=i2   " + (i1 == i2));System.out.println("i1=i2+i3   " + (i1 == i2 + i3));System.out.println("i1=i4   " + (i1 == i4));System.out.println("i4=i5   " + (i4 == i5));System.out.println("i4=i5+i6   " + (i4 == i5 + i6));   System.out.println("40=i5+i6   " + (40 == i5 + i6));

结果:

i1=i2      true
i1=i2+i3   true
i1=i4      false
i4=i5      false
i4=i5+i6   true
40=i5+i6   true

解释:
语句 i4 == i5 + i6,因为+这个操作符不适用于 Integer 对象,首先 i5 和 i6 进行自动拆箱操作,进行数值相加,即 i4 == 40。然后 Integer 对象无法与数值进行直接比较,所以 i4 自动拆箱转为 int 值 40,最终这条语句转为 40 == 40 进行数值比较。

java 虚拟机(3)相关推荐

  1. Dalvik虚拟机与java虚拟机的区别

    1.Java虚拟机运行的是Java字节码,而Dalvik虚拟机运行的则是其专有的文件格式DEX(Dalvik Executable). 2.Java虚拟机将.java文件编译成字节码文件(.class ...

  2. 深入理解Java虚拟机——第二章——Java内存区域与内存溢出异常

    运行时数据区域 Java虚拟机运行时数据区域 程序计数器 程序计数器可以看做是当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过改变这个计数器的值来选取下一条所需要执行的字节码指令,分支. ...

  3. 《Java虚拟机规范》阅读(三):Class文件格式

    每一个Class都对应着唯一的一个类或借口的定义信息.这里,我们称为"Class文件格式"只是通俗的将任意一个符合有效的类或借口的格式这么称呼,但是它并不一定是以磁盘文件的形式存在 ...

  4. 手写java_手写JAVA虚拟机(二)——实现java命令行

    咱们都知道,咱们编译.java并运转.class文件时,需求一些java指令,如最简略的helloworld程序.java初学者可以看一下下面的教程. 这儿的程序最好不要加包名,因为加了包名的话编译和 ...

  5. java 参数类型不确定_详细解析Java虚拟机的栈帧结构

    什么是栈帧? 正如大家所了解的,Java虚拟机的内存区域被划分为程序计数器.虚拟机栈.本地方法栈.堆和方法区.(什么?你还不知道,赶紧去看看<Java虚拟机内存结构及编码实战>)这次要介绍 ...

  6. mysql种编译码写在哪_深入理解Java虚拟机(程序编译与代码优化)

    对于性能和效率的追求一直是程序开发中永恒不变的宗旨,除了我们自己在编码过程中要充分考虑代码的性能和效率,虚拟机在编译阶段也会对代码进行优化.本文就从虚拟机层面来看看虚拟机对我们所编写的代码采用了哪些优 ...

  7. 《深入理解Java虚拟机》(第二版)学习3:垃圾收集器

    垃圾收集器 如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现. 我们这里讨论的收集器主要是基于JDK 1.7 Update 14之后的 Hotspot VM . Serial 收 ...

  8. 《深入理解Java虚拟机》(第二版)学习1:JVM的内存划分

    运行时数据区 先来一张图描述一下 JVM 的内存划分 PS:自己画的,丑是难免丑了点- 程序计数器(Program Counter Register) 程序计数器(Program Counter Re ...

  9. java线程的优先级是数字越大优先级越高_《深入理解Java虚拟机》5分钟速成:12章(Java内存模型与线程)...

    第12章 Java内存模型与线程 前言: 1.物理机如何处理并发问题? 2.什么是Java内存模型? 3.原子性.可见性.有序性的具体含义和应用实现? 4.volatile 关键字特性? 5.基于vo ...

  10. [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义...

    前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine  ,既然是虚拟机, ...

最新文章

  1. 5 款非常好用的开源 Docker 工具,get一波~
  2. 物理学需要哲学,哲学需要物理学
  3. [好东西]使用ngrok把本机的网站端口映射到外网
  4. Eclipse 修改文本编码方式
  5. 阿里云黄海宇:窄带高清2.0——让直播更惊艳的魔术
  6. pwm波如何控制电机代码_PWM波控制720电机
  7. Markdown入门指导
  8. android代码重启设备,Android设备重启(reboot)---Android studio
  9. linux孟庆昌第六章课后题_第六章 参数估计-矩估计:通过课后题理解矩估计
  10. 在fedora linux中,wine 成功安装手记
  11. 联想(ThinkServer) RD650做硬件 raid5 配置
  12. 详细的苹果快捷键,赶快保存吧!
  13. groupby.nth_熊猫groupby first vs groupby nth vs groupby head
  14. limbo模拟器android版,limbo模拟器app[安卓虚拟机] v0.9.8 Android版
  15. 蓝牙耳机的LDAC、aptX指的都是什么?
  16. [论文笔记] SSE-PT: Sequential Recommendation Via Personalized Transformed
  17. wps底纹去不掉_WPS广告太多,关又关不掉,其实它有无广告的版本
  18. 开源IoT操作系统Mynewt使用简介
  19. C#双色球——简单抽取中奖号码
  20. 交换机的基本配置实验报告

热门文章

  1. Ant是什么东西(初级)
  2. Django 数据库常用字段类型
  3. 图像的 matlab代码,常用的一些图像处理Matlab源代码
  4. 代码风格检查工具vera++
  5. RK3188 5.1平台PCM2708 USB声卡调试
  6. Ctrl c 复制html,一键复制粘贴(用热键代替Ctrl+X、Ctrl+C、Ctrl+V)
  7. IntelliJ IDEA上debug模式启动
  8. redis集群设置密码
  9. Ubuntu下查看显卡型号及NVIDIA驱动版本
  10. rk3568 移植 GPS/GNSS 模组