java之String的new String(String original) 和 new String(char value[]) 的区别

java中对于String这个不可变的字符串对象,大家都有所了解, 但是使用字面常量定义String和new String(String original) 定义String以及使用new String(char value[])定义String具体有审核区别呢?

字面常量定义String

		String name = "doublinglee";
        String name1 = "doublinglee";
        System.out.println("name|" + name + " - " + System.identityHashCode(name));
        System.out.println("name1|" + name1 + " - " + System.identityHashCode(name1));

输出(java8)

name|doublinglee - 2018699554
name1|doublinglee - 2018699554

这里java首先会在字符串常量池中查找这个字符串如果存在,则直接返回该字符串的引用地址;所以两个字符串打印出的hashCode(此处是原始的hashcode,而不是String重载后)

new String(String original) 定义

		String name = "doublinglee";
        String name1 = "doublinglee";
        String name2 = new String("doublinglee");
        System.out.println("name|" + name + " - " + System.identityHashCode(name));
        System.out.println("name1|" + name1 + " - " + System.identityHashCode(name1));
        System.out.println("name2|" + name2 + " - " + System.identityHashCode(name2));

输出(java8)

name|doublinglee - 2018699554
name1|doublinglee - 2018699554
name2|doublinglee - 1311053135

此时name3定义的字符串打印出的hashcode明显不同,说明创建了一个新的字符串对象;

接下来看一下通过反射强制修改String的内容(为了验证需要,大家在业务环境中不要使用,否则会改变String不可变的规则)

		String name = "doublinglee";
        String name1 = "doublinglee";
        String name2 = new String("doublinglee");
        try {
            Field charsField = String.class.getDeclaredField("value");
            charsField.setAccessible(true);
            char[] object = (char[])charsField.get(name);
            System.out.println(object.length);
            object[0] = 'P'; // 修改字符串第一个字符
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("name|" + name + " - " + System.identityHashCode(name));
        System.out.println("name1|" + name1 + " - " + System.identityHashCode(name1));
        System.out.println("name2|" + name2 + " - " + System.identityHashCode(name2));

输出(java8)

name|Poublinglee - 1311053135
name1|Poublinglee - 1311053135
name2|Poublinglee - 118352462

为什么name2也变了呢?

再看下增加new String(char value[])的创建方式

		String name = "doublinglee";
        String name1 = "doublinglee";
        String name2 = new String("doublinglee");
        String name3 = new String(name.toCharArray());
        try {
            Field charsField = String.class.getDeclaredField("value");
            charsField.setAccessible(true);
            char[] object = (char[])charsField.get(name);
            System.out.println(object.length);
            object[0] = 'P'; // 修改字符串第一个字符
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("name|" + name + " - " + System.identityHashCode(name));
        System.out.println("name1|" + name1 + " - " + System.identityHashCode(name1));
        System.out.println("name2|" + name2 + " - " + System.identityHashCode(name2));
        System.out.println("name3|" + name3 + " - " + System.identityHashCode(name3));

输出(java8)

name|Poublinglee - 1311053135
name1|Poublinglee - 1311053135
name2|Poublinglee - 118352462
name3|doublinglee - 1550089733

为什么name3没有变化呢?

带着疑问去看String的这两个构造方法

public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

发现new String(String original) 其实只是创建一个String外壳,内在的char[]其实是共用的,这说明不管你用new String(String original) 创建多少个对象,只要字符串一样,就会共用char[],真正的堆存储也会共用,避免了浪费;

而new String(char value[])是用了数组拷贝,原因也很简单,数组是你传进来的,为了保证String的不可变属性,只能拷贝,不能复用。

以上分析但愿对您有所帮助;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值