如何在java中创建不可变类?

原文【如何在java中创建不可变类?】地址

今天我们将学习如何在java中创建不变的类。不可变对象是在初始化之后状态不变的实例。例如,String是一个不可变类,一旦实例化,它的值不会改变。

不可改变的类对于缓存的目的是有益的,因为你不需要担心价值的变化。不可变类的其他好处是它本质上是线程安全的,所以在多线程环境的情况下,您不需要担心线程安全。

在这里,我提供了一种通过一个例子来创建Java中不可变类的方法,以便更好地理解。

要在java中创建不可变类,您必须执行以下步骤。

  1. 将类声明为final,因此无法扩展。
  2. 使所有字段都是私有的,以便不允许直接访问。
  3. 不要为变量提供setter方法
  4. 使所有可变字段都是最终的,以便它的值只能被分配一次。
  5. 通过执行深层拷贝的构造函数初始化所有字段。
  6. 在getter方法中执行对象的克隆以返回一个副本而不是返回实际的对象引用。

要了解第4点和第5点,我们来运行Final类,其效果很好,实例化后值不会被更改。

FinalClassExample.java

import java.util.HashMap;
import java.util.Iterator;

/**
 * <p></p>
 *
 * @author 三产
 * @version 1.0
 * @date 2017-03-24
 * @QQGroup 213732117
 * @website http://www.coderknock.com
 * @copyright Copyright 2017 拿客 coderknock.com  All rights reserved.
 * @since JDK 1.8
 */
public class FinalClassExample {
    
    private final int id;

    private final String name;

    private final HashMap<String,String> testMap;

    public int getId() {
        return id;
    }


    public String getName() {
        return name;
    }

    /**
     * 可变对象的访问器函数
     */
    public HashMap<String, String> getTestMap() {
        return (HashMap<String, String>) testMap.clone();
    }

    /**
     * 构造函数 执行深层复制
     * @param i
     * @param n
     * @param hm
     */

    public FinalClassExample(int i, String n, HashMap<String,String> hm){
        System.out.println("执行 深复制 对象初始化");
        this.id=i;
        this.name=n;
        HashMap<String,String> tempMap=new HashMap<String,String>();
        String key;
        Iterator<String> it = hm.keySet().iterator();
        while(it.hasNext()){
            key=it.next();
            tempMap.put(key, hm.get(key));
        }
        this.testMap=tempMap;
    }

    /**
     * 测试 浅复制 的后果以及如何避免使用 深复制 创建不可变类
     * @param args
     */
    public static void main(String[] args) {
        HashMap<String, String> h1 = new HashMap<String,String>();
        h1.put("1", "first");
        h1.put("2", "second");

        String s = "original";

        int i=10;

        FinalClassExample ce = new FinalClassExample(i,s,h1);

        //让我们看看它是按字段还是引用复制。
        System.out.println(s==ce.getName());
        System.out.println(h1 == ce.getTestMap());
        //print the ce values
        System.out.println("ce id:"+ce.getId());
        System.out.println("ce name:"+ce.getName());
        System.out.println("ce testMap:"+ce.getTestMap());
        //修改本地变量的值
        i=20;
        s="modified";
        h1.put("3", "third");
        
        System.out.println("ce id after local variable change:"+ce.getId());
        System.out.println("ce name after local variable change:"+ce.getName());
        System.out.println("ce testMap after local variable change:"+ce.getTestMap());

        HashMap<String, String> hmTest = ce.getTestMap();
        hmTest.put("4", "new");

        System.out.println("ce testMap after changing variable from accessor methods:"+ce.getTestMap());

    }
}

输出如下:

执行 深复制 对象初始化
true
false
ce id:10
ce name:original
ce testMap:{1=first, 2=second}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{1=first, 2=second}
ce testMap after changing variable from accessor methods:{1=first, 2=second}

修改构造函数为浅复制,输出如下:

执行 浅复制 对象初始化
true
false
ce id:10
ce name:original
ce testMap:{1=first, 2=second}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{1=first, 2=second, 3=third}
ce testMap after changing variable from accessor methods:{1=first, 2=second, 3=third}

对比两次输出可以看出,HashMap 值由于构造函数中的浅复制而改变,并提供对getter函数中原始对象的直接引用。

进一步阅读:如果不可变类有很多属性,其中一些属性是可选的,我们可以使用构建器模式创建不可变类

转载于:https://my.oschina.net/coderknock/blog/866300

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值