Java:在不消耗内存的情况下拥有一长串需要的变量的最佳方法?

Java:在不消耗内存的情况下拥有一长串需要的变量的最佳方法?,java,memory-management,Java,Memory Management,我编写了一个抽象类来包含应用程序的所有规则,因为在我的应用程序中几乎所有地方都需要它们。所以它包含的大部分是静态final变量,如下所示: public abstract class appRules { public static final boolean IS_DEV = true; public static final String CLOCK_SHORT_TIME_FORMAT = "something"; public static final String

我编写了一个抽象类来包含应用程序的所有规则,因为在我的应用程序中几乎所有地方都需要它们。所以它包含的大部分是
静态final
变量,如下所示:

public abstract class appRules
{
    public static final boolean IS_DEV = true;
    public static final String CLOCK_SHORT_TIME_FORMAT = "something";
    public static final String CLOCK_SHORT_DATE_FORMAT = "something else";
    public static final String CLOCK_FULL_FORMAT = "other thing";
    public static final int USERNAME_MIN = 5;
    public static final int USERNAME_MAX = 16;
    // etc.
}
这个类很大,包含很多这样的变量

我的问题:

  • 设置静态变量不是意味着 这些变量一直在内存中浮动
  • 你建议用它来代替 有一个抽象类,我有一个 非静态的可实例化类 变量(只需
    public final
    ),因此 实例化该类并使用 只有当我需要变量时才使用它们
  • 或者说我所做的完全是 错误的方法,你会提出其他建议吗

根据应用程序的子模块,将变量列表分解为一组变量。将变量集放在单独的类中。实例化类并将其对象存储在会话中

每当需要使用任何变量时,请从会话中引用对象。如果未使用对象中的任何变量,请从会话中释放该对象


我希望它不会占用您服务器的大部分内存。

我认为它可以解决内存问题。如果要使用大型对象,则延迟初始化可以是一种节省内存的方法。或者
java.util.prefs.Preferences
可以作为一种选择


如果我是您,我会使用name
RuleUtils
而不是
appRules
,并将其设置为最终版本,因为抽象类应该是为扩展而设计的

考虑到现代机器、RAM容量等因素,您必须拥有数千条规则(如果不是数百万条的话)才能在性能和内存方面产生显著的差异

所以问题不在于这是否会困扰你的系统:不是

问题是这是否是一种好的做法

当然我自己也用过这个模式,所以我知道它很有用。然而,主要的缺点是:它使代码不稳定。由于没有简单的方法可以为单元测试设置不同的值(与属性文件不同,在属性文件中,您只需在类路径上放置不同的文件),因此在不连接整个应用程序的情况下测试单个模块的功能将非常困难,但这取决于您在这些常量中保留的内容

我想我可能会尝试拆分一些东西,每个模块、包等有一个常量类,然后从属性文件初始化这些常量:

private static final String CONSTANT_FOO;
private static final String CONSTANT_BAR;
static{
    try{
        Properties props = new Properties();
        InputStream is = 
            MyConstantClass.class
            .getResourceAsStream("my.module.properties");
        props.load(is);

        // you'll actually want to move this to finally, but I'm lazy
        is.close();

        CONSTANT_FOO = props.get("constants.foo");
        CONSTANT_BAR = props.get("constants.bar");

    }catch(Exception e){
        throw new IllegalStateException(e);
    }
}

这样,您的代码变得更加可测试和可配置,同时仍然享受全局配置常量的好处。

我认为这不会带来太多开销。从实际角度考虑,比如说,您
3000条规则
,每条规则都是一个由1000个字符组成的
字符串
。您的内存消耗为
3MB
。太大了吗

我会说,这没关系,即使你有30000条规则。不要为内存使用费操心太多。这不是将导致内存不足错误的区域之一

设置静态变量不意味着这些变量一直在内存中浮动吗

对。但是除非你有一个非常非常大的常数,否则这不会有太大的区别。此外,如果您真的需要将它们命名为常量,则无法真正改进当前的方法

您是否建议不要使用抽象类,而是使用带有非静态变量的可实例化类(仅为public final),因此我实例化该类并仅在需要时使用变量

不,这不会占用更少的内存。JVM无论如何都必须保持字符串对象与文本相对应,以便在创建类的实例时将它们分配给(非静态)变量

此外,还可能创建多个类实例,这会占用更多空间并消耗更多CPU周期

还是我所做的完全是错误的做法

我不这么认为


@Peter Lawrey指出,一个类可以拥有的静态字段的数量在理论上是有限制的。限制因素包括:

  • Cinit伪方法的字节码段大小(2G字节)——
  • 类中的字段数(64K)——
  • 类中的字符串文本数(64K)——

然而,这不太可能是一个实际问题。我无法想象一个程序真的需要如此多的常数,以至于极限开始发挥作用。此外,您可以将常量拆分为多个类。

值得投入使用的内存量。您使用的是移动设备、PC还是服务器?对于服务器,您可以使用一台24GB的机器,花费约1800英镑。这大约是每GB 75英镑,或每MB 8美分

如果你的时间让公司每小时花费50英镑,那么花1分钟来节省10MB的内存就不值得了


在最低工资方面,花1分钟在PC或服务器上节省1MB是不值得的。

谢谢你的回答:)很高兴知道我走对了路:谢谢你的解释!很高兴知道我在正确的轨道上:)类初始化器的大小是有限制的。很难达到这个限制,但这确实意味着您无法生成一个如此大的类,它将仅从大量字段中使用大量内存(字段中有大型对象将产生更大的差异,您只需要其中一个就可以使用许多GB)