2011-08-21 28 views
1

考慮第三方類像其他線程可以看到繼承的非final字段嗎?

class A { 
    private int value; 
    public int getValue() { 
     return value; 
    } 
    public void setValue(int value) { 
     this.value = value; 
    } 
} 

我讓一成不變像

final class ImmutableA extends A { 
    public ImmutableA(int value) { 
     super.setValue(value); 
    } 
    public void setValue(int value) { 
     throw new UnsupportedOperationException(); 
    } 
} 

visibility guarantee for final fields在這裏並不適用。我的問題是,如果其他線程保證看到ImmutableA的正確狀態。

如果沒有,是否有解決方案?使用委派不是一種選擇,因爲我需要ImmutableAA

回答

0

你可以使用​​,雖然這可能在吸氣慢下來:

final class ImmutableA extends A 
{ 
    public ImmutableA(int value) { 
     synchronized (this) { 
      super.setValue(value); 
     } 
    } 

    public void setValue(int value) { 
     throw new UnsupportedOperationException(); 
    } 

    public synchronized int getValue() { 
     return super.getValue(); 
    } 
} 
1

是的,如果你使用volatile這有寫它的保障是可見的其他線程

class A { 
    private volatile int value; 
    public int getValue() { 
     return value; 
    } 
    public void setValue(int value) { 
     this.value = value; 
    } 
} 
+0

對不起,我應該更清楚地提到這一點:'A'是我不能修改的第三方類。 – maaartinus

+0

另一種在構造函數中添加同步塊的方式,但這只是解決方案的一半,如果使用external [發生前](http://download.oracle.com/javase/6/docs/api/java/ util/concurrent/package-summary.html#MemoryVisibility)保證那麼它是可見的 –

0

受starblue的回答啓發,我找到了一個不使用同步的解決方案。它結合了代表團繼承:

final class ImmutableA extends A { 
    private final ImmutableA that; 

    public ImmutableA(int value) { 
     super.setValue(value); 
     that = this; 
    } 

    public void setValue(int value) { 
     throw new UnsupportedOperationException(); 
    } 

    private int superGetValue() { 
     return super.getValue(); 
    } 

    public int getValue() { 
     return that.superGetValue(); 
    } 
} 

我想應該是因爲final知名度保證工作。但我不認爲這是值得的麻煩。所有的方法都需要重寫和重複,因爲那個.getValue()會導致無限遞歸,並且that.super.getValue()(或super.that.getValue())是非法的。