Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.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_Singleton_Constants - Fatal编程技术网

Java 实现一个“类”;常数“;在应用程序启动时初始化,而不是在编译时初始化

Java 实现一个“类”;常数“;在应用程序启动时初始化,而不是在编译时初始化,java,singleton,constants,Java,Singleton,Constants,我正在从事一个Java项目,该项目使用一大类常量,如: public final class Settings { public static final int PORT_1 = 8888; public static final int PORT_2 = 8889; ... } 现在,这些常量的某些值在编译时不再可用,因此我需要一种在应用程序启动时“初始化”它们的方法(例如,从args[])。一旦初始化,就应该没有办法更改它们。我对java不是很熟练,如何以一种可接

我正在从事一个Java项目,该项目使用一大类常量,如:

public final class Settings {
    public static final int PORT_1 = 8888;
    public static final int PORT_2 = 8889;
    ...
}
现在,这些常量的某些值在编译时不再可用,因此我需要一种在应用程序启动时“初始化”它们的方法(例如,从args[])。一旦初始化,就应该没有办法更改它们。我对java不是很熟练,如何以一种可接受的方式做到这一点


我曾想过使用一个类似于“一次性”集合方法的单例,如果多次调用就会抛出异常,但它太粗糙了……

好吧,除非有大量常量,否则使用系统属性是一种方法

private static final String CONSTANT1 = System.getProperty("my.system.property");
private static final int CONSTANT2 = Integer.valueOf(System.getProperty("my.system.property"));
使用
-D
标志启动应用程序时,会在命令行上传递系统属性

如果变量太多,则可以使用静态初始值设定项来读取包含属性的属性文件或类似文件:

public class Constants {
    private static final String CONSTANT1 = System.getProperty("my.system.property");
    private static final int CONSTANT2 = Integer.valueOf(System.getProperty("my.system.property"));
    private static final String CONSTANT3;
    private static final String CONSTANT4;

    static {
        try {
            final Properties props = new Properties();
            props.load(
                new FileInputStream(
                        System.getProperty("app.properties.url", "app.properties")));

            CONSTANT3 = props.getProperty("my.constant.3");
            CONSTANT4 = props.getProperty("my.constant.3");
        } catch (IOException e) {
            throw new IllegalStateException("Unable to initialize constants", e);
        }
    }
}

请注意,如果您使用一些外部框架,例如Spring框架或类似的框架,通常会有一个内置的机制来实现这一点。例如,Spring框架可以通过
@Value
注释从属性文件中注入属性。

在Java中没有简单的方法可以做到这一点。模拟这种情况的一种方法是使用一个生成器,它返回一个内部类型(这样它就可以编写私有字段),但内部类型只有getter


查看以下答案:

您可以使用如下静态初始值设定项:

public final class Settings {
  public static final int PORT_1;
  public static final int PORT_2;
  ...

  static {
    // create the value for PORT_1:
    PORT_1 = ...;
    // create the value for PORT_2:
    PORT_2 = ...;
  }
}

静态初始值设定项在类加载期间执行。
PORT_1
PORT_2
上的最后一个关键字保护它们在以后更改

final
变量只能分配一次。您可以从
args[]
中分配它们一次。这些常量非常完美,在jvm的生命周期中永远不会更改。您为什么考虑使用Singleton?@marounnaroun如果args[]不是静态的,并且在我的主类中,我可以分配它们,但是如果它们在设置类中,我该怎么做?我不能在那里不分配它们,或者它甚至不会编译这看起来很有希望,但我如何告诉静态初始化器使用用户插入的值作为应用程序参数?@flagg19读取静态初始化块中用户的设置(我假设是一个文件、数据库记录、一组首选项节点等)。我看到。。。谢谢,但假设我得到所有这些值作为命令行参数?我真的应该将它们写在一个文件或首选项上,以便能够在静态初始值设定项中读取它们吗?这不是一个很常见的需求,还是我在做一些奇怪的事情?这是一个常见的情况,但通常用户设置不会在命令行中指定。通常,用户通过用户界面进行设置,您的程序保存它们,然后在以后的启动过程中,程序读取保存的信息。这会起作用,也是最简单的解决方案。atm I大约有10个常量需要这样设置,但它们可能会增加到20个左右。这被认为是一种良好的做法还是至少可以接受?jar文件将由一个bash脚本启动,所以我并不介意它是一行还是太大。这绝对是一种可以接受的方法。但是,常数的数量很多,我相信其他方法更好。一种方法是使用静态初始值设定项并在我添加到答案时从文件中读取数据(以便能够外部化常量)。