美文网首页
不可变类

不可变类

作者: ThomasYoungK | 来源:发表于2017-11-21 07:50 被阅读6次

为什么String类是不可变的?

How to Create immutable Class in java?
To create immutable class in java, you have to do following steps.

  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
  4. Make all mutable fields final so that it’s 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.

To understand points 4 and 5, let’s run the sample Final class that works well and values doesn’t get altered after instantiation.
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 immutable class in java 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}

Now let’s comment the constructor providing deep copy and uncomment the constructor providing shallow copy. Also uncomment the return statement in getTestMap() method that returns the actual object reference and then execute the program once again.

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 and providing direct reference to the original object in the getter function.

相关文章

  • 1.6:避免创建不必要的对象

    ① 不可变类,采用静态工厂方法 对于不可变类,若同时提供了静态工厂方法和构造器的不可变类,通常可以使用静态工厂而不...

  • 对象的可变性以及深浅拷贝

    一、对象的可变性 OC的类有可变的类和不可变的类,这与变量和常量是不同的。可变类生成的对象是可变对象,不可变类生成...

  • String、StringBuffer、StringBuilde

    String String是不可变的类,即final 类,String底层使用final Char[] 来实现,不...

  • Object-C 学习笔记

    类的申明放在 .h 文件中,类的实现放在 .m 文件中 类分为可变类、不可变类2.1. 必须在不可变对象创建时,设...

  • iOS 面试宝典

    tip1.可变集合类 和 不可变集合类的 copy 和 mutablecopy 有什么区别? 对于可变与不可变对象...

  • [不可变类] 不可变类设计

    2017-1-18 11:40:25 oye 五条原则 不要提供任何会修改对象状态的方法 保证类不会被扩展(也有其...

  • Guava 集合类

    不可变集合类 为什么要使用不可变集合不可变对象有很多优点,包括: 当对象被不可信的库调用时,不可变形式是安全的;不...

  • Java不可变类

    0. 几个问题 什么是不可变类? 不可变类的优缺点是什么? 常见的不可变类有哪些?String为什么要设计成不可变...

  • Java学习笔记2

    Singleton / 不可变类 / 缓存不可变类 的实现 Singleton(单例类) 单例类用的地方很多,如果...

  • Foundation 框架常用API

    常用类 不可变:NSString、NSArray、NSDictionary可变: NSMutableString、...

网友评论

      本文标题:不可变类

      本文链接:https://www.haomeiwen.com/subject/gulivxtx.html