精华内容
下载资源
问答
  • 文章目录谈谈不可变对象创建一个不可变类不可变类对于开发者来说有如下好处不可变对象好处:不变模式弱不变模式强不变模式不变和只读的区别再谈可变与不可变不可变对象一定不可变吗我们能创建一个包含可变对象的...

    谈谈不可变对象

    • 可变对象:相对于不可变类,可变类创建实例后可以改变其成员变量值,开发中创建的大部分类都属于可变类。

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

    • 那么对象是类实例化而来,怎么创建一个不可变类呢?

    创建一个不可变类

    • 一个不可变类,必须要满足以下条件:

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

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

    (3)对变量不要提供setter方法;

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

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

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

    (7)如果要修改类的状态,必须返回一个新的对象。

    不可变类对于开发者来说有如下好处:

    (1)易于设计,实现和使用

    (2)使用过程中不容易导致出错

    (3)更加的安全,可以随意地共用

    (4)天然具备线程安全性,无需增加额外的同步操作

    不可变对象的好处:

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

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

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

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

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

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

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

    什么是不变模式

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

    弱不变模式

    • 弱不变模式指类实例的状态是不可改变,但是这个类的子类的实例具有可能会变化的状态,要实现弱不变模式,一个类必须满足下面条件:
      (1)对象没有任何会修改对象状态的方法 ,这样一来当对象的构造函数将对象的状态初始化之后,对象的状态便不再改变;
      (2)属性都是私有的,以防客户端对象直接修改内部状态;

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

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

    强不变模式

    • 强不变模式指一个类的实例不会改变,同时它的子类的实例也具有不可变化的状态。一个类必须首先满足弱不变模式所要求的所有条件,并且还有满足下面条件之一:
      (1)类所有的方法都应当是final,这样这个类的子类不能够重写此类的方法;

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

    不变和只读的区别

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

    再谈可变与不可变

    不可变对象一定不可变吗

    • 答:“不一定的,因为不可变对象中包含有final定义的引用对象,此时引用对象的地址是不允许修改,但是引用对象的状态是允许修改的。”

    • 不可变对象虽然具备不可变性,但是不是"完全不可变"的,这里打上引号是因为通过反射的手段是可以改变不可变对象的状态的。
      大家看到这里可能有疑惑了,为什么既然能改变,为何还叫不可变对象?这里面大家不要误会不可变的本意,从不可变对象的意义分析能看出来对象的不可变性只是用来辅助帮助大家更简单地去编写代码,减少程序编写过程中出错的概率,这是不可变对象的初衷。如果真要靠通过反射来改变一个对象的状态,此时编写代码的人也应该会意识到此类在设计的时候就不希望其状态被更改,从而引起编写代码的人的注意。下面是通过反射方式改变不可变对象的例子:
      在这里插入图片描述

    我们能创建一个包含可变对象的不可变对象吗?

    • 我们是可以创建一个包含可变对象的不可变对象的,你只需要谨慎一点,不要共享可变对象的引用就可以了,如果需要变化时,就返回原对象的一个拷贝,最常见的例子就是对象中包含一个日期对象的引用。

    参考博文:https://www.cnblogs.com/dolphin0520/p/10693891.html

    展开全文
  • java 中不可变对象

    千次阅读 2018-11-30 23:12:07
    本文我们说明什么是不可变对象,在java 中如何实现以及其有和好处。 1. 什么是不可变对象 不可变对象是指对象被创建之后,其内部状态保存不变的对象。这意味着其公开的API保证在对象的整个生命周期中其行为保持...

    java 不可变对象

    本文我们说明什么是不可变对象,在java 中如何实现以及其有和好处。

    1. 什么是不可变对象

    不可变对象是指对象被创建之后,其内部状态保存不变的对象。这意味着其公开的API保证在对象的整个生命周期中其行为保持一致。

    下面我们看看String类,即使我们使用其replace api提供了一个可变的行为,但其原字符串并没有改变:

    String name = "baeldung";
    String newName = name.replace("dung", "----");
     
    assertEquals("baeldung", name);
    assertEquals("bael----", newName);
    

    该API属于只读方法,String中没有改变其内部状态的方法.

    2. final 关键字

    在我们实现不可变之前,我们先讨论下final关键字。在java中,变量默认是可变的,意味着我们可以修改其值。通过使用final关键字声明对象,java编译器不会让我们改变变量的值,否则会报错:

    final String name = "baeldung";
    name = "bael...";
    
    

    需要注意的是,final仅禁止我们改变变量的引用,但不阻止通过公开API改变对象的内部状态:

    final List<String> strings = new ArrayList<>();
    assertEquals(0, strings.size());
    strings.add("baeldung");
    assertEquals(0, strings.size());
    

    第二个assertEquals 会失败,因为增加元素值list会改变其size,因此,其非不可变对象。

    3. java 中不可变性

    现在我们知道如何避免改变变量的内容,因此可以构建不可变对象的API。其目的是无论我们如何使用其API,都需要保证对象内部状态不变。

    正确的做法是使用final关键字声明对象属性:

    class Money {
        private final double amount;
        private final Currency currency;
     
        // ...
    }
    

    java保证我们amount值不会改变,因为其为基本类型变量。然而上述代码仅会保证currency不会改变,因此我们必须依赖Currency API 防止外部改变。大多数情况下,我们需要多些属性值为自定义值,我们可以通过构造函数进行初始化:

    class Money {
        // ...
        public Money(double amount, Currency currency) {
            this.amount = amount;
            this.currency = currency;
        }
     
        public Currency getCurrency() {
            return currency;
        }
     
        public double getAmount() {
            return amount;
        }
    }
    

    如前面所述,满足不可变API需求,Money类仅提供只读方法。使用反射API,我们能打破不可变性,改变不可变对象。但反射违反了不可变对象的公共API,通常我们应该避免这样。

    4. 优势

    因为不可变对象内部状态始终保持不变,我们可以多线程中安全地共享使用。我们也可以自由地使用它,引用它的任何对象都不会有任何区别,因此不可变对象是无副作用的。

    5. 总结

    不可变对象任何时候不会修改其内部状态,是线程安全的,可以无副作用使用。因此,不可变对象在处理多线程环境下特别有用。

    展开全文
  • 不可变对象的权衡

    2015-06-05 15:52:38
    不可变对象提供了若干强于可变对象的优点和一个潜在的缺点。 首先, 不可变对象常常比可变对象更具逻辑性,因为它们没有随着时间而变化的复杂的状态空间。其次,你可 以很自由地传递不可变对象,而或许需要在把...

    不可变对象提供了若干强于可变对象的优点和一个潜在的缺点。

    首先,

    不可变对象常常比可变对象更具逻辑性,因为它们没有随着时间而变化的复杂的状态空间。其次,你可

    以很自由地传递不可变对象,而或许需要在把可变对象传递给其它代码之前,需要先建造
    个以防万一的副本。第三,没有机会能让两个同时访问不可变对象的线程破坏它合理构造
    的状态,因为根本没有线程可以改变不可变对象的状态。第四,不可变对象让哈希表键值
    更安全。比方说,如果可变对象在被放进了HashSet之后被改变,那么你下一次查找这个

    HashSet就找不到这个对象了。

    不可变对象唯一的缺点就是它们有时需要复制很大的对象图而可变对象的更新可以在
    原地发生。有些情况下这会变得难以快速完成而可能产生性能瓶颈。结果,要求库提供可
    变替代以使其更容易在大数据结构的中间改变一些元素也并非是一件稀奇的事情。例如,
    类StringBuilder是不可变的String的可变替代。第十八章中我们会给出更多Scala里
    设计可变对象的细节。

    展开全文
  • Java不可变对象

    千次阅读 2017-01-12 13:45:46
    一、不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值。如JDK内部自带的很多不可变类:Interger、Long和String等。 可变类:相对于不可变类,可变类创建实例后可以...

    一、不可变类简介

    不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值。如JDK内部自带的很多不可变类:Interger、Long和String等。
    可变类:相对于不可变类,可变类创建实例后可以改变其成员变量值,开发中创建的大部分类都属于可变类。

    下面的理解可能会易懂一些:

    {概念:不可变类的意思是创建该类的实例后,该实例的属性是不可改变的。Java中的8个包装类和String类都是不可变类。所以不可变类并不是指该类是被final修饰的,而是指该类的属性是被final修饰的。

    自定义不可变类遵守如下原则:

    1、使用private和final修饰符来修饰该类的属性。

    2、提供带参数的构造器,用于根据传入的参数来初始化属性。

    3、仅为该类属性提供getter方法,不要提供setter方法。

    4、如果有必要,重写hashCode和equals方法,同时应保证两个用equals方法判断为相等的对象,其hashCode也应相等。}


    二、不可变类的优点

    说完可变类和不可变类的区别,我们需要进一步了解为什么要有不可变类?这样的特性对JAVA来说带来怎样的好处?

    1. 线程安全
      不可变对象是线程安全的,在线程之间可以相互共享,不需要利用特殊机制来保证同步问题,因为对象的值无法改变。可以降低并发错误的可能性,因为不需要用一些锁机制等保证内存一致性问题也减少了同步开销。
    2. 易于构造、使用和测试
    3. ...

    三、不可变类的设计方法

    对于设计不可变类,个人总结出以下原则:

    1. 类添加final修饰符,保证类不被继承
    如果类可以被继承会破坏类的不可变性机制,只要继承类覆盖父类的方法并且继承类可以改变成员变量值,那么一旦子类以父类的形式出现时,不能保证当前类是否可变。

    2. 保证所有成员变量必须私有,并且加上final修饰
    通过这种方式保证成员变量不可改变。但只做到这一步还不够,因为如果是对象成员变量有可能再外部改变其值。所以第4点弥补这个不足。

    3. 不提供改变成员变量的方法,包括setter
    避免通过其他接口改变成员变量的值,破坏不可变特性。

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

    如果构造器传入的对象直接赋值给成员变量,还是可以通过对传入对象的修改进而导致改变内部变量的值。例如:

    public final class ImmutableDemo {  
        private final int[] myArray;  
        public ImmutableDemo(int[] array) {  
            this.myArray = array; // wrong  
        }  
    }

    这种方式不能保证不可变性,myArray和array指向同一块内存地址,用户可以在ImmutableDemo之外通过修改array对象的值来改变myArray内部的值。
    为了保证内部的值不被修改,可以采用深度copy来创建一个新内存保存传入的值。正确做法:

    public final class MyImmutableDemo {  
        private final int[] myArray;  
        public MyImmutableDemo(int[] array) {  
            this.myArray = array.clone();   
        }   
    }

    5. 在getter方法中,不要直接返回对象本身,而是克隆对象,并返回对象的拷贝
    这种做法也是防止对象外泄,防止通过getter获得内部可变成员对象后对成员变量直接操作,导致成员变量发生改变。

    四、String对象的不可变性

    string对象在内存创建后就不可改变,不可变对象的创建一般满足以上5个原则,我们看看String代码是如何实现的。

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence
    {
        /** The value is used for character storage. */
        private final char value[];
        /** The offset is the first index of the storage that is used. */
        private final int offset;
        /** The count is the number of characters in the String. */
        private final int count;
        /** Cache the hash code for the string */
        private int hash; // Default to 0
        ....
        public String(char value[]) {
             this.value = Arrays.copyOf(value, value.length); // deep copy操作
         }
        ...
         public char[] toCharArray() {
         // Cannot use Arrays.copyOf because of class initialization order issues
            char result[] = new char[value.length];
            System.arraycopy(value, 0, result, 0, value.length);
            return result;
        }
        ...
    }

    如上代码所示,可以观察到以下设计细节:

    1. String类被final修饰,不可继承
    2. string内部所有成员都设置为私有变量
    3. 不存在value的setter
    4. 并将value和offset设置为final。
    5. 当传入可变数组value[]时,进行copy而不是直接将value[]复制给内部变量.
    6. 获取value时不是直接返回对象引用,而是返回对象的copy.

    这都符合上面总结的不变类型的特性,也保证了String类型是不可变的类。

    五、String对象的不可变性的优缺点

    从上一节分析,String数据不可变类,那设置这样的特性有什么好处呢?我总结为以下几点:

    1.字符串常量池的需要.
    字符串常量池可以将一些字符常量放在常量池中重复使用,避免每次都重新创建相同的对象、节省存储空间。但如果字符串是可变的,此时相同内容的String还指向常量池的同一个内存空间,当某个变量改变了该内存的值时,其他遍历的值也会发生改变。所以不符合常量池设计的初衷。

    2. 线程安全考虑
    同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。

    3. 类加载器要用到字符串,不可变性提供了安全性,以便正确的类被加载。譬如你想加载java.sql.Connection类,而这个值被改成了myhacked.Connection,那么会对你的数据库造成不可知的破坏。

    4. 支持hash映射和缓存。
    因为字符串是不可变的,所以在它创建的时候hashcode就被缓存了,不需要重新计算。这就使得字符串很适合作为Map中的键,字符串的处理速度要快过其它的键对象。这就是HashMap中的键往往都使用字符串。

    缺点:

    1. 如果有对String对象值改变的需求,那么会创建大量的String对象。

    六、String对象的是否真的不可变

    虽然String对象将value设置为final,并且还通过各种机制保证其成员变量不可改变。但是还是可以通过反射机制的手段改变其值。例如:

        //创建字符串"Hello World", 并赋给引用s
        String s = "Hello World"; 
        System.out.println("s = " + s); //Hello World
    
        //获取String类中的value字段
        Field valueFieldOfString = String.class.getDeclaredField("value");
        //改变value属性的访问权限
        valueFieldOfString.setAccessible(true);
    
        //获取s对象上的value属性的值
        char[] value = (char[]) valueFieldOfString.get(s);
        //改变value所引用的数组中的第5个字符
        value[5] = '_';
        System.out.println("s = " + s);  //Hello_World

    打印结果为:

    s = Hello World
    s = Hello_World

    发现String的值已经发生了改变。也就是说,通过反射是可以修改所谓的“不可变”对象的

    总结

    不可变类是实例创建后就不可以改变成员遍历的值。这种特性使得不可变类提供了线程安全的特性但同时也带来了对象创建的开销,每更改一个属性都是重新创建一个新的对象。JDK内部也提供了很多不可变类如Integer、Double、String等。String的不可变特性主要为了满足常量池、线程安全、类加载的需求。合理使用不可变类可以带来极大的好处。

    具体实例

    构造一个不可变类非常容易,下面举一个简单例子:

    [java] view plain copy
    1. package com.home;  
    2.   
    3. public class Address {  
    4.     private final String detail;  
    5.   
    6.     public Address() {  
    7.         this.detail = "";  
    8.     }  
    9.   
    10.     public Address(String detail) {  
    11.         this.detail = detail;  
    12.     }  
    13.   
    14.     public String getDetail() {  
    15.         return detail;  
    16.     }  
    17.   
    18.     @Override  
    19.     public int hashCode() {  
    20.         return detail.hashCode();  
    21.     }  
    22.   
    23.     @Override  
    24.     public boolean equals(Object obj) {  
    25.         if (obj instanceof Address) {  
    26.             Address address = (Address) obj;  
    27.             if (this.getDetail().equals(address.getDetail())) {  
    28.                 return true;  
    29.             }  
    30.         }  
    31.         return false;  
    32.     }  
    33.   
    34. }  


    但是值得注意的是,该类的属性虽然是被final修饰的,但若属性是非String的其他引用类型的话,那么虽然该属性的内容(所指对象的地址)不会改变,但其指向的对象却有可能会改变,这样的类当然并不能成为不可变类。比如下面的Person类中有一个Name类型的属性:

    [java] view plain copy
    1. package com.home;  
    2.   
    3. public class Person {  
    4.     private final Name name;  
    5.   
    6.     public Person(Name name) {  
    7.         super();  
    8.         this.name = name;  
    9.     }  
    10.   
    11.     public Name getName() {  
    12.         return name;  
    13.     }  
    14.   
    15.     public static void main(String[] args) {  
    16.         Name n = new Name("三""张");  
    17.         Person p = new Person(n);  
    18.         System.out.println(p.getName().getFirstName());  
    19.         // 改变Person对象Name属性的firstName属性值  
    20.         n.setFirstName("无忌");  
    21.         System.out.println(p.getName().getFirstName());  
    22.     }  
    23. }  


    Name:

    [java] view plain copy
    1. package com.home;  
    2.   
    3. public class Name {  
    4.     private String firstName;  
    5.     private String lastName;  
    6.   
    7.     public Name() {  
    8.         super();  
    9.     }  
    10.   
    11.     public Name(String firstName, String lastName) {  
    12.         super();  
    13.         this.firstName = firstName;  
    14.         this.lastName = lastName;  
    15.     }  
    16.   
    17.     public String getFirstName() {  
    18.         return firstName;  
    19.     }  
    20.   
    21.     public void setFirstName(String firstName) {  
    22.         this.firstName = firstName;  
    23.     }  
    24.   
    25.     public String getLastName() {  
    26.         return lastName;  
    27.     }  
    28.   
    29.     public void setLastName(String lastName) {  
    30.         this.lastName = lastName;  
    31.     }  
    32. }  


    运行上面程序可以看到,Person对象的Name属性的firstName属性已经被改变,这就违背了不可变类设计的初衷。我们可以采取如下办法来解决,修改Person类如下:

    [java] view plain copy
    1. package com.home;  
    2.   
    3. public class Person {  
    4.     private final Name name;  
    5.   
    6.     public Person(Name name) {  
    7.         super();  
    8.         // 设置name属性为临时创建的Name对象,该对象的firstName属性和lastName属性  
    9.         // 与传入的name对象的firstName属性和lastName属性相同  
    10.         this.name = new Name(name.getFirstName(), name.getLastName());  
    11.     }  
    12.   
    13.     public Name getName() {  
    14.   
    15.         // 返回一个匿名对象,该对象的firstName属性和lastName属性  
    16.         // 与该对象里的name属性的firstName属性和lastName属性相同  
    17.         return new Name(name.getFirstName(), name.getLastName());  
    18.     }  
    19.   
    20.     public static void main(String[] args) {  
    21.         Name n = new Name("三""张");  
    22.         Person p = new Person(n);  
    23.         System.out.println(p.getName().getFirstName());  
    24.         // 改变Person对象Name属性的firstName属性值  
    25.         n.setFirstName("无忌");  
    26.         System.out.println(p.getName().getFirstName());  
    27.     }  
    28. }  


    再次运行程序,发现Person对象的Name属性的firstName属性没有改变了。

    另外,由于不可变类的实例的状态不可改变,所以可以很方便地被多个对象所共享,那么如果程序要经常使用相同的不可变类实例,为了减少系统开销,一般要考虑使用缓存机制。下面使用数组作为缓存池来构建一个可以缓存实例的不可变类:

    [java] view plain copy
    1. package com.home;  
    2.   
    3. public class CacheImmutale {  
    4.     private final String name;  
    5.     private static CacheImmutale[] cache = new CacheImmutale[10];  
    6.     private static int pos = 0;  
    7.   
    8.     public CacheImmutale(String name) {  
    9.         super();  
    10.         this.name = name;  
    11.     }  
    12.   
    13.     public String getName() {  
    14.         return name;  
    15.     }  
    16.   
    17.     public static CacheImmutale valueOf(String name) {  
    18.         // 遍历已缓存的对象  
    19.         for (int i = 0; i < pos; i++) {  
    20.             // 如果已有相同实例,直接返回该缓存的实例  
    21.             if (cache[i] != null && cache[i].getName().equals(name)) {  
    22.                 return cache[i];  
    23.             }  
    24.         }  
    25.         // 如果缓冲池已满  
    26.         if (pos == 10) {  
    27.             // 把缓存的第一个对象覆盖  
    28.             cache[0] = new CacheImmutale(name);  
    29.             pos = 1;  
    30.             return cache[0];  
    31.         } else {  
    32.             // 把新创建的对象缓存起来,pos加1  
    33.             cache[pos++] = new CacheImmutale(name);  
    34.             return cache[pos - 1];  
    35.         }  
    36.     }  
    37.   
    38.     @Override  
    39.     public int hashCode() {  
    40.         return name.hashCode();  
    41.     }  
    42.   
    43.     @Override  
    44.     public boolean equals(Object obj) {  
    45.         if (obj instanceof CacheImmutale) {  
    46.             CacheImmutale ci = (CacheImmutale) obj;  
    47.             if (name.equals(ci.getName())) {  
    48.                 return true;  
    49.             }  
    50.         }  
    51.         return false;  
    52.     }  
    53.   
    54.     public static void main(String[] args) {  
    55.         CacheImmutale c1 = CacheImmutale.valueOf("hello");  
    56.         CacheImmutale c2 = CacheImmutale.valueOf("hello");  
    57.         System.out.println(c1 == c2);// 输出结果为true  
    58.     }  
    59. }  

    对于缓存的使用,应根据系统需求而定,简单的说,如果某个对象使用的次数不多,重复使用的概率不大,就没必要使用缓存,毕竟缓存的对象也会占用系统内存。如果某个对象需要频换地重复使用,这时就应该使用缓存了。

     另外,上面的示例来源疯狂JAVA讲义一书,个人对上面那个Person类里面的属性是引用类型的解决办法存有疑问,他那种办法虽然保证的Person对象的Name属性所指对象的内容没有改变,但Person对象返回的Name属性已经不是同一个属性了,它的地址已发生改变,赋值和返回都是通过new出来的,我个人做了如下改进,觉得更合理:

    [java] view plain copy
    1. package com.home;  
    2.   
    3. public class Person {  
    4.     private final Name name;  
    5.   
    6.     public Person(Name name) {  
    7.         super();  
    8.         // 设置name属性为临时创建的Name对象,该对象的firstName属性和lastName属性  
    9.         // 与传入的name对象的firstName属性和lastName属性相同  
    10.         this.name = new Name(name.getFirstName(), name.getLastName());  
    11.     }  
    12.   
    13.     public Name getName() {  
    14.         // 直接返回当前实例的name属性即可  
    15.         return name;  
    16.     }  
    17.   
    18.     public static void main(String[] args) {  
    19.         Name n = new Name("三""张");  
    20.         Person p = new Person(n);  
    21.         System.out.println(p.getName() + "  " + p.getName().getFirstName());  
    22.         // 改变Person对象Name属性的firstName属性值  
    23.         n.setFirstName("无忌");  
    24.         System.out.println(p.getName() + "  " + p.getName().getFirstName());  
    25.     }  
    26. }  

    从打印结果可以看出p的name属性的地址和所指内容都没变。



    参考资料

    [1] http://my.oschina.net/zzw922cn/blog/487610

    [2] java的String 为什么是不可变的:http://www.codeceo.com/article/why-java-string-immutable.html

    [3] http://www.importnew.com/7535.html

    展开全文
  • java不可变对象

    2017-10-13 10:03:00
    本文主要来介绍一下Java...最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String类为什么要设成immutable类型? 不可变对象
  • 本文主要阐述以下观点: 1.值类型与引用类型的定义与区别;...2.不可变对象与可变对象的定义与区别; 3.不可变对象的优点与缺点; 4.String类为什么是不可变的; 5.怎样声明不可变对象(包括变量和类);
  • 不可变对象(immutable objects),后面文章我将使用immutable objects来代替不可变对象! 那么什么是immutable objects?什么又是mutable Objects呢? immutable Objects就是那些一旦被创建,它们的状态就不能...
  • Java 不可变对象

    2014-05-12 11:36:51
    不可变对象: 1:一旦创建,对象的状态就不能被修改,任何的修改都会创建一个新的对象 ...不可变对象好处: 1:线程安全 2:创建的对象可以做缓存处理,使用静态工厂方法valueOf()返回一个已经存在的对象
  • 最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String类为什么要设成immutable类型? 不可变对象,顾名思义就是
  • Java不可变对象(Immutable Objects)

    千次阅读 2016-01-16 00:42:26
    什么是不可变对象不可变对象(Immutable Objects)即对象一旦被创建,它的状态(即对象属性值)不能被修改。 不可变对象的类即为不可变类(Immutable Class)。Java平台类库中包含的不可变类,如String、基本类型...
  • 让我们一起来分析下原因一: 最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下用,或者更具体一点,Java的String类为什么要设置成immutable类型?不可变...
  • 在探讨为什么要将String设置为不可变对象前,先考虑不可变对象有什么好处,在什么情况下应该用。 相对于可变对象,不可变对象有很多优势: 不可变对象可以提高对象的效率和安全性。如果你知道一个对象是不可变的,...
  • 1.前一章说,我们总是因怕生成对象的开销,避免使用不可变对象 immutable object。而是用改变对象的状态,这种方式。不过呢!随着垃圾回收机制,和对synchronized的省略,不可变对象也变的更加可行。 呵呵!对于我...
  • 在前一篇文章里将了如何实现线程安全的Java程序,其中有一条就是可以通过创建不可变对象来实现!因为不可变对象默认就是线程安全的,他们一旦创建就不能发生改变!那么如何创建不可变的Java类或者对象呢?follow...
  • 对Java String不可变的理解

    千次阅读 2019-01-08 13:27:41
    不可变对象有什么好处? 1、不可变对象,顾名思义就是创建后的对象不可以改变,典型的例子有java中的String类型。注意,是对象不可变,并非引用不可变。 例如:定义并初始化一个String变量s ,s是引用类型变量,...
  • 不可变对象(immutable objects),后面文章我将使用immutable objects来代替不可变对象! 那么什么是immutable objects?什么又是mutable Objects呢? immutable Objects就是那些一旦被创建,它们
  • String类不可变以及不可变类总结

    千次阅读 2017-10-01 20:11:38
    String类在java中是immutable(不可变),因为它被关键字final修饰。当String实例创建时就会被初始化,并且以后无法修改实例信息。String类是工程师精心设计的艺术品。 一、String为什么不可变? 要了解String类...
  • 如何写一个不可变类?

    千次阅读 2016-11-26 17:24:17
    不可变对象对于缓存是非常好的选择,因为你不需要担心它的值会被更改。不可变类的另外一个好处是它自身是线程安全的,你不需要考虑多线程环境下的线程安全问题。 阅读更多: Java线程教程以及Java多线程面试问题
  • 如何让Java类不可变

    千次阅读 2015-06-09 23:20:10
    定义不可变类指南 定义不可变益处构造简单,便于测试和使用 不可变类自然是线程安全的,无需关心多线程和同步问题 不需要实现clone 可以延迟加载,缓存它的返回值 由于不可变可以用于Map的key和Set的元素(set元素...
  • Java的String类不可变好处

    千次阅读 2015-03-19 15:08:11
    java String类为什么不可变
  • 可变类和不可变类(Mutable and Immutable Objects) 1. 可变类和不可变类(Mutable and Immutable Objects)的初步定义:  可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容。  不可变类:...
  • 缓存实例的不可变

    千次阅读 2014-12-09 18:29:09
    设计不可变类的好处在于它被多个对象共享时,该类的Field不用担心被某个对象改变。当程序需要经常使用多个相同的不可变类实例时,那么可以用缓存来满足这种需求,这样可以减少系统内存的开销。Java中用不少的类是...
  • Java不可变类机制

    千次阅读 2017-02-05 11:10:34
    不可变类(Immutable Class):所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值。如JDK内部自带的很多不可变类:Interger、Long和String等。
  • Java中的String类为什么不可变

    千次阅读 2018-07-23 15:00:42
    1、什么是不可变? java角度来讲就是说成final的。 String不可变如下图: 假设给字符串s赋值为abcd,第二次重新赋值为abcdef,这时候并不是在原内存地址上修改数据,而是重新指向一个新对象,新地址。 2、...
  • python中的变量可变与不可变

    千次阅读 2017-03-13 10:32:32
    知识点:python中,万物皆对象。  python中不存在所谓的传值调用,一切传递的都是对象的...元组(tuple)、数值型(number)、字符串(string)均为不可变对象 ,而字典型(dictionary)和列表型(list)的对象是可变对
  • 为什么String在 java 中是不可变的? 这是一个受欢迎的面试问题。 字符串是任何编程语言中使用最多的类之一。...让我们来看看字符串不可变性的一些好处,这些好处有助于我们来理解为什么 String 在 java 中是不可变...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 212,375
精华内容 84,950
关键字:

不可变对象的好处