首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >字符串概念中的混淆

字符串概念中的混淆
EN

Stack Overflow用户
提问于 2013-07-01 02:02:14
回答 4查看 163关注 0票数 0
代码语言:javascript
运行
复制
class StringTest1
{
public static final void main(String... a)
{
    String str1="JAVA";
    String str2="WORLD";

    String str3=str1+str2;
}
}

在此过程中将创建多少个对象?我想会创建3个对象。

代码语言:javascript
运行
复制
class StringTest2
{
public static final void main(String... a)
{

    String strTest="JAVA"+"WORLD";
}
}

在这个过程中会创建多少个对象?有多少对象是可访问的?有人告诉我"JAVA"+"WORLD“是一个表达式,它不会存储在字符串池中。

EN

回答 4

Stack Overflow用户

发布于 2013-07-01 02:16:49

在第一个示例中,您将得到三个String对象。您实际上可以在字节码中看到这一点。

假设您有以下代码:

代码语言:javascript
运行
复制
public class StrTest {
    public static void main(String[] args) {
        String str1 = "JAVA";
        String str2 = "WORLD";

        String str3 = str1 + str2;

        String strTest = "JAVA" + "WORLD";
    }
}

得到的字节码是:

代码语言:javascript
运行
复制
public class StrTest {
  public StrTest();
    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 JAVA
       2: astore_1      
       3: ldc           #3                  // String WORLD
       5: astore_2      
       6: new           #4                  // class java/lang/StringBuilder
       9: dup           
      10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
      13: aload_1       
      14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      17: aload_2       
      18: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      24: astore_3      
      25: ldc           #8                  // String JAVAWORLD
      27: astore        4
      29: return        
}

您可以看到,Java编译器已经在字符串池中为"JAVA""WORLD"创建了两个String实例。为了将这两者附加在一起,它创建了一个StringBuilder实例并附加了这些值。之后,它在该实例上调用toString(),这将创建一个内部包含"JAVAWORLD"的新String实例。

在第二种情况下,您最终只有一个String实例,因为Java编译器足够智能,能够看到您基本上拥有的是一个常量,因此它通过计算该表达式并在包含"JAVAWORLD"的字符串池中创建 one String实例来执行一些编译时优化。然后将对该实例的引用分配给strTest

关于字符串"JAVA""WORLD""JAVAWORLD",这些基本上都是被套住的字符串。因为字符串在Java中是不可变的,所以您只需要一个对唯一实例的引用,该实例可以在代码中的多个位置重用。这基本上是一种节省内存的方法。

所以总结一下:

  • 案例1:三个String实例:两个在池中,一个是在追加后新建的(还创建了一个StringBuilder实例来追加两个字符串,导致总共4个对象)。
  • 案例2:池中一个实例。
票数 5
EN

Stack Overflow用户

发布于 2013-07-01 02:17:47

代码语言:javascript
运行
复制
String str1="JAVA";
String str2="WORLD";

String strTest="JAVA"+"WORLD";

这三行中的每一行都将创建一个String对象。但是,如果代码被多次生成,那么它将始终是同一个对象。此外,每个String对象将包含一个char[]对象,因此从技术上讲,它是每行2个对象。

代码语言:javascript
运行
复制
String str3=str1+str2;

假设javac不能对此进行优化,它将编译为

代码语言:javascript
运行
复制
String str3 = new StringBuilder(str1).append(str2).toString();

因此,它不仅会创建一个字符串,还会创建一个在代码中无法访问的StringBuilder。因此,在最坏的情况下,会创建4个对象: String、StringBuilder和to char数组(因为它必须在append期间调整大小)

票数 1
EN

Stack Overflow用户

发布于 2013-07-01 02:09:37

在第一种情况下,编译器不能确定str1str2将具有什么值,因此它不是常量表达式,因此将在运行时计算它。将有三个对象(两个来自字符串文字,一个创建为字符串的串联)。

在第二种情况下,编译器能够计算结果,因此将只有一个对象,就像您编写"JAVAWORLD"一样

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17393271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档