关于字符串你需要知道几件事

本文深入探讨Java中字符串的创建、比较及不可变性特点,解析字符串常量池的作用,以及通过反射机制修改字符串内容的可能性。

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

大部分的编程语言都有一个专门的类型表示字符串

在Java中,创建字符串有三种主要的形式

public class Test {
    public static void main(String[] args) {
        //第一种:hehe是一种字符串常量,用一个String类型的引用指向hehe
        String str1 = "hehe";
        
        
        //第二种:new了一个String对象
        String str2 = new String("hehe");
        
        //第三种:借助字符数组构建
        char[] arr = {'a','b','c'};
        String str3 = new String(arr)
    }
}

第一种方式:hehe是一种字符串常量,用一个String类型的引用指向hehe
在这里插入图片描述
第二种方法:new了一个String对象
String str2 = new String(“hehe”);
在这里插入图片描述
相比方式1 多创建了一个额外的对象

第三种方法:两个对象,两个引用

在这里插入图片描述

Java中的字符串叫做不可变对象(对比数组).一旦把某个字符串对象创建好,这个字符串的内容就不能修改了,实在想改只能创建新的字符串对象。(String 类没有提供类似set方法这样的操作来修改String对象的内容)

int[] arr = {1,2,3};
        int[] arr2 = arr;
        arr2[0] = 100;
        System.out.println(arr[0]);

输出结果为100

public class Test {
    public static void main(String[] args) {
        String str1 = "hehe";
        String str2 = str1;
        str1 = "world";
        System.out.println(str2);
    }
}

输出结果是 hehe
因为 str1 str2 都指向 “hehe”这个对象
修改str1让它指向world,str2也是指向hehe,所以并没有影响.

2.字符串比较相等

String str1 = "hehe";
        String str2 = "hehe";
        if(str1 == str2){
            System.out.println("相等");
        }else {
            System.out.println("不想等");
        }
相等

因为“hehe”,都是字符串常量,实际上只有一份,str1和str2都指向它,所以输出结果

String str1 = "hehe";
        String str2 = new String("hehe");
        if(str1 == str2){
            System.out.println("相等");
        }else {
            System.out.println("不相等");
        }
不相等

java中用 == 针对引用类型比较的是对象的身份(两个引用是不是对应同一个对象)。

如果想比较两个字符串的值,用equals方法,或者使用compareTo方法也行。

str1.equals(str2)

“hehe"这样的字符串常量存在一个内存的特殊区域中,称为"字符串常量池”(本质上是堆中的一个区域)
如何在池中查找值为"hello"对象?哈希表

如何把new出来的String对象放入池子中

String str2 = new String("hehe").intern();
//此时str2指向的是池中的对象

intern做的事情:
1.查找当前这个字符串是否在常量池中包含,根据哈希表查找形式
2.如果包含了,直接返回池中的对象的引用
3.如果没包含,那就根据当前这个对象的值,在池中构造一个相同值的新的对象,并返回这个池里的引用。

面试题:请解释String类中两种对象实例化的区别
1.直接赋值:只开辟了一块堆内存空间,并且该字符串对象可以自动保存在对象池中供下次使用
2.构造方法:会开辟两块堆内存空间,其中一块保存在对象池中,可以使用intern()方法手工让他进入池。

字符串是不可变对象

String str1 = "hello";
        str1 = str1 + "world";
        str1 += "!!!";
        System.out.println(str1);

在这里插入图片描述
其中有三个在池子里,hello world !!! 有一个是垃圾
通常情况下,字符串是不可变对象,如果实在要修改,需要创建新的字符串对象

通过特殊手段修改字符串内容
反射

import java.lang.reflect.Field;

public class Test2 {
    public static void main(String[] args) {
        String str = "hehe";

        try {
            //1.获取到value这个字段对应的对象。
            Field valueField = String.class.getDeclaredField("value");
            //2.让value对应的对象可以被访问到,强行破坏封装
            valueField.setAccessible(true);
            //3.根据我们的valueField 对象和str对象,找到str中的value
            char[] value = (char[])valueField.get(str);
            //4.修改value
            value[0] = 'a';
            System.out.println(str);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
}

为什么String要不可变
1.方便实现字符串对象池,如果String可变,那么对象池就需要考虑何时深拷贝字符串的问题了
2.不可变对象是线程安全的。
3.不可变对象更方便缓存hash code,作为key时可以更高效的保存到HashMap中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值