java创建一个不可变对象_如何在Java中创建不可变类?

java创建一个不可变对象

Today we will learn about the immutable class in Java. What are immutable classes? The benefits and importance of deep copy for immutability.

今天,我们将学习Java中的不可变类。 什么是不可变类? 深复制对于不变性的好处和重要性。

什么是Java中的不可变类? (What is an immutable class in Java?)

Immutable objects are instances whose state doesn’t change after it has been initialized. For example, String is an immutable class and once instantiated its value never changes.

不可变对象是实例,其状态在初始化后不会改变。 例如, String是一个不可变的类,一旦实例化,其值就永远不会改变。

Read: Why String in immutable in Java

阅读为什么Java中的String不可变

Java中不可变类的好处 (Benefits of Immutable Class in Java)

An immutable class is good for caching purposes because you don’t have to worry about the value changes.

不可变的类非常适合缓存,因为您不必担心值的更改。

Another benefit of immutable class is that it is inherently thread-safe, so you don’t have to worry about thread safety in case of multi-threaded environment.

不可变类的另一个好处是,它本质上是线程安全的 ,因此在多线程环境中,您不必担心线程安全。

Read: Java Thread Tutorial and Java Multi-Threading Interview Questions.

阅读Java线程教程Java多线程面试问题

Here I am providing a way to create an immutable class via an example for better understanding.

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

如何用Java创建一个不可变的类? (How to Create an immutable class in Java?)

To create an immutable class in Java, you have to do the following steps.

要使用Java创建不可变的类,您必须执行以下步骤。

  1. Declare the class as final so it can’t be extended.

    将课程声明为最终课程,因此无法扩展。
  2. Make all fields private so that direct access is not allowed.

    将所有字段设为私有,以便不允许直接访问。
  3. Don’t provide setter methods for variables.

    不要为变量提供setter方法。
  4. Make all mutable fields final so that its value can be assigned only once.

    将所有可变字段定为最终值,使其值只能分配一次。
  5. Initialize all the fields via a constructor performing deep copy.

    通过执行深度复制的构造函数初始化所有字段。
  6. Perform cloning of objects in the getter methods to return a copy rather than returning the actual object reference.

    在getter方法中执行对象的克隆以返回副本,而不是返回实际的对象引用。

To understand points 4 and 5, let’s run the sample Final class that works well and values don’t get altered after instantiation.

为了理解第4点和第5点,让我们运行示例Final类,该类运行良好,并且实例化后值不会改变。

FinalClassExample.java

FinalClassExample.java

package com.journaldev.java;

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

public final 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;
	}

	/**
	 * Accessor function for mutable objects
	 */
	public HashMap<String, String> getTestMap() {
		//return testMap;
		return (HashMap<String, String>) testMap.clone();
	}

	/**
	 * Constructor performing Deep Copy
	 * @param i
	 * @param n
	 * @param hm
	 */
	
	public FinalClassExample(int i, String n, HashMap<String,String> hm){
		System.out.println("Performing Deep Copy for Object initialization");
		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;
	}
	
	
	/**
	 * Constructor performing Shallow Copy
	 * @param i
	 * @param n
	 * @param hm
	 */
	/**
	public FinalClassExample(int i, String n, HashMap<String,String> hm){
		System.out.println("Performing Shallow Copy for Object initialization");
		this.id=i;
		this.name=n;
		this.testMap=hm;
	}
	*/
	
	/**
	 * To test the consequences of Shallow Copy and how to avoid it with Deep Copy for creating immutable classes
	 * @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);
		
		//Lets see whether its copy by field or reference
		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());
		//change the local variable values
		i=20;
		s="modified";
		h1.put("3", "third");
		//print the values again
		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());

	}

}

Output of the above example program is:

上面的示例程序的输出是:

Performing Deep Copy for Object initialization
true
false
ce id:10
ce name:original
ce testMap:{2=second, 1=first}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{2=second, 1=first}
ce testMap after changing variable from accessor methods:{2=second, 1=first}

为什么Deep Copy对于不变性很重要? (Why Deep Copy is important for immutability?)

Let’s comment the constructor providing deep copy and uncomment the constructor providing a shallow copy.

让我们评论提供深拷贝的构造函数,并取消注释提供浅拷贝的构造函数。

Also, uncomment the return statement in the getTestMap() method that returns the actual object reference.

另外,在返回实际对象引用的getTestMap()方法中取消注释return语句。

Run the program after all the changes are done. It will produce the following output.

完成所有更改后,运行程序。 它将产生以下输出。

Performing Shallow Copy for Object initialization
true
true
ce id:10
ce name:original
ce testMap:{2=second, 1=first}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{3=third, 2=second, 1=first}
ce testMap after changing variable from accessor methods:{3=third, 2=second, 1=first, 4=new}

As you can see from the output, HashMap values got changed because of shallow copy in the constructor.

从输出中可以看到,由于构造函数中的浅表复制, HashMap的值已更改。

It’s happening because of the direct reference to the original object in the getter function.

之所以发生这种情况,是因为直接在getter函数中引用了原始对象。

That’s all for an immutable class in Java. We also learned the importance of deep copy for immutable classes.

这就是Java中不可变类的全部内容。 我们还了解了深度复制对于不可变类的重要性。

Further Reading: If the immutable class has a lot of attributes and some of them are optional, we can use builder pattern to create immutable classes.

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

GitHub Repository. GitHub Repository中查看更多Java示例。

翻译自: https://www.journaldev.com/129/how-to-create-immutable-class-in-java

java创建一个不可变对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值