我是靠谱客的博主 无奈小白菜,最近开发中收集的这篇文章主要介绍String为什么不可变,超级容易理解首先我们都知道String是一个不可变对象,那什么是不可变对象呢?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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是一个不可变对象,那什么是不可变对象呢?所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部