Java中的字符串初始化

8
  1. String str1;
  2. String str2 = null;
  3. String str3 = "";
  4. String str4 = new String();
  5. String str5 = new String("");

我知道上面第三个初始化的字符串对象是在字符串池中初始化的,而第四个则与字符串池无关。

1.和2.之间有什么区别?如果将str1视为指针变量,则它存储的是JVM或操作系统从未使用过的特定内存地址吗?

4.和5.有区别吗?

当我通过System.out.println(str1)System.out.println(str2)直接打印str1str2时,对于str1,我甚至不能通过编译。对于str2,编译是可以的,而且我得到了"null"和控制台窗口中的输出。为什么?

在@aioobe的回答之后进行编辑:更多问题:

我想更多地了解"null"。由于str2(引用变量)就像一个指针变量,因此它内部应该有一些(0/1位)东西(在这个指针变量所占用的内存中)。由于它被初始化为null,它是全0位还是null的字节码是全零?另一个问题是,如果我通过str2.toString()调用toString()方法,我会在运行时得到一个NullPointer错误。那么JVM是检查引用变量是否为null吗?JVM如何知道它是null的?JVM检查str2中的位吗?

关于Java中的null还有一个问题:连接null和字符串文字


我更新了我的回答,针对你的编辑做出了响应。 - aioobe
有没有投反对票的人能给出一些理由?我想不通为什么... - Gab是好人
我认为人们认为这个问题以前已经被问过了。你的问题中的部分曾经被问过,而部分则没有。 - aioobe
2个回答

17
如果我把str1视为指针变量,它存储的是一个从未被JVM或OS使用的特定内存地址,那么1和2有什么区别?
如果这些是一个类中的字段,那么没有区别,因为引用类型(如String)字段的默认值已经是null
如果这些是方法中声明的局部变量,str1将不会被初始化为任何值,而str2将被初始化为null。区别在于局部变量在初始化之前不能使用,所以你无法打印str1,但可以打印str2
4和5有区别吗?
不,从语义上讲没有区别,但生成的字节码略有不同。
当我通过System.out.println(str1)和System.out.println(str2)直接打印str1和str2时,对于str1,我甚至无法通过编译。对于str2,编译是可以的,并且我得到了“null”和控制台窗口中的输出。为什么?
这似乎表明这些是局部变量。局部变量在使用之前需要初始化。
我想了解更多关于“null”的信息。由于str2(引用变量)就像一个指针变量,因此它应该在其中有一些(0/1位)(在该指针变量所占用的内存中)。由于它被初始化为null,它是全部为0位还是字节码为null的全部为零?
这已经被问过(并回答)了:
- Java中的null在内存中如何表示 - null在Java内存中究竟是什么 另一个问题是,如果我通过str2.toString()调用toString()方法,运行时会得到一个NullPointer错误。因此,是JVM检查引用变量是否为null吗?
是的。
JVM如何知道它是null?JVM检查str2中的位吗?
是的。

这个问题已经太大了(答案也是如此!)。您可以把最后一个作为新问题剪切/粘贴吗?我保证尽力回答...(在评论区发一个链接)。 - aioobe

1

Java 中表示对象的每个变量实际上不是一个值,而是指向内存中存储该变量的某个位置的指针。 null 是一种特殊类型的指针,表示该变量(指针)已初始化,但指向空地址。 由于任何两个字符串变量都是指针,如果您像这样比较它们str1 == str2,则将检查变量是否指向同一实例。要比较指针所指向的内容,您需要使用equals:str1.equals(str2),但在这种情况下,我们必须确保 str1 不是 null


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接