Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.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_Static - Fatal编程技术网

Java 按类名访问静态列表变量值(只读静态列表)可以吗?

Java 按类名访问静态列表变量值(只读静态列表)可以吗?,java,static,Java,Static,这是我的密码 public class PropertyLoader { private Properties appProperties; /** * The instance. */ private static PropertyLoader inst = null; /** * Instantiates a new property data loader. */ private PropertyLoad

这是我的密码

public class PropertyLoader {

    private Properties appProperties;

    /**
     * The instance.
     */
    private static PropertyLoader inst = null;

    /**
     * Instantiates a new property data loader.
     */
    private PropertyLoader() {
        try
        {
            appProperties = new Properties();
            appProperties.load(this.getClass().getClassLoader().getResourceAsStream("app.properties"));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public static PropertyLoader getInstance() {
        if (inst == null) {
            inst = new PropertyLoader();
        }
            return inst;
        }
    }

    public String getPropertyAPP(String key) {
        return appProperties.getProperty(key);
    }

}
getPropertyAPP
方法需要同步:它是一个单实例,因此许多线程可以同时访问同一个实例并调用它


有人能给我建议正确的方法吗?

您的
getInstance()
方法中发生了大量竞争情况。如果多个线程同时调用
getInstance()
,您将创建多个实例,并将它们依次分配给静态变量。考虑到您在这里所做的工作,这不会导致任何逻辑问题,但确实意味着您所做的工作超出了必要的范围

我建议您阅读一些关于单例模式的内容,为什么它不好,以及如何在Java中以安全的方式实现它


但简言之,不要使用单例模式,它被严重破坏,将使任何使用此对象的代码紧密耦合,并将抑制您执行任何类型的隔离测试的能力。

您的
getInstance()
方法中发生了大量竞争情况。如果多个线程同时调用
getInstance()
,您将创建多个实例,并将它们依次分配给静态变量。考虑到您在这里所做的工作,这不会导致任何逻辑问题,但确实意味着您所做的工作超出了必要的范围

我建议您阅读一些关于单例模式的内容,为什么它不好,以及如何在Java中以安全的方式实现它


但简而言之,不要使用单例模式,它被严重破坏,会使任何使用此对象的代码紧密耦合,并会抑制您执行任何类型的隔离测试的能力。

一个更简单的解决方案,也是线程安全的,就是使用静态初始化来初始化静态字段

public class AppProperties {
    private static final Properties appProperties;
    static {
        try {
            appProperties = new Properties();
            appProperties.load(AppProperties.class
                      .getClassLoader().getResourceAsStream("app.properties"));
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    public String get(String key) {
        return appProperties.getProperty(key);
    }

    public String get(String key, String defaultValue) {
        return appProperties.getProperty(key, defaultValue);
    }
}

一个更简单的解决方案也是线程安全的,就是使用静态初始化来初始化静态字段

public class AppProperties {
    private static final Properties appProperties;
    static {
        try {
            appProperties = new Properties();
            appProperties.load(AppProperties.class
                      .getClassLoader().getResourceAsStream("app.properties"));
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    public String get(String key) {
        return appProperties.getProperty(key);
    }

    public String get(String key, String defaultValue) {
        return appProperties.getProperty(key, defaultValue);
    }
}

您可以使用以下解决方案

public class PropertyLoader {

        private Properties appProperties;

    /** The instance. */
    private static PropertyLoader inst = null;

    static{
        inst = new PropertyLoader();
    }

    /**
     * Instantiates a new property data loader.
     */
    private PropertyLoader() {
            try
            {
                appProperties = new Properties();
                appProperties.load(this.getClass().getClassLoader().getResourceAsStream("app.properties"));
            }
            catch(IOException e)
            {
                e.printStackTrace();
            }
    }

    public static PropertyLoader getInstance() {
        return inst;
    }


    public String getPropertyAPP(String key) {
        return appProperties.getProperty(key);
    }
}

您可以使用以下解决方案

public class PropertyLoader {

        private Properties appProperties;

    /** The instance. */
    private static PropertyLoader inst = null;

    static{
        inst = new PropertyLoader();
    }

    /**
     * Instantiates a new property data loader.
     */
    private PropertyLoader() {
            try
            {
                appProperties = new Properties();
                appProperties.load(this.getClass().getClassLoader().getResourceAsStream("app.properties"));
            }
            catch(IOException e)
            {
                e.printStackTrace();
            }
    }

    public static PropertyLoader getInstance() {
        return inst;
    }


    public String getPropertyAPP(String key) {
        return appProperties.getProperty(key);
    }
}

您的代码有几个问题:

(a) 您确定需要惰性初始化吗?初始化的成本必须是显著的,并且资源从未被使用的可能性必须是非零的。另外:最好在程序启动时失败,而不是在资源首次被访问时的某个不确定时刻。这实际上取决于您的应用程序

(b) 实现延迟初始化的一种方法是使用正确版本的双重检查锁定(volatile关键字至关重要):

这篇wikipedia文章解释了为什么这是可行的(从Java5开始,但之前没有):


(c) 在大多数情况下,捕获异常并简单地记录它们是完全错误的。在您的情况下,getPropertyAPP不会返回任何属性。如果属性的存在被明确声明为可选,那么这可能是正常的

您的代码有几个问题:

(a) 您确定需要惰性初始化吗?初始化的成本必须是显著的,并且资源从未被使用的可能性必须是非零的。另外:最好在程序启动时失败,而不是在资源首次被访问时的某个不确定时刻。这实际上取决于您的应用程序

(b) 实现延迟初始化的一种方法是使用正确版本的双重检查锁定(volatile关键字至关重要):

这篇wikipedia文章解释了为什么这是可行的(从Java5开始,但之前没有):


(c) 在大多数情况下,捕获异常并简单地记录它们是完全错误的。在您的情况下,getPropertyAPP不会返回任何属性。如果属性的存在被明确声明为可选,那么这可能是正常的

也许您可以为
属性
推荐一种替代
单例
模式的方法。顺便说一句:这个模式并没有被打破——它在Java中的许多实现都被打破了。这里介绍的单例模式和知道单例在哪里的类被打破了——Eric Gamma甚至说它不应该出现在GoF的书中。我建议在应用程序启动时手动或使用DI框架实例化它,并在必要时注入它。是的,但我已经在同步环境中调用了get instance means on contextInitialized,所以仍然提供静态块初始化。我不确定getPropertyAPP方法是否存在竞争条件。感谢您的解释。也许您可以为
属性
推荐一种替代
单例
模式的方法。顺便说一句:这个模式并没有被打破——它在Java中的许多实现都被打破了。这里介绍的单例模式和知道单例在哪里的类被打破了——Eric Gamma甚至说它不应该出现在GoF的书中。我建议在应用程序启动时手动或使用DI框架实例化它,并在必要时注入它。是的,但我已经在同步环境中调用了get instance means on contextInitialized,所以仍然提供静态块初始化。我不确定getPropertyAPP方法是否存在竞争条件。谢谢你的解释。嘿,彼得,IOException肯定会导致应用程序崩溃?@MrWiggles,除非默认值是合理的。否则我会用断言器包装IOE。嘿,彼得,IOException肯定会导致应用程序崩溃?@MrWiggles,除非默认值是合理的。否则我会用断言错误来包装IOE