给出我的程序的以下部分:
public class AnimalNames {
private static String[] animalNames = {dog, cat, horse, cow, donkey, elephant};
private static String[] animalNameAbbreviations = {d, c, h, co, d, e};
public static HashMap<String, String> getAnimalNameTranslations() {
HashMap<String, String> animalNameTranslations = new HashMap<String, String>();
for (int i = 0; i < animalNames.length; i++) {
animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
}
return animalNameTranslations;
}
}
我能够访问填充的animalNameTranslations(使用static关键字),而无需实例化AnimalNames类,这正是我想要的。但是,每次我想访问它时(使用for循环),我的程序仍然必须填充animalNameTranslations。是否有一种方法来填充HashMap对象只有一次为我的程序?
您可以从静态初始化块中调用getAnimalNameTranslations
方法,该方法将在初始化类时执行一次。您必须添加一个静态成员来保存该方法返回的Map。
例如:
private static HashMap<String, String> animalNameTranslations;
static {
animalNameTranslations = getAnimalNameTranslations ();
}
或者直接将该方法的逻辑移到静态初始化块中。
private static HashMap<String, String> animalNameTranslations;
static {
animalNameTranslations = new HashMap<String, String>();
for (int i = 0; i < animalNames.length; i++) {
animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
}
}
你可以声明你的animalNameTranslations
作为一个私有静态变量,然后更新你的getAnimalNameTranslations()
方法来初始化animalNameTranslations
,只有当它之前没有像这样初始化:
public class AnimalNames {
private static HashMap<String, String> animalNameTranslations;
public static HashMap<String, String> getAnimalNameTranslations() {
if(animalNameTranslations == null) {
animalNameTranslations = new HashMap<String, String>();
for (int i = 0; i < animalNames.length; i++)
animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
}
return animalNameTranslations;
}
}
这将避免将调用者与类中的数据结构耦合,从而封装底层实现。
现在需要注意的是,以前,每次调用getAnimalNameTranslations()
时都会更新数据结构。使用我建议的方法,如果您的animalNames
和animalNameAbbreviations
发生了变化,您将需要单独的方法,如addAnimalNameTranslations()
, deleteAnimalNameTranslations()
等来更新您的底层数据结构。
像这样:
public class AnimalNames {
private static String[] animalNames = {dog, cat, horse, cow, donkey, elephant};
private static String[] animalNameAbbreviations = {d, c, h, co, d, e};
private static HashMap<String, String> animalNameTranslations = new HashMap<String, String>();
static{
for (int i = 0; i < animalNames.length; i++) {
animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
}
}
public static HashMap<String, String> getAnimalNameTranslations() {
return animalNameTranslations;
}
}
您可以使用静态块来解决问题。也称为静态初始化块。这是一个普通的代码块,用大括号{}括起来,前面是static关键字。像这样:
static {
// add the code for initialization
}
一个类可以有任意数量的静态初始化块,它们可以出现在类体的任何地方。运行时系统保证静态初始化块按照它们在源代码中出现的顺序被调用。
你可以把你的代码写成
private static HashMap<String, String> animalNameTranslations;
static {
animalNameTranslations = new HashMap<String, String>();
for (int i = 0; i < animalNames.length; i++) {
animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
}
}
您可以简单地硬编码该映射。当然,它是蛮力的,看起来很过时,但它很快,在编译时就为您构建了,不需要等待任何代码运行。如果一切都是静态的,列表不会改变,这是一个巨大的胜利。
如果你仍然想要运行一些启动代码,在一个静态初始化器中做,一次为程序。
简单地定义一个私有成员并用它来填充变量:
private static HashMap<String, String> _animalNameTranslations = new HashMap<String, String>();
public static HashMap<String, String> getAnimalNameTranslations() {
var animalNameTranslations = _animalNameTranslations;
for (int i = 0; i < animalNames.length; i++) {
animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
}
return animalNameTranslations;
}