Immutable对象

来源:互联网 发布:mac彻底删除音乐创作 编辑:程序博客网 时间:2024/05/22 06:18

翻译自Oracle教程。http://docs.oracle.com/javase/tutorial/essential/concurrency/syncrgb.html

我们先来定义一个表示颜色的类,

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 << 8) | 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 color =    new SynchronizedRGB(0, 0, 0, "Pitch Black");...int myColorInt = color.getRGB();      //Statement 1String myColorName = color.getName(); //Statement 2

如果你在语句1和语句2之间有个线程调用setter方法改变颜色的RGB值,那么输出的颜色值和名称就会不匹配。

怎么解决呢?简单的方法是使用同步。

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


还有一种从设计上根除的方法,就是构造一个不可变类 (Immutable Object)。

下面给出简单的策略。虽然有些Immtuable类不完全符合这些策略,但这并不意外着他们不仔细,因为他们有理由确保它们的实例不会在构造后被修改。

  • 不提供setter方法
  • 使所有的属性为private和final
  • 不允许子类重写方法。最简单的方法是将类声明为final,但更好的做法是使构造函数私有,然后提供一个提供实例的工厂方法
  • 如果实例的属性包含对可变对象的引用,不能允许这些对象被修改不提供修改可变对象的方法;不共享对可变对象的引用;不要保存引用外部的变量,不要保存传递到构造器的可变对象;如果 必要的话,创建拷贝在保存。


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 << 8) | blue);    }    public String getName() {        return name;    }    public ImmutableRGB invert() {        return new ImmutableRGB(255 - red,                       255 - green,                       255 - blue,                       "Inverse of " + name);    }}


0 0
原创粉丝点击