스레드 안전 선택 사양 인 지연 초기화를 요구하는 일반 기능을 작성하려고합니다. 값이 최종 값이 아니며 이미 setter를 통해 설정되었을 수 있으므로 표준 패턴을 사용할 수 없습니다.Java 7에서 패턴 생성 또는 생성 하시겠습니까?
final LazyInitializer<List<String>> value = new LazyInitializer<>(ArrayList<String>::new);
이 스레드 안전, 처리 할 수
public class LazyInitializer<T> {
protected final Supplier<T> initializer;
protected AtomicReference<T> value = new AtomicReference<>();
public LazyInitializer(final Supplier<T> initializer) {
this.initializer = initializer;
}
public T get() {
T result = this.value.get();
if (result == null) {
this.value.compareAndSet(null, this.initializer.get());
result = this.value.get();
}
return result;
}
public void setValue(final T value) {
this.value.set(value);
}
}
당신은 다음과 같이이 클래스를 사용합니다 :
자바 8 년 전 공급 업체와 LazyInitializer
일반적인를 작성하여 것으로 해결 setters는 매우 낮은 오버 헤드를 가지며 특히 : 상용구 코드가 거의 필요하지 않습니다.
그러나 Java 7을 사용하도록 강요 받았으며 Java 7이 Suppliers를 사용할 수 없으므로 추악한 코드를 많이 작성해야하므로 똑같이 우아한 솔루션을 찾을 수없는 것 같습니다. 또한 일반 클래스 값 (예 : ArrayList<String>
)을 사용하는 경우 제네릭은 정확한 클래스를 제공하지 않으면 해당 클래스를 인스턴스화 할 수 없습니다.
필자도 추한 코드를 작성하거나 내 능력을 뛰어 넘는 반사 마법을 사용하도록 강요 받았다거나, 누락 된 Java 7에서 우아한 방법으로 LazyInitializer
클래스를 작성하는 방법이 있습니까?
편집 : 다음과 같이 요른 Vernee에서 응답을 사용하여이 나는 자바 7에서 작동하도록 클래스를 수정 :
final LazyInitializer<List<String>> value = new LazyInitializer<>(ArrayList.class);
: 다음 우아 같이이라고 (다시 한번) 할 수
public class LazyInitializer<T> {
protected final Class<?> clazz;
protected AtomicReference<T> value = new AtomicReference<>();
public LazyInitializer(final Class<?> clazz) {
this.clazz = clazz;
}
public T get() {
T result = this.value.get();
if (result == null) {
this.value.compareAndSet(null, constructNew());
result = this.value.get();
}
return result;
}
public void setValue(final T value) {
this.value.set(value);
}
protected T constructNew() {
try {
return (T) clazz.newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new IllegalStateException(ex);
}
}
}
이 클래스는 제공된 클래스가 실제로 일치하는지 (Generics) 때문에 더 이상 확인할 수 없으며 기본 생성자에서만 작동합니다. 그러나 적어도 그것은 나의 경우를 해결합니다.
잘못되었거나 Java8 예제 코드의 첫 번째'this.value.get()'과 if 절을 건너 뛸 수 있습니까? – Alexander
'value == null'의 경우, 값은 초기 값으로 설정되어야합니다. 그래서, 당신은 그것을 건너 뛸 수 없습니다. – TwoThe
@TwoThe 실수로 코드가 공급자 실행을 두 번 이상 트리거 할 수 있습니까? 'compareAndSet'에 대한 매개 변수 평가가 함수 자체에 대한 원자 적 평가가 아니기 때문입니다. – chimmi