我有一个带有两个方法load()和getValue()的类。 load函数将一组键值对从文件加载到hashMap,getValue(Object key)方法用于提取传递给它的键的值。
我的问题是我想创建一个类的Object,使load()只执行一次(将值加载到内存中),然后getValue()方法应该能够处理这些数据,每个它的召唤时间。
解决此问题的最佳方法是什么?我是Java和OOP的新手,所以请随意修改问题或标题以使其更清晰。
答案 0 :(得分:9)
您可以为您的班级使用静态初始化程序块。这只对一个类执行一次。
答案 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)
也许这些方法太明显了,但我认为无论如何我都会提到它们......单身人士和其他静态“魔法”通常会有一些陷阱,以后可能会咬你。
load()
一次。这可能是最简单的解决方案。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)
您还可以使用静态方法,这意味着即使调用该方法,它们也不会更新现有数据。