代码之家  ›  专栏  ›  技术社区  ›  dogbane

惰性地实例化最后一个字段

  •  2
  • dogbane  · 技术社区  · 16 年前

    是否可以懒洋洋地实例化最后一个字段?

    以下代码未编译:

    public class Test{
        private final Connection conn;
    
        public Connection getConnection(){
            if(conn==null){
                conn = new Connection();
            }
            return conn;
        }
    }
    

    5 回复  |  直到 16 年前
        1
  •  8
  •   Jon Skeet    16 年前

    不。最后一个字段的要点是,它在构建期间设置一次,此后将永远不会更改。编译器或虚拟机如何知道任何有用的信息 conn 对你来说?它怎么知道只有该属性才能设置它,而不能设置其他方法?

    也许如果你解释一下你想要的语义是什么,我们可以想出一个替代词。您可能有一个“provider”接口,表示获取值的方法,然后是 MemoizingProvider

        2
  •  3
  •   dogbane    14 年前

    这里有一种方法可以使用备忘录(带可调用项)实现:

    课程备忘录:

    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();
    }
    

    Source

        3
  •  1
  •   james    16 年前

    不要使用。

        4
  •  0
  •   Daniel Hiller    16 年前

    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;
        }
    }
    
        5
  •  0
  •   jassuncao    16 年前

    作为旁注,可以更改最后一个字段。至少包含实例字段。你只需要思考一下:

    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