简体   繁体   English

Java - 创建包广泛或全局变量的最佳实践

[英]Java - best practice for creating package-wide or global variables

What is the standard approach/best practice to creating variables that are program- or package-wide in Java? 在Java中创建程序或包的变量的标准方法/最佳实践是什么?

I want to set up some global variables that are accessible by multiple classes. 我想设置一些可由多个类访问的全局变量。 Examples of these global variables would be things like a boolean flag testModeOn, a language setting, current local server, time display format, etc. According to some other questions (namely this one ) there aren't any global variables, but there are some work-arounds using interfaces (not recommended?) or classes. 这些全局变量的例子可能是布尔标志testModeOn,语言设置,当前本地服务器,时间显示格式等。根据其他一些问题(即这一个 ),没有任何全局变量,但有一些使用接口(不推荐?)或类的解决方法。 Since the original poster didn't explain their situation, they got nearly every answer under the sun and I want to ask specifically for program configuration variables. 由于原始海报没有解释他们的情况,他们几乎得到了阳光下的每一个答案,我想专门询问程序配置变量。

Is it better to create a class/package/interface and then import it into my working class/package? 创建类/包/接口然后将其导入我的工作类/包更好吗? Is there anything I should be aware of when trying to implement these variables using a separate class or interface? 在尝试使用单独的类或接口实现这些变量时,我应该注意什么? Is there any other way to fudge package-level variables since Java apparently doesn't do this natively? 有没有其他方法可以捏造包级变量,因为Java显然不会本地执行此操作?

NOTE: These variables would probably not change except when the program is re-compiled. 注意:除非重新编译程序,否则这些变量可能不会更改。

If you're talking about constants, then they should be declared as static final fields in a class (never in an interface, according to Joshua Bloch). 如果你在谈论常量,那么它们应该被声明为类中的static final字段(根据Joshua Bloch的说法,从不在接口中)。

If you're talking about settings which can change on the fly, then these could be either static fields in a class, or you could create a ConfigHandler class to manage the setting and fetching of configurable values. 如果您正在讨论可以随时更改的设置,那么这些设置可以是类中的static字段,也可以创建ConfigHandler类来管理可配置值的设置和获取。

Using class fields for mutable values might lead to concurrency problems, so if your application is multi-threaded it might be better to create a ConfigHandler class which manages concurrent access carefully and provides synchronized methods to avoid problems. 将类字段用于可变值可能会导致并发问题,因此如果您的应用程序是多线程的,那么最好创建一个ConfigHandler类来仔细管理并发访问,并提供synchronized方法以避免出现问题。

In my opinion, the best approach to passing anything into your classes is using dependency injection. 在我看来,将任何东西传递到您的类中的最佳方法是使用依赖注入。 This would eliminate your need for Singletons, static constants and the likes. 这将消除您对Singletons,静态常量等的需求。

Depending on which DI you favor, here are some link solutions to the problem you describe: 根据您喜欢的DI,以下是您描述的问题的一些链接解决方案:

Create a Bean class if multiple variables are required to be used in different classes. 如果需要在不同的类中使用多个变量,请创建Bean类。 Best practice is to create a private variable with its getters and setters. 最佳做法是使用getter和setter创建一个私有变量。

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

In general there are so many ways to do it wrong regarding this topic. 一般来说,有很多方法可以解决这个问题。

The simple way is to use a Singelton. 简单的方法是使用Singelton。 This is not an option - Singelton is an Anti-Pattern. 这不是一个选择 - Singelton是一个反模式。 http://c2.com/cgi/wiki?SingletonsAreEvil http://c2.com/cgi/wiki?SingletonsAreEvil

So what is else there? 那还有什么呢? An Interface with public static final variables? 具有public static final变量的接口? Not an option - Thats simply not the use case of an interface: https://stackoverflow.com/a/2659740/1248724 不是一个选项 - 这根本不是接口的用例: https//stackoverflow.com/a/2659740/1248724

so what is else there? 那还有什么呢? The answer is: 答案是:

在此输入图像描述

What I prefer is the spring boot way (eg Dependency Injection) Here an code example which is obviously Spring. 我更喜欢的是spring boot方式(例如Dependency Injection)这里有一个代码示例,显然是Spring。

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

If you are using some similar Framework such things could be easy archived. 如果您正在使用类似的框架,那么这些东西可以轻松归档。

If that is somehow not possible in your environment I had to code something like this: 如果在您的环境中以某种方式不可能,我必须编写如下代码:

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

Benefits: - You can validate your properties how ever you want. 优点: - 您可以根据需要验证您的属性。 - You can work with the java security manager if you like to - 如果您愿意,可以使用java安全管理器

Downsides: - You may have to maintain a bunch of code (this should be easier with lambda expressions) - Not that great as the way spring offers here for example. 缺点: - 您可能需要维护一堆代码(这应该更容易使用lambda表达式) - 就像Spring在这里提供的方式那样不是那么好。

A very similar approach I just found: https://stackoverflow.com/a/3931399/1248724 我发现的一种非常类似的方法: https//stackoverflow.com/a/3931399/1248724

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM