문제

최종 필드를 게으르게 인스턴스화 할 수 있습니까?

다음 코드는 컴파일되지 않습니다.

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top