String

本文探讨了Java中String对象的创建过程,包括字符串常量池的使用和不可变性。通过示例代码解释了字符串的内存分配以及`String`对象的比较。在常量池中查找字符串可以避免重复创建对象,而任何修改String对象的操作都会生成新对象。文章还分析了`String`对象的内存布局和构造方法,强调了`String`的final属性对于其不可变性的保证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class App {
    public static void main(String[] args) {
        String a = "111";
        a = "222";
        System.out.println(a);
    }
}

JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:

使用字符串常量池。每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串。

这里先去JVM给常量池里找,找到了就不用创建对象了,直接把对象的引用地址赋给a。找不到会重新创建一个对象,然后把对象的引用地址赋给a。同理a="222";也是先找,找不到就重新创建一个对象,然后把对象的引用地址赋给a。

String 为什么是不可变的?

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
    public String() {
        this.value = "".value;
    }
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }
}   

String 类是final修饰

String存储内容使用的是char数组

char数组是final修饰

无论是concat、replace、substring还是trim方法的操作都不是在原有的字符串上进行的,而是重新生成了一个新的字符串对象。也就是说进行这些操作后,最原始的字符串并没有被改变。

得出两个结论:

String对象一旦被创建就是固定不变的了,对String对象的任何改变都不影响到原对象,相关的任何变化性的操作都会生成新的对象。

String对象每次有变化性操作的时候,都会从新new一个String对象(这里指的是有变化的情况)。

public class App {
    public static void main(String[] args) {
        String a = "111";
        String a1 = "111";

        String b = new String("111");

        //对象地址是同一个
        System.out.println(a==a1);
        //对象内容是一样的
        System.out.println(a.equals(a1));
        //对象地址不一样
        System.out.println(a==b);
        //对象内容是一样的
        System.out.println(a.equals(b));
    }
}
true
true
false
true

第一个输出true,说明a和a1两个变量保存的引用地址是同一个。

第二个也输出true,说明a和a1引用地址中内容是一样的。

a和a1放在栈上,存放着对象的引用地址。

new的对象是在堆中。

常量其实是要看jdk版本的。

å¾ç

å¾ç

所以String a = "111"; 在JVM申请内存存放"111"对应的对象,并将对象保存起来。当String a1="1111";的时候,会先去JVM的那块地里寻找是否存在"111",刚好前面保存过,所以找到,然后直接把对象的引用地址给了a1。所以此时的a和a1都保存着同一个引用地址。

接触java后都知道可以new一个对象。所以 String b = new String("111");就是创建一个对象然后把对象引用地址赋给变量b。但是这里有个特殊点,那就是(“111”),这里会先去JVM里的那块地里找找,找到了直接存放引用地址。找不到创建一个对象然后把引用地址给String的有参构造方法里。

所以第三个中输出false,因为a和b所保存的对象引用是不一样的。

最后一个输出true。那是因为两个变量所保存的引用地址中的内容都是“111”.

答案:

如果常量池中存在,则只需创建一个对象,否则需要创建两个对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值