Java 字符串常量池、新对象初始化(使用新关键字)与字符串的正常初始化?

Java 字符串常量池、新对象初始化(使用新关键字)与字符串的正常初始化?,java,string,Java,String,在s1中,将创建两个对象,一个在字符串池中,另一个在非池内存中 在s2中,字符串池中将只创建一个对象 如果我们这样做: String s1 = new String("abc"); String s2 = "abc"; 现在字符串池中有3个对象(“abc”,“def”,和“abcdef”),其中两个被放弃(“def”和“abcdef”),将“abc”留在内存中 两个引用都引用了字符串池对象 记忆对象的意义是什么?和s2.concat(“def”)发生在运行时,它们不会成为常量池的一部分,而是进

s1
中,将创建两个对象,一个在字符串池中,另一个在非池内存中

s2
中,字符串池中将只创建一个对象

如果我们这样做:

String s1 = new String("abc");
String s2 = "abc";
现在字符串池中有3个对象(
“abc”
“def”
,和
“abcdef”
),其中两个被放弃(
“def”
“abcdef”
),将
“abc”
留在内存中

两个引用都引用了字符串池对象

记忆对象的意义是什么?

s2.concat(“def”)发生在运行时,它们不会成为常量池的一部分,而是进入堆

注意
concat
的签名:

s1.concat("def");
s2.concat("def");
它返回一个新字符串,并且您没有将该字符串分配给任何变量

记忆对象的意义是什么

不清楚您在问什么,但请注意,由于未分配由
concat
创建的字符串(对它的引用将被丢弃),因此它有资格进行垃圾收集

s2
中,字符串池中将只创建一个对象

实际上不,这条线不会创建新对象
s2
将引用用于构造
s1
的同一常数

现在字符串池中有3个对象(
“abc”
“def”
,和
“abcdef”
),其中两个被放弃(
“def”
“abcdef”
),将
“abc”
留在内存中

不,只有
“abc”
“def”
在常量池中,由于它们是常量,因此在程序运行期间将保留在内存中<代码>“abcdef”
在构建后将立即被垃圾收集,因为它从未存储在任何地方

如果您使用了
+
操作符而不是
String.concat()
,编译器实际上会将两个常量字符串合并为一个,并且只将结果字符串存储在池中

两个引用都引用了字符串池对象

否,只有
s2
引用常量池中的字符串,并且
.concat()
的结果都不会在常量池中

记忆对象的意义是什么

您是否在问字符串常量池的意义是什么?它本质上只是一种允许常量的优化(例如,
-ed字符串在代码中)共享同一引用以避免构造多个相同的实例。因为它们是常量,所以可以在编译时执行此操作,从而在运行时节省空间和时间。除非显式调用,否则这不适用于在运行时构造的任何字符串,但通常应这样做

您也可能对以下内容感兴趣:


编辑:由于您坚持您的示例中的
“abcdef”
将是常量池的一部分,这里有一个简单的证据证明情况并非如此:

public String concat(String str)
$javac-version
JavaC1.7.0_02
$cat Test.java
公开课考试{
公共静态void main(字符串[]args){
字符串s1=“123”+“456”;
字符串s2=“abc”。concat(“def”);
}
}
$javac Test.java
$javap-c-classpath.Test
从“Test.java”编译而来
公开课考试{
公开考试();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
公共静态void main(java.lang.String[]);
代码:
0:ldc#2//字符串123456
2:astore_1
3:ldc#3//字符串abc
5:ldc#4//字符串定义
7:invokevirtual#5//方法java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
10:astore_2
11:返回
}

您可以清楚地看到,字符串
123456
abc
def
都是常量(请参阅),并且
String.concat()
在运行时被调用。

您认为“内存对象的意义是什么?”?为什么您认为“abcdef”会出现在字符串池中?还有,“abcdef”将成为垃圾收集的候选对象,因为您没有将concat()的结果分配给任何变量。concat()不修改字符串。它创造了一个新的世界。@PurvenderHooda你似乎确信你比这里的每个人都了解。那你为什么要问?不,s1.concat(“def”)的结果不会进入字符串池。我不明白你在问我什么。@PurvenderHooda-我不是说字符串literal
“abcdef”
。我说的是由
s1.concat(“def”)
生成的字符串
abcdef
。我向您保证,它不会进入字符串常量池。它们将是字符串常量池的一部分。我们没有赋值,问题是对象的总数以及它们在哪个内存中的位置。请注意,在给定的上下文中,
abc
def
123456
是类常量,而不是字符串常量池的常量。i、 e,类常数!=字符串常量池(不总是)
$ javac -version
javac 1.7.0_02

$ cat Test.java
public class Test {
  public static void main(String[] args) {
    String s1 = "123" + "456";
    String s2 = "abc".concat("def");
  }
}

$ javac Test.java

$ javap -c -classpath . Test
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String 123456
       2: astore_1
       3: ldc           #3                  // String abc
       5: ldc           #4                  // String def
       7: invokevirtual #5                  // Method java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
      10: astore_2
      11: return
}