`
luccs624061082
  • 浏览: 84479 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Immutable Objects 不可变对象

阅读更多
  如果一个对象在创建后它的状态不可变那这个对象被认为是不可变的。对于不可变对象的极大信任使它作为一个合理的策略来创建简单信任的代码而被广泛认可。

  不可变对象在并发程序中十分有用。因为它们不能改变状态,它们不会在线程争用中毁坏或者在不一致性错误中被观察。

   程序通常不情愿使用不可变对象,因为他们担心创建一个新的对象的成本与适当的时候更新一个对象的成本截然相反。创建对象的影响通常被过高评估,会抵消与不可变量有关联的效率。这些由于垃圾收集而减少开销和代码消除,需要它去防止可变对象变坏。

   下面的子章节演示了谁的实例是可变的并从它衍生出不可变实例的一课。这样做,它们为这种转换给出了一般的规则并且展示了不可变对象的一些优点。


   A Synchronized Class Example ---一个同步类的例子

   这个类,SynchronizedRGB,定义了颜色对象。每个对象作为三个整形,表示了基本颜色值和给定颜色名字的字符串。
  
   public class SynchronizedRGB {

    // Values must be between 0 and 255.
    private int red;
    private int green;
    private int blue;
    private String name;

    private void check(int red,
                       int green,
                       int blue) {
        if (red < 0 || red > 255
            || green < 0 || green > 255
            || blue < 0 || blue > 255) {
            throw new IllegalArgumentException();
        }
    }

    public SynchronizedRGB(int red,
                           int green,
                           int blue,
                           String name) {
        check(red, green, blue);
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.name = name;
    }

    public void set(int red,
                    int green,
                    int blue,
                    String name) {
        check(red, green, blue);
        synchronized (this) {
            this.red = red;
            this.green = green;
            this.blue = blue;
            this.name = name;
        }
    }

    public synchronized int getRGB() {
        return ((red << 16) | (green << | blue);
    }

    public synchronized String getName() {
        return name;
    }

    public synchronized void invert() {
        red = 255 - red;
        green = 255 - green;
        blue = 255 - blue;
        name = "Inverse of " + name;
    }
}

  SynchronizedRGB 必须小心使用以防在一个不一致状态下被看见。例如,一个线程执行了以下代码:

  SynchronizedRGB color =
    new SynchronizedRGB(0, 0, 0, "Pitch Black");
  ...
  int myColorInt = color.getRGB();      //Statement 1
  String myColorName = color.getName(); //Statement 2


另一个线程在Statement 1之后在Statement 2之前调用了color.set方法,myColorInt 的值将不会与myColorName的值匹配。为避免这种结果,那两个语句必须绑定在一起。

   synchronized (color) {
    int myColorInt = color.getRGB();
    String myColorName = color.getName();
   }

  这种不一致性仅仅可能发生在可变对象上----对于不可变版本的SynchronizedRGB将不是问题。


  A Strategy for Defining Immutable Objects 定义不可变对象的策略
 
  下面的规则定义了一个简单策略来创建不可变对象。不是所有的类按照下面规则表明是不可变的。这也不一定意味着这些规则的制定者是草率的---他们也许有更好的原因相信他们类的实例在构建后从不改变。然而,这样的策略需要复杂的分析并不合适新手。

  1。 不要提供setter方法---方法修改字段或者与字段相关联的对象。
  2。 是所有字段是final和private
  3。 不允许子类重写方法。最简单的方法是这样做用fianl声明类。更复杂方式是使构造方法为私有的并通过工厂方法创建实例。
  4.如果字段包含的实例与可变对象关联,不允许这些对象改变。
      不提供方法修改可变对象
      不共享可变对象的引用。从不保存表面的,可变对象的引用,这些对象将传递给构造函数。如果必须,创建复制,保存复制的引用。相似的,在必要时创建你的内部可变对象的复制以避免在你的方法中返回原始值。

  按照下面步骤对SynchronizedRGB 使用这种策略的结果:

  1 在这个类中有两个setter方法。第一个,设置,任意转换对象。在这个类中没有可变版本。第二个,转换,通过创建一个新的对象代替修改已经存在的可以适应。
  2 所有字段是私有的,进一步用final限制。
  3 类自身申明为final
  4 只有一个对象与字段关联,那个对象自身是不可变的。因此,没有防范改变”contained“可变对象的状态是没有必要的。

  经过这些改变,有了ImmutableRGB:

  final public class ImmutableRGB {

    // Values must be between 0 and 255.
    final private int red;
    final private int green;
    final private int blue;
    final private String name;

    private void check(int red,
                       int green,
                       int blue) {
        if (red < 0 || red > 255
            || green < 0 || green > 255
            || blue < 0 || blue > 255) {
            throw new IllegalArgumentException();
        }
    }

    public ImmutableRGB(int red,
                        int green,
                        int blue,
                        String name) {
        check(red, green, blue);
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.name = name;
    }


    public int getRGB() {
        return ((red << 16) | (green << | blue);
    }

    public String getName() {
        return name;
    }

    public ImmutableRGB invert() {
        return new ImmutableRGB(255 - red,
                       255 - green,
                       255 - blue,
                       "Inverse of " + name);
    }
}

  
分享到:
评论

相关推荐

    不可变对象ImmutableXXX:Collection、List、Set、Map…

    在Java编程中,不可变对象(Immutable Objects)是一种一旦创建后就不能被修改的对象。这种特性在多线程环境中尤其重要,因为不可变对象是线程安全的,它们不会因为并发修改而引发数据不一致的问题。Guava库是Google...

    ImmutableObjects

    在Java编程语言中,不可变对象(Immutable Objects)是一个重要的概念,尤其是在构建健壮、易于维护的应用程序时。本篇将基于提供的文件内容来深入探讨不可变对象的概念及其在Java中的应用。 #### 不可变对象定义 ...

    java多线程设计

    本知识点将深入探讨Java多线程设计以及如何利用“不可变对象”(immutable objects)来避免多线程环境中的非安全问题。 一、Java多线程基础 1. 线程的创建:Java提供了两种创建线程的方式——继承Thread类和实现...

    JAVA变还是不变1

    Java标准库中的String、Integer和BigDecimal类就是不变对象的典型例子,它们分别表示不可变的字符串、整数和大数。 1. **简化编程**:由于不变对象只能处于一种状态,它们在正确初始化后就不会进入不一致的状态。这...

    effectice_java第二版 英文

    14. **条目14:优先考虑使用不可变对象( Prefer Immutable Objects)** 不可变对象简化并发编程,减少错误,并且可以作为线程安全的缓存项。 15. **条目15:最小化可变对象的范围(Minimize Mutability)** 尽...

    php-data:事件引擎的不可变对象

    轻松生成不可变对象! 安装 composer require event-engine/php-data 版本号 1.x使用方法返回类型提示来检测ImmutableRecord属性类型在PHP 7.2-PHP 7.3环境中使用此版本 2.x利用PHP 7.4属性类型提示在&gt; = PHP 7.4...

    JAVA面试题汇总.pdf

    11. 在 Java 中不可变对象(Immutable Objects): - 一旦被创建,状态不能改变。 - 优点是线程安全。 - 示例:String、Integer。 12. Java 中的 switch 语句: - 在 JDK 1.7 之后支持 String 类型参数。 13. ...

    麻省理工18年春软件构造课程阅读09-避免调试-1

    4. **不可变对象(Immutable Objects)**:不可变对象在其创建后无法改变状态。在Java中,字符串是不可变的,这意味着一旦创建,就不能更改其内容。 5. **断言(Assertions)**:Java中的断言机制(`assert`关键字...

    Java 并发核心编程

    不可变字段与对象(Final fields & Immutable objects) 不可变字段(final fields)在对象创建后必须被赋予一个值,此后其值不可更改。不可变字段的设定值对所有线程可见,即使在无同步的情况下也是如此。不可变...

    java并发核心编程

    8. **不可变对象 (Immutable Objects)**: - **描述**:不可变对象是指一旦创建就不能被改变的对象。在Java中,可以通过将对象的所有字段声明为`final`来创建不可变对象。不可变对象是线程安全的,因为它们的状态...

    麻省理工18年春软件构造课程阅读12-接口与枚举-1

    此外,还提到了不可变对象(Immutable Objects)的概念,例如`ImmutableSquare`和`ImmutableRectangle`。不可变对象一旦创建就不能改变其状态,它们提供了安全性和并发性优势。`ImmutableSquare`继承自`...

    java oracle并发官方教程

    ### 不可变对象(Immutable Objects) 在并发编程中,不可变对象是不可更改的对象,一旦创建了它的实例,就不能修改它的状态。不可变对象可以提供线程安全保证,因为它们的状态不会在多个线程间改变。 ### 高级...

    深拷贝拷贝的是内容,浅拷贝拷贝的是指针

    - 主要适用于不可变对象(immutable objects),因为这些对象一旦创建就不会发生改变。 - 在C++中,浅拷贝可以通过调用`copy()`方法实现;而在Python等语言中,可以通过`copy`模块提供的`copy()`函数来实现。 ###...

    effective-java 配套代码

    4. **可变与不可变对象(Mutable vs Immutable Objects)**: 通过示例代码展示了如何创建不可变对象,以及不可变对象的益处和实现策略。 5. **泛型(Generics)**: 书中深入讲解了Java泛型的用法,包括类型擦除、...

    Practical+Java(重点版)

    - **创建不可变对象**:另一种方法是设计不可变对象(Immutable Objects)。这意味着一旦对象被创建,它的状态就不能被更改。这通常通过使对象的所有字段成为final并且不允许任何外部修改操作来实现。这种方式可以...

    关键字Final

    2. **不可变对象(Final Objects)** 当一个对象引用被声明为`final`时,引用本身不能被重新分配,但对象内部的状态仍然可以改变,只要对象的修改不违反其封装性。如果希望整个对象保持不变,需要确保对象的所有...

    Unlimited-objects

    另外,Java的`Immutable Object`(不可变对象)也与"无限对象"的概念有关。不可变对象一旦创建完成,其状态就不能再改变,这使得它们可以被安全地共享,减少了复制对象的需要,从而提高了效率。例如,`String`类就是...

    Java理论与实践:描绘线程安全性

    首先,我们来看不可变对象(Immutable Objects),这类对象一旦创建,其状态就不能改变,因此它们天然地线程安全。例如,`java.lang.String`就是不可变的,多个线程可以安全地共享同一个字符串实例。 其次,线程...

    ippo:不可变,静态类型,可克隆和可序列化的自动生成的纯老式PHP对象

    国际植保组织 不可变- with s一起使用with而不是setter 静态类型-您的工具喜欢它可克隆-没有参考共享可序列化-JSON,数组和字符串―自动生成的普通PHP对象。 :shield: 在其最严格的级别上验证lib的源代码及其生成的...

    不可变的:注释处理器,用于创建不可变的对象和构建器。 感觉像番石榴的不可变集合,但对于常规值对象。 包括JSON,Jackson,Gson,JAX-RS集成

    阅读完整的文档,为 // Define abstract value type using interface, abstract class or annotation@Value . Immutablepublic interface ValueObject extends WithValueObject { // extend not-yet-generated ...

Global site tag (gtag.js) - Google Analytics