Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 静态初始值设定项的合法使用?_Java_Guava_Static Initialization_Event Bus - Fatal编程技术网

Java 静态初始值设定项的合法使用?

Java 静态初始值设定项的合法使用?,java,guava,static-initialization,event-bus,Java,Guava,Static Initialization,Event Bus,我记得几年前,我使用静态初始化器调用类级设置操作。我记得它有非常奇怪的行为,我只是决定避开它们。也许是因为我搞乱了上下订单,或者是因为我是个菜鸟。但我遇到了重新审视它们的需要,我想确保没有更好的方法可以做到同样简洁 我知道这并不流行,但我经常使用数据驱动类来维护从数据库导入的实例的静态列表 public class StratBand { private static volatile ImmutableList<StratBand> stratBands = impo

我记得几年前,我使用静态初始化器调用类级设置操作。我记得它有非常奇怪的行为,我只是决定避开它们。也许是因为我搞乱了上下订单,或者是因为我是个菜鸟。但我遇到了重新审视它们的需要,我想确保没有更好的方法可以做到同样简洁

我知道这并不流行,但我经常使用数据驱动类来维护从数据库导入的实例的静态列表

public class StratBand { 
      private static volatile ImmutableList<StratBand> stratBands = importFromDb();

      private final int minRange;
      private final int maxRange;

      private static ImmutableList<StratBand> importFromDb() { 
            //construct list from database here
      }
      //constructors, methods, etc
}
公共类StratBand{
私有静态volatile ImmutableList stratBands=importFromDb();
私有最终整数范围;
私有最终整数最大范围;
私有静态不可变列表importFromDb(){
//在这里从数据库构造列表
}
//构造器、方法等
}
当我有几十个像这样的表驱动类时,这种模式非常简洁(是的,我知道它将类与一个数据/实例源紧密耦合)

然而,当我发现GoogleGuava的优点时,我想在发布某个事件时使用EventBus来更新静态列表。我将创建一个静态的final布尔变量来调用初始化注册的静态方法

public class StratBand { 
      private static volatile ImmutableList<StratBand> stratBands = importFromDb();
      private static final boolean subscribed = subscribe();

      private final int minRange;
      private final int maxRange;

      private static ImmutableList<StratBand> importFromDb() { 
            //construct list from database here
      }
      //constructors, methods, etc

      private static boolean subscribe() {
            MyEventBus.get().register(new Object() { 
                @Subscribe
                public void refresh(ParameterRefreshEvent e) { 
                    stratBands = importFromDb();
                }
            });
        return true;
      }
}
公共类StratBand{
私有静态volatile ImmutableList stratBands=importFromDb();
私有静态final boolean subscribed=subscribe();
私有最终整数范围;
私有最终整数最大范围;
私有静态不可变列表importFromDb(){
//在这里从数据库构造列表
}
//构造器、方法等
私有静态布尔订阅(){
MyEventBus.get().register(新对象(){
@订阅
公共无效刷新(ParameterRefreshEvent e){
stratBands=importFromDb();
}
});
返回true;
}
}
这很快就会让人恼火,因为编译器会对从未使用过的订阅变量发出警告。而且,它只是增加了混乱。因此,我想知道使用静态初始值设定项是否合乎犹太教,如果我不将其解耦为两个或更多类,就没有更好的方法了。想法

 public class StratBand { 
          private static volatile ImmutableList<StratBand> stratBands = importFromDb();

          static { 
           MyEventBus.get().register(new Object() { 
                    @Subscribe
                    public void refresh(ParameterRefreshEvent e) { 
                        stratBands = importFromDb();
                    }
                });
          }

          private final int minRange;
          private final int maxRange;

          private static ImmutableList<StratBand> importFromDb() { 
                //construct list from database here
          }
          //constructors, methods, etc


    }
公共类StratBand{
私有静态volatile ImmutableList stratBands=importFromDb();
静态{
MyEventBus.get().register(新对象(){
@订阅
公共无效刷新(ParameterRefreshEvent e){
stratBands=importFromDb();
}
});
}
私有最终整数范围;
私有最终整数最大范围;
私有静态不可变列表importFromDb(){
//在这里从数据库构造列表
}
//构造器、方法等
}
所以我想知道使用静态初始值设定项是否合乎犹太教

有趣的是

private static final boolean subscribed = subscribe();

编译成完全相同的字节码。因此,使用不必要的静态变量是非常糟糕的


但在我们准备扩展到DI驱动的框架之前

发现。不要称之为框架(尽管它是)。它易于使用,让您摆脱了
静态

或者手动操作。通过删除所有静态修饰符重写类,并将其传递到任何需要的地方。有时它相当冗长,但是显式地声明依赖关系允许您单独测试类

按照这种方式,无论测试的方法多么琐碎,在不访问数据库的情况下都无法测试
StratBand
。问题是将每个
StratBand
实例耦合到所有
StratBand
s的列表

此外,您无法测试依赖于
stratBands
内容的行为,因为它总是从数据库加载(当然,您可以相应地填充数据库,但这是一个很大的难题)

首先,我会创建
StratBandManager
(或
StratBands
或任何您喜欢的名称),并将所有静态功能移动到它。为了简化转换,我创建了一个带有静态助手的临时类,如

private static StratBandManager stratBandManager = new StratBandManager();
public static ImmutableList<StratBand> stratBands() {
   return stratBandManager.stratBands();
}
私有静态StratBandManager StratBandManager=新StratBandManager();
公共静态不可变列表(){
返回stratBandManager.stratBands();
}
然后将其全部弃用并替换为DI(使用GUI或手动执行)



Guice即使对于小项目也很有用。开销很小,因为通常没有或几乎没有任何配置。

它“不流行”,正是因为,正如您所发现的,它确实会导致“非常奇怪的行为”。通常更好的做法是完全不让这些东西是静态的,在需要它们的地方显式地传递它们(或通过依赖注入隐式地传递)。静态初始值设定项在创建单例或进行纯计算时是可以的,但它们通常不应该与文件系统、数据库或任何外部的东西进行交互,真的。我正等着有人这么说。我得到了我欣赏的DI范例。但是,在我们准备扩展到DI驱动的框架之前,我希望能够将我们现有的框架保持更长的时间。您不需要在这里使用DI,但如果您能让它工作起来,我会感到惊讶,而且它仍然非常脆弱,难以测试,坦白地说,这需要比正确使用它更多的努力。在这一点上,我可能会避免使用静态初始值设定项。是的,我已经花了很多时间研究Guice,尽管我还没有应用它,我也很想应用它。考虑到我们目前的业务环境和功能,我们采取了极简主义的方法。。。我所说的极简主义意味着,如果它简化了事情,那么就要整合和减少类的数量。我一定要考虑你的过渡建议。
private static StratBandManager stratBandManager = new StratBandManager();
public static ImmutableList<StratBand> stratBands() {
   return stratBandManager.stratBands();
}