JAVA不可修改类

在面试中经常会问到关于不可变类的问题。


问题一

Q:什么是不可变(immutable)类?

A:一个对象在构建后,就不会被修改了,就是不可变类。

问题二

Q:为什么需要(immutable)类?

A:这个问题有这么两种情形,①当在多线程情况下,多个线程对一个变量同时进行访问,会造成逻辑错误,及数据本身逻辑不一致。
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就必须很小心的使用避免出现不一致的状态,假设一个线程执行了如下代码
SynchronizedRGB color =
    new SynchronizedRGB(0, 0, 0, "Pitch Black");
...
int myColorInt = color.getRGB();      //Statement 1
String myColorName = color.getName(); //Statement 2

如果另外一个线程执行了color.set在Statement 1之后但在Statement 2之前, myColorInt跟myColorName就不匹配了。 

②在HashMap这种散列表中,键的选取,必须是hashcode不会变化。假设如果出现这种情况,如果一个键值对插入了散列表中,后续键的内部属性被修改了。如果修改的内部属性会决定hash值,那么该散列表就紊乱了。所以说散列表的键通常都是String、Integer这两个都是不可变类。

不可变类需要满足的条件

  1. Don't provide "setter" methods — methods that modify fields or objects referred to by fields
  2. Make all fields final and private.
  3. Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
  4. If the instance fields include references to mutable objects, don't allow those objects to be changed:
  5. Don't provide methods that modify the mutable objects.
  6. Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值