0

假设我想阅读以下文件:

TestFile;100

进入类的领域:

public class MyReader { 
    String field1;
    Integer field2;
}

阅读内容有两种略有不同的方式:

公共类 MyReader {

public void loadValues(File file) throws IOException {

    //a generic method that reads the content file to a string throwing an IOException
    String line = readFileToString(file);
    String[] values = line.split(";");

    field1=values[0];
    field2=Integer.parseInt(values[1]);

}

//then i'll have well known getters:

public String getField1() {
  return field1;
} 

public Integer getField2() {
  return field2;
}

现在第二个成语:

private String[] values; //made the values a class field

public void loadValues(File file) throws IOException {

    //a generic method that reads the content file to a string throwing an IOException
    String line = readFileToString(file);

    values = line.split(";");

}

public String getField1() {
  return values[0]
} 

public Integer getField2() {
  return Integer.parseInt(values[1]);
}

最大的区别在于异常管理。我故意省略了捕获两种情况下可能发生的两个运行时异常:

  • ArrayIndexOutOfBoundsException如果文件包含少于两个字段
  • NumberFormatException如果整数解析失败

第一种方法
所有字段都在启动时加载。足够其中一个是不可解析的,我得到了NumberFormatException. 如果字段少于所需的字段,我将获得越界异常。这听起来不错,特别是如果我想确保我将使用特定的事实背后的所有字段值的正确性:快速失败范例。假设我有一百个字段,该记录包含一个错误,该错误又被记录到一个文件中以进行故障排除。照原样,这段代码给出了这样的东西:

Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)

即:我得到错误,导致错误的值,给出错误的行号,但不是字段名称。对开发人员有好处,对通常无法访问源代码的系统工程师来说不是很好。

第二种方法只有在通过 getters 访问
字段时,才会从数据字符串中“提取”和解析这些字段。在完全相同的情况下,每个 getter 都可能返回上述两个错误。相对于“快速失败范式”,存在一定程度的“容错”。如果记录的第 100 个字段包含不正确的值,但类的客户端没有调用它的 getter,则永远不会抛出异常。另一方面,当调用错误值的 getter 时,记录的异常将包含导致问题的字段的信息(在堆栈跟踪中):

at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:449)
at java.lang.Integer.parseInt(Integer.java:499)

at com.test.MyReader.getField2(MyReader.java:39)

at com.test.MyReader.test(MyReader.java:33)
at com.test.MyReader.main(MyReader.java:16)

问题)

两种方法都有利有弊,可以说采用哪种方法的决定取决于上下文。问题是:

  • getter 和 setter 是 javabean 的主题。他们返回异常是否“可以接受”?
  • 这两种方法中的类可能显然具有相同的接口,但由于它们具有完全不同的异常架构,因此客户端应该以完全不同的方式使用它们。那么如何向客户展示这个事实呢?也许 getters 语义具有误导性,也许有更雄辩的方式?
4

1 回答 1

2

首先,第二种方法不起作用,因为您将 values[] 数组存储为局部变量,并且其他函数(在您的情况下为 getter)无法访问它。

其次,当您公开的 api 时,不要在 getter 中抛出异常,这会产生误导,并且不符合任何约定。

第三,与其自己解析字符串,不如考虑使用现成的库进行 csv 解析,不要重新发明轮子,例如。http://opencsv.sourceforge.net/

第四,为csv记录创建一个简单的POJO对象,您可以在为每个字段分配值时检查错误,然后抛出异常,提供默认值等。

希望有帮助

于 2012-06-15T10:00:10.210 回答