Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 字符串对象和堆_Java_String_Object_Heap - Fatal编程技术网

Java 字符串对象和堆

Java 字符串对象和堆,java,string,object,heap,Java,String,Object,Heap,我正在为SCJP考试学习,我有一套我正在研究的问题样本 一个问题的答案我不确定,希望这里有人能帮我把这个问题解决 问题是 鉴于: 11. public String makinStrings() { 12. String s = "Fred"; 13. s = s + "47"; 14. s = s.substring(2, 5); 15. s = s.toUpperCase(); 16. return s.toString(); 17. } 调用此方法时将创建多

我正在为SCJP考试学习,我有一套我正在研究的问题样本

一个问题的答案我不确定,希望这里有人能帮我把这个问题解决

问题是

鉴于:

11. public String makinStrings() {
12.    String s = "Fred";
13.    s = s + "47";
14.    s = s.substring(2, 5);
15.    s = s.toUpperCase();
16.    return s.toString();
17. }
调用此方法时将创建多少字符串对象

A. 1
B. 2
C. 3
D. 4
E. 5
F. 6
提前感谢您提供的任何帮助。
我非常感激。

我想说3:第12行、第13行和第15行的那些


第14行(子字符串)没有创建新对象的原因是字符串的内部工作方式。由于对子字符串进行了必要的优化(包括编译器在内的所有内容都依赖于子字符串),String类有两个指向字符串开头和结尾的指针。执行子字符串只会移动此指针,而不会将对象“复制”到新指针中。

让我们逐行查看它

第11行

一个简单的开始,这里没有创建字符串

第12行

我们正在将字符串
“Fred”
分配给
s
。虽然看起来这里创建了一个字符串,但该字符串将存在于常量池中。该部分保证字符串文本的对象最迟将在加载周围类时创建,根据定义,这是在调用该方法之前。因此,不会在此行上创建新的字符串对象

第13行

引用了文本字符串
“47”
,该字符串将再次静态创建(如上所述)。然而,还有
+
操作符的调用,它将创建一个新字符串以保存连接的结果。这是创建的第一个字符串

第14行

substring
方法确实创建了一个新字符串。它与其父级共享底层字符数组,因此几乎不占用任何额外内存,但由于字符串是不可变的,每个不同的字符串表示都需要不同的
string
对象。(这可能是一个问题-我的第一个本能反应是“啊,子字符串创建的字符串是特殊的”,但当然它仍然需要创建一个新对象)

第15行

如上所述-大写表示不同,因此必须创建一个新字符串来保存结果

第16行

Strings
重写
toString()
方法以简单地
返回该字符串
——因此不会创建额外的字符串

门上的分数


根据我的统计,这是在这个方法中创建的三个字符串对象(其中两个对象共享相同的底层字符数组,并且字符串文本引用了两个预先存在的对象)。

实际上,可以将整个方法变成一个常量。这是可能的,但编译器不允许这样做。因此,使用常量池中的2创建了3个字符串

  • 弗雷德47
  • ed4(注意:使用与Fred47相同的支持字符[])
  • ED4
2和3非常简单,因为不允许编译器优化此方法调用,但字符串已更改。Sting.toString()只返回
这个
,因此也没有新字符串。但是让我们看看第13行中使用的反汇编字节码(
javap-c
是您的朋友):

public java.lang.String makinStrings();
代码:
0:ldc#16//串弗雷德
2:astore_1
3:新#18//类java/lang/StringBuilder
6:dup
7:aload_1
8:invokestatic#20//方法java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
11:特别是#26//方法java/lang/StringBuilder。“”:(Ljava/lang/String;)V
14:最不发达国家29//串47
16:invokevirtual#31//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19:invokevirtual#35//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
//剪断
}
如您所见,“Fred”和“47”从常量池(
ldc
)加载,以填充最终将成为字符串的StringBuilder(StringBuilder.toString())


这样,每个方法调用就可以生成2个常量字符串加上3个新创建的字符串。

它将创建字符串的5个对象

字符串是不可变的类,所以对于每个新字符串,它都将创建一个对象

范例

  • 公共字符串makinStrings(){
  • 字符串s=“Fred”;(此行创建1---Fred字符串)
  • s=s+“47”;(此行创建2-47字符串+3-47)
  • s=s.substring(2,5);(此行创建4-ed4)
  • s=s.toUpperCase();(此行创建5-ED4)
  • 返回s.toString()

  • 因此,根据我的说法,它将创建5个对象

    链接问题的可能重复项,甚至包含完全相同的示例。没错,我同意这是完全重复的。尽管
    String.toUpperCase()
    很棘手-新的
    字符串
    对象只有在有任何字符需要更改的情况下才会创建。从阅读此响应中,3确实是答案,但在第13、14和15行。感谢您的响应:)@JarekPrzygódzki我也这么认为-子字符串不会更改字符,但toUpperCase会更改字符(无论如何,在本例中)@Guillaume我不同意你的推理。我只同意最终结果是正确的..子字符串(..)确实创建了字符串的新实例(特例
    s.substring(0,s.length())
    是唯一返回
    this
    )的实例。但它使用相同的字符[]。包私有构造函数
    String(int offset,int count,char[]value)
    用于此特殊目的。注意:所有使用char[]的公共可见构造函数都将制作一个副本。此答案重申了此答案,因此感谢您的澄清。这是一个很好的答案,包括反汇编
    public java.lang.String makinStrings();
      Code:
       0:   ldc #16; //String Fred
       2:   astore_1
       3:   new #18; //class java/lang/StringBuilder
       6:   dup
       7:   aload_1
       8:   invokestatic    #20; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
       11:  invokespecial   #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
       14:  ldc #29; //String 47
       16:  invokevirtual   #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       19:  invokevirtual   #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
           // SNIP
    }