| |
|
开发:
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 #2dupldc #3invokespecial #4astore_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图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 3:39:57- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |