java中String类为什么要设计成final

这是个很有趣的问题,String设计成final类型,不能被继承、不能被重写,简言之String是不可变的。问题在于为什么不可变呢?这主要是性能与安全性的考虑。String是JVM中使用频率非常高的数据类型,涉及很多底层操作,因此SUN公司的工程师在设计String时,很小心的把整个String设置成final禁止继承,避免被其他人继承后破坏。另外一方面String作为高频使用数据类型,SUN对String的内存分配做了很多优化,比如字符串常量池,就是基于String的不可变性来实现的。

String内存分配机制

当在class文件被JVM装载到方法区后,JVM会创建一个常量池,常量池用于存放该类型所用到直接常量(String,Integer和 Floating point常量)和对其他类型,字段和方法的符号引用。对于String类型,当执行字符串初始化时,JVM会先在常量池检查是否存在字符串对象,如果存在则将字符串变量引用指向已经存在的对象。

创建赋值过程分析:在class文件被JVM装载到内存中,JVM会创建一块String Pool(String缓冲池)。当执行String s = “abc”;时,JVM首先在String Pool中查看是否存在字符串对象“abc”(如何查看呢?用equals()方法判断),如果已存在该对象,则不用创建新的字符串对象“abc”,而直接使用String Pool中已存在的对象“abc”,然后将引用指向该对象;如果不存在该对象,则先在String Pool中创建一个新的字符串对象“abc”,然后将引用指向String Pool中创建的新对象。当要对变量进行赋值,则会重新创建一个字符串对象然后把这个对象的引用导向变量。

从这里可以看出,常量池中一个字符串对象会指向多个变量的,如果String可变,那么就会导致多个变量的值同时发生变动,这显然不是我们所希望的。当然你可以说这是JVM的原因,那么如果你设计的String是可变的,你必须同时兼顾JVM创建字符串,字符串变动的一系列流程。即使这是可行的,那么必然会导致String对象的增多,JVM内存使用率的降低。对于一个使用频率很高对类型,这样的影响我们可能会无法接受。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章