| |
|
|
开发:
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的内存布局
在编译后内存情况
运行时发生情况如何查看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
astore_1
ldc #3
astore_1
图片解释:用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
dup
ldc #3
invokespecial #4
astore_1
后续的操作一样,因此会出现 ?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类型的情况,后续出包装类型的情况 |
|
|
|
|
| 上一篇文章 下一篇文章 查看所有文章 |
|
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
| 360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年12日历 | -2025/12/3 2:09:47- |
|
| 网站联系: qq:121756557 email:121756557@qq.com IT数码 |