在Java中创建/允许单个执行方法

时间:2012-04-20 06:31:05

标签: java

我有一个带有两个方法load()和getValue()的类。 load函数将一组键值对从文件加载到hashMap,getValue(Object key)方法用于提取传递给它的键的值。

我的问题是我想创建一个类的Object,使load()只执行一次(将值加载到内存中),然后getValue()方法应该能够处理这些数据,每个它的召唤时间。

解决此问题的最佳方法是什么?我是Java和OOP的新手,所以请随意修改问题或标题以使其更清晰。

11 个答案:

答案 0 :(得分:9)

您可以为您的班级使用静态初始化程序块。这只对一个类执行一次。

http://www.glenmccl.com/tip_003.htm

答案 1 :(得分:3)

你可以使load()方法是私有的并在构造函数中调用(当你的对象被创建/类启动时。

它看起来像这样:

public class YourClass {

    private Map map;

    public YourClass() {
        load();
    }

    private void load() {
        // Load the data here
    }

    public Object getValue(int key) {
        return map.get(key);
    }

}

答案 2 :(得分:2)

您需要的是Singleton Pattern。所以基本上你可以这样做:

public class MySingleton
{
     private static Map<String, String> myMap = null;
     private void load()
     {
         myMap = ...//load your contents here
     }

     public static String getValue(String key)
     {
          if (myMap == null)
          {
              load();
          }

          return myMap.get(key);
     } 
}

上面的代码允许您在应用程序中加载一次HashMap。在将初始化代码保留给类外无法访问的私有方法时,您将只显示一个方法load()

正如一个单挑,如果你计划在多线程环境中使用它,你将需要引入synchronized块,如维基百科的例子。

我假设键值对都是字符串,但你可以做任何你想要的数据类型。如果要在应用程序使用之间存储HashMap,可以将其存储到磁盘,只需确保构成HashMap的元素实现Serializable接口。

答案 3 :(得分:2)

也许这些方法太明显了,但我认为无论如何我都会提到它们......单身人士和其他静态“魔法”通常会有一些陷阱,以后可能会咬你。

  1. 仅拨打load()一次。这可能是最简单的解决方案。
  2. 请在load()中记住该方法已被调用(添加boolean成员,在方法结束时将其设置为true,然后检查true方法的开头,在这种情况下简单地返回)。

答案 4 :(得分:1)

@tom为给定的问题指出了一个非常好的解决方案。但是,它也可以通过使用单例模式来解决。由于前面提到的那些不是线程安全的,因此可能会在以后引起问题,继承我对此特定问题的线程安全解决方案:

public Enum MyClass {
   INSTANCE;

   public static MyClass getInstance() {
          INSTANCE.load();
          return INSTANCE;
   }

   private void load() {
          // Load your data
   }
}

鉴于代码使用Enum单例模式并与JDK 5 +一起使用

答案 5 :(得分:0)

使用单身模式。确保只能为该类创建一个对象。包含在构造函数as given in this example中加载load()中的值的代码。这将解决您的问题。

答案 6 :(得分:0)

将Map对象设为静态变量并使用static initialization

答案 7 :(得分:0)

听起来你只需要在构造函数中调用load()。要确保使用任何构造函数调用它,请从其他构造函数中调用它。

顺便说一下,静态初始化器听起来不错,但是不同,在某些情况下是不好的做法。有些人相信永远不会使用静态初始化程序,因为你无法对其进行单元测试,在某些情况下你无法对其进行调试(在首次加载类时调用它,而不是在调用构造函数时调用,或者在调用方法时调用它被调用等等,所以它取决于你为JVM提供的版本和平台!)

示例1:

class MyObj {
    private load() {
        //private so it can't be called elsewhere by mistake (except by you in this file)
    }

    public MyObj() {
        load();
    }
    public MyObj(Collection values) {
        MyObj();
        //next deal with values (duplicate code)
    }
    public MyObj( Collection keys, Collection values) {
        MyObj();
        //next deal with keys and values (some duplicate code)
    }

    ...
}

示例2 :(可能更复杂,导致新开发人员使用NullPointerExceptions,但对于高级编码器更好,因为它避免了重复)

class MyObj {
    public MyObj( Collection keys, Collection values) {
        load();
        //next deal with keys and values (no duplication this time)
    }
    public MyObj(Collection values) {
        MyObj(null, values);
    }
    public MyObj() {
        MyObj(null, null);
    }

    ...
}

如果你想要更复杂的东西,例如。您可以随时使用单个对象,也可以使用工厂。 (工厂意味着每个工厂存在一个对象而不是整体,并且具有此处未提及的其他好处)。

答案 8 :(得分:0)

我已经了解了上述所有解决方案! 首先,执行一次的代码段通常会提供给构造函数,如 j0ntech 所示!其次,如果你不想让人们运行两次或更多的方法,你必须从内部控制方法调用,例如布尔,在第一次调用<之后设置为false强>负载()即可。 E.g。

private boolean enabledLoad = true;

public void load( ...something here...) {
   if(enabledLoad){
     //do something       
   }
   enabledLoad = false;
} 

很简单......

答案 9 :(得分:-1)

您可以反复序列化要再次使用的类,而不会丢失保留给该类的值,显然不会再次加载值....

答案 10 :(得分:-1)

您还可以使用静态方法,这意味着即使调用该方法,它们也不会更新现有数据。