String类

1.概念
String是最终类,在java中是immutable(不可变),因为String类底层是根据不可改变字符数组来实现数据存储,String类对象的内容无法改变(常量)。当String实例创建时就会被初始化,并且以后无法修改实例信息。String类是工程师精心设计的艺术品。(提高安全性和效率)
一、String为什么不可变?
要了解String类创建的实例为什么不可变,首先要知道final关键字的作用:final的意思是“最终,最后”。final关键字可以修饰类、方法、字段。修饰类时,这个类不可以被继承;修饰方法时,这个方法就不可以被覆盖(重写),在JVM中也就只有一个版本的方法–实方法;修饰字段时,这个字段就是一个常量。
查看java.lang.String方法时,可以看到:

/**
 * The String class represents character strings. All string literals in Java programs, such as "abc",
 * are implemented as instances of this class.
*/
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
   ...
}

"The String class represents character strings"意思是String类表示字符串;String类被关键字final修饰,可以说明它不可被继承;从"private final char value[]"可知,String本质上是一个char数组。
String类的成员字段value是一个char[]数组,而且也是用final关键字修饰,被final关键字修饰的字段在创建后其值是不可变的,但也只是value这个引用地址不可变,可是Array数组的值却是可变的,Array数组数据结构如下图所示:
在这里插入图片描述从图中可以看出,Array变量只是栈上(stack)的一个引用,数组中的数据存储在堆上(heap)。String类里的value是用final修饰,只能说在栈上(stack)这个value的引用地址不可变,可没说堆里的Array本身数据不可变。

value是被final关键字修饰的,编译器不允许把value指向堆另外一个地址;但如果直接对数组元素进行赋值,就允许;如下面这个例子:
final int[] value  = {1,2,3,4,5};
value[0] = 0;

所以说String是不可变,在后面所有的String方法里没有去动Array中的元素,也没有暴露内部成员字段。private final char value[],private的私有访问权限的作用都比final大。所以String是不可变的关键都是在底层实现的,而不是一个简单的final关键字。

二、String类实例不可变的内存结构图
String类实例不可变很简单,如下图所示是String类实例不可变的内存结构图:在这里插入图片描述
有一个字符串s的值为"abcd",它再次被赋值为"abcdef",不是在原堆的地址上修改数据,而是重新指向一个新的对象,新的地址。
三、字符串常量池
字符串常量池是方法区(Method Area)中一个特殊的存储区域。当一个字符串被创建时,如果这个字符串的值已经存在String pool中,就返回这个已经存在的字符串引用,而不是创建一个新的对象,这样在大量使用字符串的情况下,可以节省内存空间,提高效率。但之所以能实现这个特性,String的不可变性是最基础的一个必要条件。
四、String类不可变有什么好处?
最简单的就是为了安全和效率。从安全上讲,因为不可变的对象不能被改变,他们可以在多个线程之间进行自由共享,这消除了进行同步的要求;从效率上讲,设计成final,JVM才不用对相关方法在虚函数表中查询,而是直接定位到String类的相关方法上,提高执行效率;总之,由于效率和安全问题,String被设计成不可变的,这也是一般情况下,不可变的类是首选的原因。

五、不可变类
不可变类只是它的实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例时就提供,并在对象 的整个生命周期内固定不变。String、基本类型的包装类、BigInteger和BigDecimal就是不可变得类。

    为了使类成为不可变,必须遵循以下5条规则:①不要提供任何会修改对象状态的方法。②保证类不会被扩展。③使所有的域都是final。④使所有的域都成为私有的。⑤确保 对于任何可变组件的互斥访问。如果类具有指向可变对象的域,则必须确保该类的客户端无法获得指向这些对象的引用。

六、不可变类的优点和缺点
不可变类实例不可变性,具有很多优点。①不可变类对象比较简单。不可变对象可以只有一种状态,即被创建时的状态。②不可变对象本质上是线程安全的,它们不要求同步。当多个线程并发访问这样的对象时,它们不会遭到破坏。实际上,没有任何线程会注意到其他线程对于不可变对象的影响。所以,不可变对象可以被自由地分配。“不可变对象可以被自由地分配”导致的结果是:永远不需要进行保护性拷贝。③不仅可以共享不可变对象,甚至也可以共享它们的内部信息。④不可变对象为其他对象提供了大量的构件。如果知道一个复杂对象内部的组件不会改变,要维护它的不变性约束是比较容易的。
不可变类真正唯一的缺点是,对于每个不同的值都需要一个单独的对象。创建这种对象的代价很高。
我也是网上看的,看懂之后转载的,如果有不懂的地方请看原文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值