Skip to content

Java 中的字符串

ZhangPan edited this page Jul 3, 2025 · 4 revisions

1.下面的代码在JVM中生成了几个String对象?JVM是如何对其进行内存分配的?

String s1 = new String("abc")

对于这一问题应该分情况讨论,因为虚拟机在JDK7之前与之后对于字符串常量池的实现是不一样的。

(1)JDK7之前 对于String类型的数据,JVM维护了一个字符串常量池来存放字符串对象。JDK7之前,字符串常量池位于方法区(永久代)。上述代码中如果常量池中还没有”abc"对象,则会首先在字符常量池中生成一个”abc"对象,如果“abc"已经存在于字符串常量池,则不会再次生成。注意这个字符串对象是位于永久代而非堆内存。接着,在执行new的时候在堆内存中再生成一个“abc"对象,并将这个对象的引用赋值给了s1。因此上述代码可能生成两个String对象,也可能生成一个。如下图: 在这里插入图片描述

而在JDK7之后,由于常量池被移到了堆内存,并且常量池中不再存放字符对象,而是存放字符串的引用。 那么上述代码中则首先会在堆内存中生成一个“abc"对象,并将这个对象的引用会放入常量池。接着,在执行new时,会再次在堆中生成一个”abc"对象,并将这个对象引用赋值给s1。如下图:

在这里插入图片描述

因此,无论是在JDK7之前还是之后,这一代码都会生成一个或者两个字符串对象,只是内存的分配会有所区别。

可参考:Java进阶--深入理解Java中的字符串(一)

2.了解String的intern()方法吗?它有什么作用?

当调用intern方法的时候,如果字符串常量池中已经包含了一个等于该String对象的字符串,则直接返回字符串常量池中该字符串的引用。否则,会将该字符串对象包含的字符串添加到常量池,并返回此对象的引用。

详情可参考:Java进阶--深入理解Java中的字符串(一)

3.String、StringBuffer与StringBuilder有区别?

(1)String 类被final修饰,同时内部维护的char[] 数组也是final修饰的,意味着String类是无法被继承和改变的。它内部不存在扩容机制。字符串拼接,截取等操作都会生成一个新的字符串对象。因此,频繁操作String对象效率会比较低。

(2)StringBuilder继承自AbstractStringBuilder, 类内部维护了一个可变长度char[] (即没有final修饰), 初始化数组容量为16,当char[]的空间不足时会启用存在扩容机制。在操作StringBuilder的字符串时会调用System的native方法进行数组的拷贝。因此,不会像String一样重新生成新的字符串对象。 但在调用 toString方法时不会共享StringBuilder对象内部的char[],而是进行一次char[]的copy操作,使用新生成的char[]数组重新生成的String对象。toString代码如下:

public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

另外,StringBuilder是非线程安全的。

(3)StringBuffer同样也继承自AbstractStringBuilder,由于大部分逻辑都是在AbstractStringBuilder中实现的,所以StringBuilder与StringBuilder差别不大。只是StringBuffer重写了相关方法,并加了synchronize关键字,保证了线程安全。另外一点是StringBuffer有一个String类型的toStringCach的缓存,在进行字符串操作的时候都会更新toStringCache的值。在调用toString方法时,返回的String共享了toStringCach。如下代码:

@Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

详情参考:Java进阶--深入理解Java中的字符串(二)

Java中的String字符串

StringBuilder与StringBuffer

公众号:玩转安卓Dev

Java基础

面向对象与Java基础知识

Java集合框架

JVM

多线程与并发

设计模式

Kotlin

Android

项目相关问题

Android基础知识

Android消息机制

Android Binder

View事件分发机制

Android屏幕刷新机制

View的绘制流程

Activity启动

Framework

性能优化

Jetpack&系统View

第三方框架实现原理

计算机网络

算法

Clone this wiki locally