如图,s3,s4,s5都是不同的内存地址且s3在字符串常量池我可以理解
想请问一下,那s4 和 s5 是怎么在内存中储存的呢?
或者说,执行到第4,5行的时候 内存中是怎么样的一个过程呢?
s4=s1+"world";因为右侧表达式s1不是常量,所以s4不会从常量池中查找是否有这个字符,而是重新申请一块空间来存储相加的结果;同理,s5也是一个道理。
我们先来说说基本数据类型:
在Java中有boolean,byte short int long double float short,然后
string不属于基本数据类型,这个时候就出现了怎么存数据的问题。
string,你定义了一个字符串那他就会把字符串存在常量池中。
也就是说
你定义的s1,s2,的hello world是在字符串常量池中,s1,s2在栈中存的都是指向常量池的地址
而s3执行时候,虽然是+但是在jvm的优化下,会采用先stringbuilder的方式进行字符串想加,然后toString形成新的字符串在堆中存起来,这个时候s3,在栈中存的地址就指向helloworld,
之后你的你的s4=s1+world,虽然s1是hello,但是他在栈中存的事地址,他需要先去找到地址,然后再去地址中找到值之后想加,想加之后形成的值,又存在一个新的地方。
而s5也是同样,他是先找到s1s2中的地址,然后去内存中找对应的值,然后去堆中继续存储起来
然后你还要明白一点是
==比较的是内存地址,而字符串比较值使用equars
你还要明白的第一地方
s1,s2,是存在字符串常量池中,是常量
s3 s4 s5是直接存在堆中是个对象
所以这个时候当你s3/s4/s5,无论怎么比较都是false
(手机打的不容易,排版差了点,听懂了满意了给个采纳吧)
0 ldc #7 <hello>
2 astore_1
3 ldc #9 <world>
5 astore_2
6 ldc #11 <helloworld>
8 astore_3
9 new #13 <java/lang/StringBuilder>
12 dup
13 invokespecial #15 <java/lang/StringBuilder.<init> : ()V>
16 aload_1
17 invokevirtual #16 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
20 ldc #9 <world>
22 invokevirtual #16 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
25 invokevirtual #20 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
28 astore 4
30 new #13 <java/lang/StringBuilder>
33 dup
34 invokespecial #15 <java/lang/StringBuilder.<init> : ()V>
37 aload_1
38 invokevirtual #16 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
41 aload_2
42 invokevirtual #16 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
45 invokevirtual #20 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
48 astore 5
上面是用 javap -c -v
查看你写的代码对应的字节码,可以看出 s3
在编译时被 javac
写入常量池了,而 s4
和 s5
都是由 StringBuilder
的 toString
方法得到的。所以结论是:s1
s2
s3
在常量池;s4
s5
是在堆里的。