IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> JAVA String a = “abc“ 中发生了什么 -> 正文阅读

[Java知识库]JAVA String a = “abc“ 中发生了什么

JAVA String a = "abc" 中发生了什么

和上次int a = 1 后续

测试代码

javac TestCode.java

?public class TestCode {
? ? ?public static void main(String[] args) {
?   ? ? ?// 此处写aaaa是便于看字节码
? ? ? ? ?String aaaa = "bbbb";
? ? ? ? ?aaaa = "cccc";
? ?  }
?}

反编译

javap -v -p -l TestCode(l是小写的L)

注解:javap是jdk自带的反解析工具。作用是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。

?Classfile xxxxx/com/code/baseCode/TestCode.class
? ?Last modified 2021-11-22; size 475 bytes
? ?MD5 checksum 0a108c035194f620555926cf7d113c8b
? ?Compiled from "TestCode.java"
?public class com.code.baseCode.TestCode
? ?minor version: 0
? ?major version: 52
? ?flags: ACC_PUBLIC, ACC_SUPER
?Constant pool:
? ? #1 = Methodref ? ? ? ? ?#5.#21 ? ? ? ? // java/lang/Object."<init>":()V
? ? #2 = String ? ? ? ? ? ? #22 ? ? ? ? ? ?// bbbb
? ? #3 = String ? ? ? ? ? ? #23 ? ? ? ? ? ?// cccc
? ? #4 = Class ? ? ? ? ? ? ?#24 ? ? ? ? ? ?// com/code/baseCode/TestCode
? ? #5 = Class ? ? ? ? ? ? ?#25 ? ? ? ? ? ?// java/lang/Object
? ? #6 = Utf8 ? ? ? ? ? ? ? <init>
? ? #7 = Utf8 ? ? ? ? ? ? ? ()V
? ? #8 = Utf8 ? ? ? ? ? ? ? Code
? ? #9 = Utf8 ? ? ? ? ? ? ? LineNumberTable
? ?#10 = Utf8 ? ? ? ? ? ? ? LocalVariableTable
? ?#11 = Utf8 ? ? ? ? ? ? ? this
? ?#12 = Utf8 ? ? ? ? ? ? ? Lcom/code/baseCode/TestCode;
? ?#13 = Utf8 ? ? ? ? ? ? ? main
? ?#14 = Utf8 ? ? ? ? ? ? ? ([Ljava/lang/String;)V
? ?#15 = Utf8 ? ? ? ? ? ? ? args
? ?#16 = Utf8 ? ? ? ? ? ? ? [Ljava/lang/String;
? ?#17 = Utf8 ? ? ? ? ? ? ? aaaa
? ?#18 = Utf8 ? ? ? ? ? ? ? Ljava/lang/String;
? ?#19 = Utf8 ? ? ? ? ? ? ? SourceFile
? ?#20 = Utf8 ? ? ? ? ? ? ? TestCode.java
? ?#21 = NameAndType ? ? ? ?#6:#7 ? ? ? ? ?// "<init>":()V
? ?#22 = Utf8 ? ? ? ? ? ? ? bbbb
? ?#23 = Utf8 ? ? ? ? ? ? ? cccc
? ?#24 = Utf8 ? ? ? ? ? ? ? com/code/baseCode/TestCode
? ?#25 = Utf8 ? ? ? ? ? ? ? java/lang/Object
?{
? ?public com.code.baseCode.TestCode();
? ? ?descriptor: ()V
? ? ?flags: ACC_PUBLIC
? ? ?Code:
? ? ? ?stack=1, locals=1, args_size=1
? ? ? ? ? 0: aload_0
? ? ? ? ? 1: invokespecial #1 ? ? ? ? ? ? ? ? ?// Method java/lang/Object."<init>":()V
? ? ? ? ? 4: return
? ? ? ?LineNumberTable:
? ? ? ? ?line 8: 0
? ? ? ?LocalVariableTable:
? ? ? ? ?Start ?Length ?Slot ?Name ? Signature
? ? ? ? ? ? ?0 ? ? ? 5 ? ? 0 ?this ? Lcom/code/baseCode/TestCode;
??
? ?public static void main(java.lang.String[]);
? ? ?descriptor: ([Ljava/lang/String;)V
? ? ?flags: ACC_PUBLIC, ACC_STATIC
? ? ?Code:
? ? ? ?stack=1, locals=2, args_size=1
? ? ? ? ? 0: ldc ? ? ? ? ? #2 ? ? ? ? ? ? ? ? ?// String bbbb
? ? ? ? ? 2: astore_1
? ? ? ? ? 3: ldc ? ? ? ? ? #3 ? ? ? ? ? ? ? ? ?// String cccc
? ? ? ? ? 5: astore_1
? ? ? ? ? 6: return
? ? ? ?LineNumberTable:
? ? ? ? ?line 11: 0
? ? ? ? ?line 12: 3
? ? ? ? ?line 55: 6
? ? ? ?LocalVariableTable:
? ? ? ? ?Start ?Length ?Slot ?Name ? Signature
? ? ? ? ? ? ?0 ? ? ? 7 ? ? 0 ?args ? [Ljava/lang/String;
? ? ? ? ? ? ?3 ? ? ? 4 ? ? 1 ?aaaa ? Ljava/lang/String;
?}
?SourceFile: "TestCode.java"

反编译后,会发现aaaa存在于Constant pool(常量池)和LocalVariableTable(本地变量表)中

同时发现和int a = 1的区别在于字符串“bbbb”和“cccc”也会在常量池中

JVM中常量池的划分,请看上篇文章

图片解释

java1.8的内存布局

image-20211122224530763

在编译后内存情况

image-20211123212545822

运行时发生情况

如何查看Java bytecode指令?

https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions

Jvm系列3—字节码指令 - Gityuan博客 | 袁辉辉的技术博客

其中java byte code为

?0: ldc ? ? ? ? ? #2 ? ? ? ? ? ? ? ? ?// String bbbb
?2: astore_1
?3: ldc ? ? ? ? ? #3 ? ? ? ? ? ? ? ? ?// String cccc
?5: astore_1

ldc:push a constant #index from a constant pool (String, int, float, Class, java.lang.invoke.MethodType, java.lang.invoke.MethodHandle, or a dynamically-computed constant) onto the stack

意思就是:int、float或String型等常量从常量池推送至栈顶

astore_1:store a reference into local variable 1

意思就是将:一个引用放入到局部变量1中(也就是aaaa中)

ldc #2

image-20211123213852082

astore_1

image-20211123214132207

ldc #3

image-20211123214251552

astore_1

image-20211123214346740

图片解释:用new String()创建

将代码改成如下:

?public class TestCode {
? ?  public static void main(String[] args) {
? ? ? ?  String aaaa = new String("bbbb");
? ? ? ?  aaaa = new String("cccc");
? ?  }
?}

则会发现常量池多了一些东西,并且执行指令多了。

其中执行指令如下

?0: new ? ? ? ? ? #2 ? ? ? ? ? ? ? ? ?// class java/lang/String
?3: dup
?4: ldc ? ? ? ? ? #3 ? ? ? ? ? ? ? ? ?// String bbbb
?6: invokespecial #4 ? ? ? ? ? ? ? ? ?// Method java/lang/String."<init>":(Ljava/lang/String;)V
?9: astore_1
?10: new ? ? ? ? ? #2 ? ? ? ? ? ? ? ? ?// class java/lang/String
?13: dup
?14: ldc ? ? ? ? ? #5 ? ? ? ? ? ? ? ? ?// String cccc
?16: invokespecial #4 ? ? ? ? ? ? ? ? ?// Method java/lang/String."<init>":(Ljava/lang/String;)V
?19: astore_1

new:创建类实例

dup:复制数值,并压入栈顶

ldc:从常量池推送至栈顶

invokespecial:调用特殊实例方法(包括实例初始化方法、父类方法)

astore_1:一个引用放入到局部变量1中(也就是aaaa中)

常量池如下

?Constant pool:
? ? #1 = Methodref ? ? ? ? ?#7.#23 ? ? ? ? // java/lang/Object."<init>":()V
? ? #2 = Class ? ? ? ? ? ? ?#24 ? ? ? ? ? ?// java/lang/String
? ? #3 = String ? ? ? ? ? ? #25 ? ? ? ? ? ?// bbbb
? ? #4 = Methodref ? ? ? ? ?#2.#26 ? ? ? ? // java/lang/String."<init>":(Ljava/lang/String;)V
? ? #5 = String ? ? ? ? ? ? #27 ? ? ? ? ? ?// cccc
? ? #6 = Class ? ? ? ? ? ? ?#28 ? ? ? ? ? ?// com/code/baseCode/TestCode
? ? #7 = Class ? ? ? ? ? ? ?#29 ? ? ? ? ? ?// java/lang/Object
? ? #8 = Utf8 ? ? ? ? ? ? ? <init>
? ? #9 = Utf8 ? ? ? ? ? ? ? ()V
? ?#10 = Utf8 ? ? ? ? ? ? ? Code
? ?#11 = Utf8 ? ? ? ? ? ? ? LineNumberTable
? ?#12 = Utf8 ? ? ? ? ? ? ? LocalVariableTable
? ?#13 = Utf8 ? ? ? ? ? ? ? this
? ?#14 = Utf8 ? ? ? ? ? ? ? Lcom/code/baseCode/TestCode;
? ?#15 = Utf8 ? ? ? ? ? ? ? main
? ?#16 = Utf8 ? ? ? ? ? ? ? ([Ljava/lang/String;)V
? ?#17 = Utf8 ? ? ? ? ? ? ? args
? ?#18 = Utf8 ? ? ? ? ? ? ? [Ljava/lang/String;
? ?#19 = Utf8 ? ? ? ? ? ? ? aaaa
? ?#20 = Utf8 ? ? ? ? ? ? ? Ljava/lang/String;
? ?#21 = Utf8 ? ? ? ? ? ? ? SourceFile
? ?#22 = Utf8 ? ? ? ? ? ? ? TestCode.java
? ?#23 = NameAndType ? ? ? ?#8:#9 ? ? ? ? ?// "<init>":()V
? ?#24 = Utf8 ? ? ? ? ? ? ? java/lang/String
? ?#25 = Utf8 ? ? ? ? ? ? ? bbbb
? ?#26 = NameAndType ? ? ? ?#8:#30 ? ? ? ? // "<init>":(Ljava/lang/String;)V
? ?#27 = Utf8 ? ? ? ? ? ? ? cccc
? ?#28 = Utf8 ? ? ? ? ? ? ? com/code/baseCode/TestCode
? ?#29 = Utf8 ? ? ? ? ? ? ? java/lang/Object
? ?#30 = Utf8 ? ? ? ? ? ? ? (Ljava/lang/String;)V

new #2

image-20211123223808106

dup

image-20211123223942761

ldc #3

image-20211123224047739

invokespecial #4

image-20211123224141928

astore_1

image-20211123224232319

后续的操作一样,因此会出现

?String a = new String("bbbb");
?String b = new String("bbbb");
?System.out.println(a == b); // false

面试题

做下面的题是,需要知道几个知识点

1.编辑时,编译器会对确切的值进行优化:

比如String a = "a" + "b"; -> 比如String a = "ab";

final String a = "a"; String b = "a" + a; -> String b = "aa";

2.字符串变量相加会创建StringBuilder调用append方法,然后StringBuilder转换成new String

3.intern:Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用。

?String s11 = "a";
?String s22 = "bc";
??
?String s1 = "abc";
?String s2 = "a" + "bc";
?String s3 = new String("a") + "bc";
?String s4 = new String("a") + new String("bc");
?String s5 = new String("abc");
?String s6 = s11 + s22;
??
?System.out.println(s1 == s2);
?System.out.println(s1 == s3);
?System.out.println(s1 == s4);
?System.out.println(s1 == s5);
?System.out.println(s1 == s6);
?System.out.println(s3 == s4);
?System.out.println(s4 == s5);
??
?System.out.println(s1 == s5.intern());
?System.out.println(s1 == s6.intern());
??
?System.out.println(s1.equals(s5));
?System.out.println(s1.equals(s6));

答案解释:[java面试题]判断字符串相等,看这一篇就够了 - 知乎

结尾

之前出了int类型的情况,上述是String类型的情况,后续出包装类型的情况

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-27 09:46:50  更:2021-11-27 09:46:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:39:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码