在java中,String其实是一个char型数组,而且是不可变的char型数组。至于为什么,很多人都说是因为它是被final修饰的,其实这是不准确的,在java中被final修饰只是说明它不可指向新的数组,并不意味着它本身的数据不会被改变,它之所以不可变还因为它是私有成员变量,且开发人员没有暴露和提供任何修改字符数组的方法。
而一些字符串操作都是返回的新字符对象,必不可能影响原数据。
上图:
同时,String的类也被final修饰了
这样就直接杜绝String被继承的可能,阻止了子类覆盖父类的操作。
以上就是为什么String是不可变的原因。
那么为什么要这样去设计呢?
第一:众所周知,在Java中存在堆空间,堆中有常量池。每当我们用字面量创建一个String时,返回的是已有对象的引用,如果String是可变的,那么被引用的值就是随时可以被修改的,一旦被修改就会影响到其他值的引用,造成的影响就不是一点半点的了,那就更不用谈Java常量池的复用了。
第二:不可变意味着不可能被修改,说明它是线程安全,不用担心在多线程场景下出现脏数据问题。
第三:字符数组不可变,意味着它的hash码也不可变,那么进行一次哈希码计算后下一次完全可以复用,有助于提高性能。同时这也是为什么我们能够放心的使用hash相关计算的原因。例:HashMap。
说到char型数组,就顺便再提一下数组。Java中一切皆对象(除了一些基本数据类型),包括类,方法,多线程中常提起的锁(同步监视器)都是对象。说这么多其实想说的就一句:数组也是对象。关于这一点在java官方其实有明确的说明,所以不必深究了。数组区别于其他对象的地方是:它并不是通过任何类来实例化的,它是由JVM直接创建的。意思是除Object外,数组不是任何类的实例,这也是数组区别于其它普通对象的点。
至于Array,只是数组相关的工具类,并不是数组类型。



