:
class Foo
{
final Object param;
final Foo other;
Foo(Object param, Foo other)
{
this.param = param;
this.other = other;
}
// create a pair of Foo's, A=this, B=other
Foo(Object paramA, Object paramB)
{
this.param = paramA;
this.other = new Foo(paramB, this);
}
Foo getOther(){ return other; }
}
// usage
Foo fooA = new Foo(paramA, paramB);
Foo fooB = fooA.getOther();
// publish fooA/fooB (unsafely)
질문이 fooA
의 this
는 생성자 내부에서 유출되어 있기 때문에, 여전히 불변 스레드 안전 fooA
입니다입니까? 즉, 다른 스레드가 fooB.getOther().param
을 읽으면 paramA
이 표시됩니까? 대답은 예입니다. 동결 조치 전에 this
이 다른 스레드로 유출되지 않았으므로 예입니다. 우리는 paramA
이 읽을 수있는 유일한 가시 값임을 증명하기 위해 사양에 필요한 hb/dc/mc 주문을 수립 할 수 있습니다.
원래 질문으로 돌아 가기. 실제로는 순수한 기술적 인 것 이상의 제약이 있습니다. 모든 엔지니어링, 운영, 정치 및 기타 인간의 이유를 고려하여 생성자 내부의 모든 것을 초기화하는 것이 반드시 설계를위한 최상의 옵션은 아닙니다.
우리가 왜 그것이 최고의 생각이라고 생각하게되었는지 궁금한가요?
더 깊은 문제는 Java입니다. 에는이 부족합니다. 휘발성보다 비용이 적게 드는 안전한 발행을 위해 일반적으로 저렴한 가격입니다. Java는 final
필드에만 있습니다. 웬일인지, 울타리는 그렇지 않으면 이용할 수 없다.
이제 final
은 두 가지 독립적 인 의미를 전달합니다. 첫째, 최종 필드가 정확히 한 번 지정되어야합니다. 둘째, 안전한 출판의 기억 의미론. 이 두 가지 의미는 서로 관련이 없습니다. 그것들을 함께 묶는 것은 매우 혼란 스럽습니다. 사람들이 제 2의 의미를 필요로 할 때, 제 1의 의미도 받아 들여야합니다. 1 위가 디자인에서 달성하기가 매우 불편할 때 사람들은 자신이 잘못한 것을 궁금해 할 것입니다. Java가 잘못되었다는 사실을 깨닫지 못합니다.
final
에서 두 개의 의미를 묶어 두 번 더하기 좋게 만듭니다. 따라서 분명히 더 많은 이유와 동기가 있습니다. final
. 더 불길한 이야기는 실제로 우리가 더 유연한 선택을 할 수 없기 때문에 그것을 사용해야 만합니다.
이 접근법의 예가 있습니까? – user77115