我对于不可变对象的内存管理存在概念上的疑问,例如java和其他语言中的String对象.例如,如果我有一个String对象“str”,其值为“Hello”,我会执行以下操作:
String str = "Hello";
str = str.concatenate("World");
在这种情况下,据我所知,创建了一个状态为“Hello World”的新String对象,并将其引用回str.现在,在Java(以及大多数其他面向对象的语言)中,任何对象的生命周期都与其引用一样长.那么持有“你好”的对象去哪里了.它是否驻留在内存堆中,直到垃圾收集器自行处理它?另外,那些不支持垃圾收集器并且必须依赖于类析构函数的语言呢?
此外,如果可变对象(如StringBuffer和StringBuilder)更灵活且性能更友好,为什么在设计语言时首先使对象成为不可变的? (我的意思是为什么String Objects从一开始就不可变,而不必在后续的JDK版本中引入新的结构,如String Buffers?).
如果有人可以指导我这将是很好的.我是新手,所以一个明确的,基本的解释将受到高度赞赏.谢谢.
解决方法:
这实际上是一个关于java String类的问题 – 一般来说不是不变量.当Java首次引入时,设计人员决定使String特殊 – 在某些方面它位于引用类型和基本类型之间.
我们使用String获得的优势是虚拟机保留了一个公共的字符串文字池,阻止了堆填充 – 请参阅here以获取描述.这背后的原因是程序的大部分内存可以用于存储常用的字符串.另见String.intern.
对于任何其他类型的不可变对象,情况并非如此(遗憾的是).关于str去哪里的问题已由其他人回答 – 它遵循我确定你知道的(或可以找到)正常的垃圾收集规则.
也许你问题中最有趣的部分是
Also, if mutable objects such as StringBuffer/StringBuilder are much
more flexible and performance friendly, why make objects mutable in
the first place, while designing the language?? (I mean why aren’t
String Objects mutable right from the beginning instead of having to
introduce new structures such as String Buffers in subsequent jdk
releases?).
我的答案是,常见的情况是我们有很多相同的字符串,我们希望针对常见情况进行优化.另请注意,Java编译器在连接字符串时使用StringBuilder.例如,使用此代码
public class StringBuilderTest {
public static void main(String [] args){
String hello = "hello ";
String world = "world";
System.out.println(hello+world);
}
}
并使用它拆卸它
javap -c StringBuilderTest
并获取main方法的以下字节码
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String hello
2: astore_1
3: ldc #3 // String world
5: astore_2
6: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
9: new #5 // class java/lang/StringBuilder
12: dup
13: invokespecial #6 // Method java/lang/StringBuilder."":()V
16: aload_1
17: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: aload_2
21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: return
}
它使用StringBuilder来执行追加.
标签:java,memory-management,immutability
来源: https://codeday.me/bug/20190723/1509484.html