多线程----Immutable VS Mutable (可变与不可变)

本文探讨了Java中Immutable对象的概念,以String为例说明其不可变性及其在多线程环境下的优势。文章通过示例程序展示了如何确保对象的不变性,并讨论了何时应该使用不可变对象,以及哪些情况可能破坏不可变性。最后,提到了Java标准库中其他使用不可变模式的类,并指出即使不可变对象如String,也可能通过反射进行状态修改的风险。
摘要由CSDN通过智能技术生成

Immutable

    Immutable是什么意思?不变的、不发生改变的意思。在JDK中有很多的类被设计成不可变的,举个大家经常用到的类java.lang.StringString类被设计成不可变。String所表示的字符串的内容绝对不会发生变化。因此,在多线程的情况下,String类无需进行互斥处理,不用给方法进行synchronized或者lock等操作,进行上锁、争抢锁、解锁等流程也是有一定性能损耗的。因此,若能合理的利用Immutable,一定对性能的提升有很大帮助。

为什么String不可变?

    那么为什么String是不可变的呢?满足那些条件才可以变成不可变的类?大家可以打开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];
    /**
     * Allocates a new {@code String} so that it represents the sequence of
     * characters currently contained in the character array argument. The
     * contents of the character array are copied; subsequent modification of
     * the character array does not affect the newly created string.
     *
     * @param  value
     *         The initial value of the string
     */
    public String(char value[]) {
   
        this.value = Arrays.copyOf(value, value.length);
    }
    /**
     * Converts this string to a new character array.
     *
     * @return  a newly allocated character array whose length is the length
     *          of this string and whose contents are initialized to contain
     *          the character sequence represented by this string.
     */
    public char[] toCharArray() {
   
        // Cannot use Arrays.copyOf because of class initialization order issues
        char result[] = new char[value.length];
        System.arraycopy(value, 0, result, 0, value.length);
        return result;
    }
  }

通过上边的这段代码你会发现:

1、首先String类本身是被final修饰过的,表明该类无法进行扩展,无法创建子类。因此类中声明的方法则不会被重写。
2、String类中的成员变量都被final修饰,同时均为private,被final修饰则表示成员变量
不会被setter方法再次赋值,private则表示成员变量均为类私有,外部无法直接调用。
3、String类中的成员变量都没有setter方法,避免其他接口调用改变成员变量的值。
4、通过构造器初始化所有成员,同时在String中赋值是用的Arrays.copyOf等深拷贝方法。
5、在getter方法中,不要直接返回对象本身,而是克隆对象,并返回对象的拷贝。

以上5点保证String类的不可变性(immutability)。

示例程序

    下面咱们通过一些简单的示例程序来实验Immutable,自己动手,丰衣足食,多动手会有好处的。下边定义三个类。

类名 说明
People 表示一个人的类
PeopleThread 表示People实例的线程的类
Main 测试程序行为的类

下边看下每个类的示例代码,People类,类以及成员变量均被final修饰,同时只能通过构造函数来对成员变量赋值,没有setter方法:

public final class People {
   
    private final String sex;
    private final int age;
    private f
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值