---

2015/10/25

layout: post
title: "Java创建一个不可变的类"
category: Reading Notes

tags: ["读文章", "Java"]

{% include JB/setup %}

创建一个不可变的类

  • 将类声明为final,所以它不能被继承
  • 将所有的成员声明为私有的,这样就不允许直接访问这些成员
  • 对变量不要提供setter方法
  • 将所有可变的成员声明为final,这样只能对它们赋值一次
  • 通过构造器初始化所有成员,进行深拷贝(deep copy)
  • 在getter方法中,不要直接返回对象本身,而是克隆对象,并返回对象的拷贝

    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 testMap;
     
        public int getId() {
            return id;
        }
     
        public String getName() {
            return name;
        }
     
        /**
         * 可变对象的访问方法
         */
        public HashMap getTestMap() {
            //return testMap;
            return (HashMap) testMap.clone();
        }
     
        /**
         * 实现深拷贝(deep copy)的构造器
         * @param i
         * @param n
         * @param hm
         */
     
        public FinalClassExample(int i, String n, HashMap hm){
            System.out.println("Performing Deep Copy for Object initialization");
            this.id=i;
            this.name=n;
            HashMap tempMap=new HashMap();
            String key;
            Iterator it = hm.keySet().iterator();
            while(it.hasNext()){
                key=it.next();
                tempMap.put(key, hm.get(key));
            }
            this.testMap=tempMap;
        }
     
        /**
         * 实现浅拷贝(shallow copy)的构造器
         * @param i
         * @param n
         * @param hm
         */
        /**
        public FinalClassExample(int i, String n, HashMap hm){
            System.out.println("Performing Shallow Copy for Object initialization");
            this.id=i;
            this.name=n;
            this.testMap=hm;
        }
        */
     
        /**
         * 测试浅拷贝的结果
         * 为了创建不可变类,要使用深拷贝
         * @param args
         */
        public static void main(String[] args) {
            HashMap h1 = new HashMap();
            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 hmTest = ce.getTestMap();
            hmTest.put("4", "new");
     
            System.out.println("ce testMap after changing variable from accessor methods:"+ce.getTestMap());
     
        }
     
    }
    

输出:

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}