【问题标题】:How to initialize a static variable only when at least one instance has been created如何仅在至少创建一个实例时才初始化静态变量
【发布时间】:2018-06-14 19:02:13
【问题描述】:

假设我有一个包含两个静态最终变量的类,其中一个由另一个类导入。例如,

// File 1
import static com.company.Dependency.y;

class Import {
    // Some code...
}

// File 2
class Dependency {
    public static final Something y = new Something();
    private static final Otherthing x = new Otherthing();

    // Some code...
}

在两个静态字段中,x 仅与类 Dependency 的实例相关,例如 Dependency 对象的数量,并且初始化成本很高。我不想初始化x,除非至少实例化了一个依赖类的实例。但在这种情况下,import static 语句会意外触发x 的初始化。处理这种情况的最佳做法是什么?

这是我当前的实现。不幸的是,它没有保留 x 的最终属性:

class Dependency {
    public static final Something y = new Something();
    private static Otherthing x = null;

    public Dependency() {
        if (Dependency.x == null) {
            x = new Otherthing();
        }
    }
}

【问题讨论】:

  • 创建字段private,忽略它不是final,写一个static getter。请记住,您当前的实现不是线程安全的。
  • 因为可以从多个线程调用构造函数,您可能还需要考虑同步检查和分配x 的代码。

标签: java import static initialization


【解决方案1】:

你可以使用辅助类。

虽然在语法上可能不是更可取,但您可以保留您的成员static final

class Demo {
    private static final Something something = new Something();

    public Demo() {
        Helper.x.doSomething();
    }

    private static final class Helper {
        private static final Otherthing x = new OtherThing();
    }
}

class Otherthing {
    public void doSomething() { }
}

class Something { }

通过将打印语句添加到每个类型的构造函数的顶部,运行如下:

Class c = Demo.class; // loads the class
Demo demo = new Demo();

结果:

Something constructor was called!
Demo constructor was called!
Otherthing constructor was called!

【讨论】:

    【解决方案2】:

    我会考虑这样的工厂方法

    public class Dependency {
        private static Dependency xHolder;
    
        public static synchronized Dependency get() {
            if( xHolder == null ) xHolder = new Dependency();
            return xHolder;
        }
    

    但我也会考虑使用第二个内部类来实现,这将消除显式同步的需要,也可以设为final

    public class Dependency {
        private static class Holder {
           static final Dependency x = new Dependency();
        }
    
        public static Dependency get() {
            return Holder.x;
        }
    

    【讨论】:

    • 这仍然让他在班上留下了一个非最终成员,他可以通过他目前的方法来实现。
    • 哦,我想第二种方式也可以设为final。我会更新的。
    【解决方案3】:

    最简单的方法是将 x 保存在静态依赖对象中,该对象仅在需要时创建。然后,您可以使用静态方法从静态依赖对象返回 x。构造函数是私有的,以防止在 Dependency 类之外创建 Dependency 对象。

    public class Dependency {
        public static final Something y = new Something();
        private static Dependency xHolder;
    
        /*
         * Call this to get x, creating it if necessary.
         */
        public static Otherthing getX() {
            if(xHolder == null) {
                xHolder = new Dependency();
            }
            return xHolder.x;
        }
    
        private final Otherthing x = new Otherthing();
        private Dependency(){
    
        }
    
    }
    

    【讨论】:

    • 他的变量不能是final 使用这种方法。他想将变量声明为final。他已经有了一个非最终的方法。
    猜你喜欢
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多