我收到了一份工作代码(Java,1.7),它执行以下操作: 将一个字符串数组(一个血液测试名称列表)从一个文件加载到一个字符串数组成员中(使用Properties和FileInputStream)。该文件可以更改字符串,但含义保持不变(例如:测试可以称为“abc”,而在另一次运行中,它称为“zzz”)。我有一个枚举测试名称的枚举类。枚举字符串与输入的字符串不同(因为后者可以改变)。
文件bloodtest.names包含:
bloodTestNames=abc;def;123;
代码:
public enum BloodTestNames {
AAA,BBB,CCC;
}
Properties props = new Properties();
FileInputStream fis = new FileInputStream("bloodtest.names");
props.load(fis);
String testName[]=props.getProperty("bloodTestNames").toString().split(";");
现在问题: 问题1: 当我知道测试名称时,我需要返回文件中设置的字符串(例如:返回“def”表示值BBB)。这样做最好的是什么?
我提出的最佳方式是:
return testName[BloodTestNames.BBB.ordinal()]
问题2:如果在编译时不知道BBB - 我如何实现相同的目标?
三点: *我是C的老手,但是是Java的新手。任何做和不欢迎。假设我的Java知识为零。 *我没有完全重新分解,这就是我们需要的东西。 *我可能忘了提到重要的细节,请问,我会感觉到缺失的空白
答案 0 :(得分:1)
使整个设置驱动:添加一个statuc方法来加载设置的字符串映射到枚举,并添加使用这些设置的工厂方法:
public enum BloodTestNames {
AAA,BBB,CCC;
private static Map<String, BloodTestNames> map = new HashMap<String, BloodTestNames>();
public static void addAlias(String alias, String name) {
map.put(alias, valueOf(name));
}
public static BloodTestNames getByAluas(String alias) {
if (map.containsKey(alias))
return map.get(alias);
// own name assumed to be mapped
return valueOf(alias);
}
}
启动时,根据某些设置文件反复调用BloodTestNames.addAlias()
以加载映射。
当您阅读已保存的文件时,请使用BloodTestNames.getByAlias()
返回给定字符串值的枚举。
你最好用单数命名你的类,并删除“Name”,即BloodTest
- 为每个枚举的名称命名(所有枚举都有一个“名称”,即编码的实例名称) )。
答案 1 :(得分:1)
我首先假设你需要枚举常量来建模这个用例,因为你有一些特定的代码可以为每种血液测试执行(否则,一组简单的字符串就足够了,更灵活,因为您不需要预先知道测试的数量或关心他们的名字。)
Q1:由于Java枚举只是一系列值,你可以充分利用它们面向对象的本质。
public enum BloodTest {
AAA, BBB, CCC;
private static String[] names;
public static void setNames(String[] names) {
if (BloodTest.names != null)
throw new IllegalStateException("You can only set the names once");
if (names.length != values().length)
throw new IllegalArgumentException("Wrong number of names");
BloodTest.names = names;
}
@Override
public String toString() {
return names[ordinal()];
}
}
现在您需要做的是通过调用BloodTest.setNames(namesFromConfiguration)
初始化您的枚举,然后您可以通过调用标准toString()
方法获取每个常量的字符串表示形式:BloodTest.BBB.toString()
由于最初的假设是每个测试类型都有一些特定的逻辑,我建议逻辑(以及所需的属性)也将封装在枚举本身或枚举常量中; e.g:
public enum BloodTest {
AAA(10) {
@Override
public boolean isRequired(MedicalRecord medicalRecord) {
return medicalRecord.includes("someDisease");
}
},
BBB(15) {
@Override
public boolean isRequired(MedicalRecord medicalRecord) {
return ! medicalRecord.hasTakenBloodTestsLately();
}
},
CCC(20) { // ... also implements the abstract method and so on
private final int threshold;
private BloodTest(int threshold) {
this.threshold = threshold;
}
public boolean hasPassed(int value) {
return value <= threshold;
}
public abstract boolean isRequired(MedicalRecord medicalRecord);
// ... same as above
}
现在,一旦获得对某些BloodTest
的引用,您可以通过调用相应的方法来检查是否通过了switch
并且逻辑遍布客户端代码来传递特定的测试:
BloodTest bloodTest = BloodTest.valueOf(someString); // someString can be "AAA", "BBB" or "CCC"
// no matter which constant this is, you use it as an object and rely on polymorphism
if (bloodTest.hasPassed(someValue)) { // ... do something
Q2:你的问题有两种“问题”是我对你实际需要枚举的初步假设。如果你有可能需要动态处理你还不知道的血液测试,那么就不能使用枚举。
换句话说,如果您的代码没有任何switch
或if/else if
块来处理每次验血,那么枚举对您的用例来说是一个非常糟糕的选择。
但是,如果确实如此,我建议重构代码以将逻辑包含在枚举本身中,如上例所示,而不是switch
/ if
块;此外,如果您的switch
有default
个案例(或您的if
有最后else
个阻止),这仍然可以在枚举本身中建模,例如添加DEFAULT
常数作为后备。
答案 2 :(得分:0)
我的枚举类之一的简短摘录:
public enum TypesStructurelsE {
SOURCE("SRC"),
COLONNE("COL");
private String code;
TypesStructurelsE(final String code1) {
code = code1;
}
/** @return String */
public String getCode() {
return code;
}
public void setCode(final String newCode) {
code = newCode;
}
}
。 。在其他班级
if(TypesStructurelsE.SOURCE.getCode().equal(testName[i])){ // can be "COL" or "SRC"
//
;
}
......改变价值:
TypesStructurelsE.SOURCE.setCode("SOURCE_NEW");
因此,如果您的属性文件发生更改,您只需使用新的symbole(SRC - &gt; SOURCE)进行编译