Java 中字符串的内存分配
内容提要
Java中,字符串以String类的对象形式存储在内存中,内存分为堆栈和堆两部分。堆内存中有字符串常量池,用于存储唯一的字符串字面量。堆栈内存中存储变量和对象引用。创建字符串对象有两种方式:字符串字面量和使用new关键字。通过“==”运算符比较物理地址,通过equals函数比较内容。使用字符串字面量节省内存空间,但常量池大小有限。使用new关键字创建对象可以释放不需要的对象,但会增加JVM负担。
延伸解读
字符串常量池的容量限制
字符串常量池是堆内存中的固定大小区域,用于存储唯一的字符串字面量。由于大小固定,当大量不同的字面量被创建时,常量池可能被填满,导致后续字面量无法存入,可能引发性能问题或内存错误。因此,在需要大量动态字符串时,应谨慎使用字面量方式。
new关键字创建字符串的双重开销
使用new关键字创建字符串时,JVM会在堆和常量池中各创建一个对象(如果常量池中不存在该字面量)。这虽然允许对象在不再使用时被垃圾回收器回收,但每次new都会产生新对象,增加JVM的分配和垃圾回收负担。在频繁创建字符串的场景下,可能影响性能。
==与equals的选择依据
==运算符比较的是对象的内存地址,而equals方法比较的是字符串的内容。因此,当需要判断两个字符串是否指向同一对象时使用==,而判断内容是否相同时应使用equals。例如,字面量创建的相同字符串在常量池中共享同一对象,==返回true;而new创建的字符串即使内容相同,==也返回false。
字符串赋值的引用传递
当将一个字符串变量赋值给另一个变量时,如str6 = str4,两个变量将指向堆中的同一个对象。此时,通过==比较会返回true,因为地址相同。修改其中一个变量指向新对象不会影响另一个变量,但若对象本身不可变,则无需担心内容被意外修改。
Q&A
Java中字符串是如何存储的?
Java中的字符串以String类的对象形式存储在内存中,分为堆栈和堆两部分。
什么是字符串常量池,它的作用是什么?
字符串常量池是堆内存中的一个区域,用于存储唯一的字符串字面量,帮助节省内存空间。
在Java中如何创建字符串对象?
可以通过字符串字面量或使用new关键字来创建字符串对象。
使用'=='和equals函数比较字符串有什么区别?
'=='运算符比较字符串对象的物理地址,而equals函数比较字符串的内容。
使用字符串字面量和new关键字创建字符串的优缺点是什么?
使用字符串字面量节省内存,但常量池大小有限;使用new关键字会创建两个对象,增加JVM负担。
如果字符串常量池满了会发生什么?
如果字符串常量池满了,无法再创建新的字符串字面量,可能导致内存问题。