【问题标题】:Java - best practice for creating package-wide or global variablesJava - 创建包范围或全局变量的最佳实践
【发布时间】:2014-06-22 11:14:23
【问题描述】:

在 Java 中创建程序或包范围的变量的标准方法/最佳实践是什么?

我想设置一些可供多个类访问的全局变量。这些全局变量的示例包括布尔标志 testModeOn、语言设置、当前本地服务器、时间显示格式等。根据其他一些问题(即this one),没有任何全局变量,但有一些使用接口(不推荐?)或类的解决方法。由于原始发帖人没有说明他们的情况,他们几乎得到了所有答案,我想专门询问程序配置变量。

创建一个类/包/接口然后将其导入我的工作类/包是否更好?尝试使用单独的类或接口实现这些变量时,我应该注意什么?有没有其他方法可以伪造包级别的变量,因为 Java 显然本身并不这样做?

注意:除非重新编译程序,否则这些变量可能不会改变。

【问题讨论】:

  • 单例模式。
  • “单例模式”是指我应该创建一个只创建一个实例/对象的类?
  • @Smutje 没办法。永远不要使用单机 c2.com/cgi/wiki?SingletonsAreEvili.stack.imgur.com/Dzdio.png
  • @Zarathustra “不要实例化第二个实例。”很好,我认为从来没有处理过现实生活中的问题——有时最好强制执行某事,而不是“抱最好的希望”。
  • @Smutje 我不同意单例模式在这里是相关的。使用static 字段意味着根本不需要创建对象实例,因此甚至不需要 Singleton 对象。

标签: java variables global-variables


【解决方案1】:

如果您在谈论常量,那么它们应该在类中声明为 static final 字段(根据 Joshua Bloch 的说法,永远不要在接口中)。

如果您谈论的是可以即时更改的设置,那么这些可以是类中的static 字段,或者您可以创建一个 ConfigHandler 类来管理设置和获取可配置值。

对可变值使用类字段可能会导致并发问题,因此如果您的应用程序是多线程的,最好创建一个 ConfigHandler 类来仔细管理并发访问并提供synchronized 方法以避免出现问题。

【讨论】:

  • 除非重新编译程序,否则这些变量可能不会改变,所以我不太担心可变性问题,但我会记住它们。
  • 那么这些值是常量,在适当的类的顶部将这些值定义为static final 将是最好的方法。不要忘记 final 不会阻止 Collection 或 Array 的内容被修改,因此您可能需要查看 java.util.Collections class 的文档,该文档提供了一组名为 unmodifiableXxxx 的方法,可让您创建执行以下操作的 Collection 对象不允许重新排列它们的内容。
  • 我想我将主要使用整数、字符串和布尔值,但我会看一下集合和数组文档。我倾向于在我的程序中大量使用数组,所以我可能需要在这个类中添加一个注释,以提醒自己在将来某个时候使用数组时要注意可变性。谢谢!
  • 既然这个类只存在保存我的配置变量,我是否也将这个类声明为static final?我将如何引用此类中的变量 - MyClass.myStaticField
  • 一个类不能是static 所以不用担心。你是对的,你使用类的名称引用静态字段。请参阅Understanding Class Members 以获得更完整的解释。
【解决方案2】:

在我看来,将任何内容传递到类中的最佳方法是使用依赖注入。这将消除您对单例、静态常量等的需求。

根据您喜欢的 DI,以下是您描述的问题的一些链接解决方案:

【讨论】:

    【解决方案3】:

    如果需要在不同的类中使用多个变量,则创建一个 Bean 类。最佳实践是用它的 getter 和 setter 创建一个私有变量。

    public class ListBean implements Serializable
    {
        private boolean testModeOn;
        public boolean getTestModeOn()
        { 
           return testModeOn;
        }
        public setTestModeOn(boolean testModeOn)
        {
            this.testModeOn = testModeOn;
        }
    

    【讨论】:

      【解决方案4】:

      总的来说,关于这个话题有很多方法可以做错。

      简单的方法是使用 Singelton。 这不是一种选择——Singelton 是一种反模式。 http://c2.com/cgi/wiki?SingletonsAreEvil

      那么还有什么?带有public static final 变量的接口? 不是一个选项 - 那根本不是接口的用例:https://stackoverflow.com/a/2659740/1248724

      那么还有什么? 答案是:

      我更喜欢的是spring boot方式(例如依赖注入) 这是一个明显是 Spring 的代码示例。

      import org.springframework.stereotype.*
      import org.springframework.beans.factory.annotation.*
      @Component
      public class MyBean {
       @Value("${name}")
       private String name;
       // ...
      }
      

      如果您使用一些类似的框架,则可以轻松存档。

      如果这在您的环境中无法实现,我必须编写如下代码:

      public final class Configuration {
      
      private Configuration() {
          // make sure there is no instance of this class
      }
      
          public static final MySetting<DateFormat>   setting = new SampleProperty();
      
          public interface MySetting<T> {
              T get();
          }
      
          private static final class SampleProperty implements MySetting<DateFormat> {
      
              @Override
              public DateFormat get() {
                  return new SimpleDateFormat("...");
              }
      
          }
      
          // other inner classes that implement the MySetting interface
      }
      
      public static void main(final String[] args) {
           Configuration.setting.get();
      }
      

      好处: - 您可以随心所欲地验证您的属性。 - 如果您愿意,可以使用 java 安全管理器

      缺点: - 您可能需要维护一堆代码(这应该使用 lambda 表达式更容易) - 例如,这里没有春天提供的方式那么好。

      我刚刚发现的一个非常相似的方法:https://stackoverflow.com/a/3931399/1248724

      【讨论】:

      • 虽然这可能是避免使用单例的好建议,但您实际上并没有在这里提供替代答案。这张图表只告诉我我不应该使用单例。既然你已经排除了其他可能性,我应该假设你建议使用一个类吗?
      • “建议使用类”是指“建议使用普通类”。
      • 看来你是在表达你对单身人士的仇恨,而不是真正提供答案。单例模式是一种公认​​的模式,与任何其他设计模式一样,当以不正确的方式/位置使用时,它“可能是邪恶的”。您最好正确了解该模式并了解在哪里使用和在哪里不使用,而不是一概拒绝!
      • @mohamnag 这里是另一个很好的结论.. dzone.com/articles/what-the-singleton-pattern-costs-you
      • @Zarathustra 抱歉,但 DZone 非常商业化,我宁愿不将其用作参考。就像这里当他将单例与现场注入进行比较并得出结论比前者更好的OO时一样!!!
      猜你喜欢
      • 1970-01-01
      • 2018-04-18
      • 2019-12-19
      • 1970-01-01
      • 2013-03-15
      • 2017-02-17
      • 1970-01-01
      • 2015-07-05
      • 1970-01-01
      相关资源
      最近更新 更多