首页 热点资讯 义务教育 高等教育 出国留学 考研考公

java 什么是不可变对象

发布网友 发布时间:2022-04-22 05:55

我来回答

3个回答

热心网友 时间:2023-11-11 06:53

不可变对象是指一个对象的状态在对象被创建之后就不再变化。不可变对象对于缓存是非常好的选择,因为你不需要担心它的值会被更改。


创建一个不可变类:

将类声明为final,所以它不能被继承;

将所有的成员声明为私有的,这样就不允许直接访问这些成员;

对变量不要提供setter方法;

将所有可变的成员声明为final,这样只能对它们赋值一次;

通过构造器初始化所有成员,进行深拷贝(deep copy);

在getter方法中,不要直接返回对象本身,而是克隆对象,并返回对象的拷贝;


示例:


public final class Immutable {  
    private final int id;  
    private final String name;  
    private final HashMap map;  
   
    public int getId() {  
        return id;  
    }  
   
    public String getName() {  
        return name;  
    }  
   
    /** 
     * 可变对象的访问方法 
     */  
    public HashMap getMap() {  
        return (HashMap) testMap.clone();  
    }  
   
    /** 
     * 实现深拷贝的构造器*/  
    public Immutable(int i, String n, HashMap hm){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.map = tempMap;  
    }  
  
}


不变模式有两种形式:弱不变模式和强不变模式。

弱不变模式,指类实例的状态是不可改变,但是这个类的子类的实例具有可能会变化的状态,要实现弱不变模式,一个类必须满足下面条件:

对象没有任何会修改对象状态的方法 ,这样一来当对象的构造函数将对象的状态初始化之后,对象的状态便不再改变;

属性都是私有的,以防客户端对象直接修改内部状态;

这个对象所引用的其他对象如果是可变的话,必须设法*外界对这些可变对象的访问,以防止外界修改这些对象,尽量在不可变对象内部初始化这些被引用的对象,而不要在客户端初始化再传入到不可变对象内部来,如果某个可变对象必须在客户端初始化,然后再传入到不变对象里的话,就应当考虑在不可变对象初始化的时候,将这个可变对象进行拷贝。


弱不变模式的缺点是,一个弱不变对象的子对象可能是可变的,这个可变的子对象可能可以修改父对象的状态,从而可能允许外界修改父对象的状态。


强不变模式:一个类的实例不会改变,同时它的子类的实例也具有不可变化的状态。一个类必须首先满足弱不变模式所要求的所有条件,并且还有满足下面条件之一:

类所有的方法都应当是final,这样这个类的子类不能够重写此类的方法;

此类本身就是final的,那么这个类就不可能会有子类,从而也就不可能有被子类修改的问题;

不变和只读的区别:当一个变量是只读时,变量的值不能直接改变,但是可以在其他变量发生改变的时候改变;比如生日是不变属性,而年龄是只读的,年龄会随着时间发生变化,生日则不会变化。(用final声明的变量是只读的)

不可变对象的好处:


不可变对象更容易构造,测试与使用;

真正不可变对象都是线程安全的;

不可变对象的使用没有副作用(没有保护性拷贝);

对象变化的问题得到了避免;

不可变对象的失败都是原子性的;

不可变对象更容易缓存,且可以避免null引用;

不可变对象可以避免时间上的耦合;


String,StringBuffer,StringBuilder,都是final类,不允许被继承,在本质上都是字符数组,不同的是,String的长度是不可变的而后两者长度可变,在进行连接操作时,String每次返回一个新的String实例,而StringBuffer和StringBuilder的append方法直接返回this,所以当进行大量的字符串连接操作时,不推荐使用String,因为它会产生大量的中间String对象。


StringBuffer和StringBuilder的一个区别是,StringBuffer在append方法前增加了一个synchronized修饰符,以起到同步的作用,为此也降低了执行效率;若要在toString方法中使用循环,使用StringBuilder。

热心网友 时间:2023-11-11 06:53

需要理解String中有一个pool(池),还有String a="name";其实是这样的:String a=new String(“name”);上网查查详细资料就能来理解了。
String:
是对象不是原始类型.
为不可变对象,一旦被创建,就不能修改它的值.
对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.
String 是final类,即不能被继承.

你应该是想要知道的是String、StringBuffer、StringBuilder之间的区别

热心网友 时间:2023-11-11 06:53

被const限定的变量
其实就是常量追答不好意思没看到是JAVA

JAVA是用final

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com