概述
String为什么不可变,超级容易理解
- 首先我们都知道String是一个不可变对象,那什么是不可变对象呢?
- 走着
- 分析
- 结合源码分析
- 废了吗?
首先我们都知道String是一个不可变对象,那什么是不可变对象呢?
一个对象在创建完成之后,不能或者无法改变他的状态,那么这个对象就是不可变的对象不能改变状态的意思是说:对象内的成员变量(包括基本数据类型的值不能变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变)
走着
什么是不可变对象呢?一个对象在创建完成之后,不能或者无法改变他的状态,那么这个对象就是不可变的对象
不能改变状态的意思是说:对象内的成员变量(包括基本数据类型的值不能变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变)
对象和对象的引用:
代码:
String s = "aaaa";
System.out.println("s"+s);
String s1 = "bbbb";
s = s1;
System.out.println("s" +s);
输出结果:s=aaaa s=bbbb
发现都是s但是输出的结果不是变化了吗?怎么能说String是不可变对象呢?
分析
首先创建了一个String的s对象,给s赋值为aaaa,然后又让s的值为“123456”,从打印结果来看s确实发生了变化
其实这里的s并不是String的对象,而是String的一个引用,并非对象本身,
这里简单说一下对象和引用(对象:Thinking in java中有这么一段话:按照通俗的说法,每个对象都是某个类(class)的一个实例(instance),这里,‘类’就是‘类型’的同义词)
即对象是类的一个实例,比如有一个person类,里面有一个具体的人“张三”,这个张三就是一个对象,是Person类的一个实例
引用:举例说明:
//①
Person person = new Person("张三");
//②
Person person1;
person1 = new Person("张三");
①②实现的功能是完全一样的
在Java中new是用来在堆上创建对象用的,如果person 是一个对象的话,那么②中第二行为何还要通过new来创建对象呢?由此可见,person 并不是所创建的对象,是什么?就只能是引用了
回到正题:s是一个引用,他指向了一个具体的对象,当s=“bbbb”时,又创建了一个新的对象。在这里有段话:一个引用可以指向多个对象
即相同的s引用会输出不同的值。而原来的对象“aaaa”还在内存中存在,并没有改变。
结合源码分析
在java中我们一般不可能直接操作对象本身,所有的对象都由一个引用指向,必须通过这个引用才能访问对象本身,包括获取成员变量的值,改变对象的成员变量,调用对象的方法等,以person点的方式操作:
即:
//①
Person person = new Person("张三");
person.xxx();
String类的源码:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
/**
* Class String is special cased within the Serialization Stream Protocol.
*
* A String instance is written into an ObjectOutputStream according to
* <a href="{@docRoot}/../platform/serialization/spec/output.html">
* Object Serialization Specification, Section 6.2, "Stream Elements"</a>
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
发现变量都是private的,并且没有提供set方法来修改这些值,所以在String类的外部无法修改String。也就是说一旦初始化就不能修改, 并且在String类的外部不能访问这些成员。此外,char value[];变量是final的, 也就是说在String类内部,一旦这三个值初始化了, 也不能被改变。所以可以认为String对象是不可变的了。
在我们平时写代码的时候经常会用到一些substring, replace, replaceAll, toLowerCase等函数来改变String类型的值,这是为什么呢?
其实是同样的道理,都是在这些函数内部新建了String的对象,才导致我们产生了改变的假象。
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
String中substring方法的源码中的返回值是:return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);都是在方法内部重新创建新的String对象,并且返回这个新的对象,原来的对象是不会被改变的。
String s = "aaaa";
s.replace("aaaa","ccccc");
System.out.println("******"+s);
String s1 = s.replace("aaaa","ccccc");
System.out.println("******"+s1);
这段代码看懂了就理解了,猜猜输出的是啥
废了吗?
最后
以上就是无奈小白菜为你收集整理的String为什么不可变,超级容易理解首先我们都知道String是一个不可变对象,那什么是不可变对象呢?的全部内容,希望文章能够帮你解决String为什么不可变,超级容易理解首先我们都知道String是一个不可变对象,那什么是不可变对象呢?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复