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

2021年5月13日16:43:15 发表评论 866 次浏览

不可变的类意味着一旦创建了对象, 我们就无法更改其内容。在Java中, 所有包装类(例如Integer, Boolean, Byte, Short)和String类是不可变的。我们也可以创建自己的不可变类。

以下是要求:

  • 该类必须声明为最终类(这样才能创建子类)
  • 该类中的数据成员必须声明为私有(因此, 不允许直接访问)
  • 该类中的数据成员必须声明为final(这样, 在创建对象后我们就无法更改其值)
  • 参数化的构造函数应初始化执行深层复制的所有字段(这样就不能使用对象引用来修改数据成员)
  • 对象的深层复制应在getter方法中执行(要返回副本而不是返回实际的对象引用)
  • 无设置器(无法选择更改实例变量的值)

创建不可变类的示例

Java

import java.util.HashMap;
import java.util.Map;
 
//An immutable class
public final class Student {
     private final String name;
     private final int regNo;
     private final Map<String, String> metadata;
 
     public Student(String name, int regNo, Map<String, String> metadata)
     {
         this .name = name;
         this .regNo = regNo;
         Map<String, String> tempMap = new HashMap<>();
         for (Map.Entry<String, String> entry :
              metadata.entrySet()) {
             tempMap.put(entry.getKey(), entry.getValue());
         }
         this .metadata = tempMap;
     }
 
     public String getName() { return name; }
 
     public int getRegNo() { return regNo; }
 
     public Map<String, String> getMetadata()
     {
         Map<String, String> tempMap = new HashMap<>();
         for (Map.Entry<String, String> entry :
              this .metadata.entrySet()) {
             tempMap.put(entry.getKey(), entry.getValue());
         }
         return tempMap;
     }
}
 
//Driver class
class Test {
     public static void main(String[] args)
     {
         Map<String, String> map = new HashMap<>();
         map.put( "1" , "first" );
         map.put( "2" , "second" );
         Student s = new Student( "ABC" , 101 , map);
         System.out.println(s.getName());
         System.out.println(s.getRegNo());
         System.out.println(s.getMetadata());
 
         //Uncommenting below line causes error
         //s.regNo = 102;
 
         map.put( "3" , "third" );
         System.out.println(s.getMetadata()); //Remains unchanged due to deep copy in constructor
 
         s.getMetadata().put( "4" , "fourth" );
         System.out.println(s.getMetadata()); //Remains unchanged due to deep copy in getter
     }
}

输出如下

ABC
101
{1=first, 2=second}
{1=first, 2=second}
{1=first, 2=second}
木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: