문제
최종 필드를 게으르게 인스턴스화 할 수 있습니까?
다음 코드는 컴파일되지 않습니다.
public class Test{
private final Connection conn;
public Connection getConnection(){
if(conn==null){
conn = new Connection();
}
return conn;
}
}
대안이 있습니까?
해결책 2
다음은 MEMOISATION (Callables 포함)을 사용하여 수행 할 수있는 한 가지 방법입니다.
클래스 메모 :
public class Memo<T> {
private T result;
private final Callable<T> callable;
private boolean established;
public Memo(final Callable<T> callable) {
this.callable = callable;
}
public T get() {
if (!established) {
try {
result = callable.call();
established = true;
}
catch (Exception e) {
throw new RuntimeException("Failed to get value of memo", e);
}
}
return result;
}
}
이제 우리는 마지막 코를 만들 수 있습니다!
private final Memo<Connection> conn = new Memo<Connection>(
new Callable<Connection>() {
public Connection call() throws Exception {
return new Connection();
}
});
public Connection getConnection() {
return conn.get();
}
다른 팁
아닙니다. 최종 필드의 요점은 건설 중에 한 번 설정되어 그 이후로 변하지 않을 것입니다. 컴파일러 나 VM이 어떻게 유용한 것을 알 수 있습니까? conn
당신의 경우? 그 속성만이 다른 방법이 아니라 설정을 설정할 수 있어야한다는 것을 어떻게 알 수 있습니까?
아마도 당신이 의미론을 원하는 것을 설명했다면, 우리는 변화를 일으킬 수 있습니다. 잠재적으로 값을 가져 오는 방법을 나타내는 "제공자"인터페이스를 가질 수 있습니다. MemoizingProvider
다른 공급자에게 프록시가되지만 한 번만 값을 캐싱합니다. 그것은 캐시 된 값에 대한 최종 필드를 가질 수는 없지만 적어도 한 곳에있을 것입니다.
Dhiller의 답변은 클래식 한 더블 점검 잠금 버그입니다. 사용하지 마세요.
Jon Skeet이 말했듯이, 그렇지 않습니다.
코드 샘플 해석 : 다음과 같은 작업을 수행 할 수 있습니다.
public class Test{
private final Object mutex = new Object(); // No public locking
private Connection conn;
public Connection getConnection(){
if(conn==null){
synchronized (mutex) {
if(conn==null){
conn = new Connection();
}
}
}
return conn;
}
}
참고로 최종 필드를 변경할 수 있습니다. 적어도 인스턴스 필드. 당신은 약간의 반성이 필요합니다 :
import java.lang.reflect.Field;
public class LazyFinalField {
private final String finalField = null;
public static void main(String[] args) throws Exception {
LazyFinalField o = new LazyFinalField();
System.out.println("Original Value = " + o.finalField);
Field finalField = LazyFinalField.class.getDeclaredField("finalField");
finalField.setAccessible(true);
finalField.set(o, "Hello World");
System.out.println("New Value = " + o.finalField);
}
}
Original Value = null
New Value = Hello World
제휴하지 않습니다 StackOverflow