繁体   English   中英

在我的特定情况下,我是否应该使用自定义异常?

[英]In my particular situation should I use custom exceptions or not?

如果不满足某些条件,我必须创建这个学生存储库,其中需要抛出异常。 我的问题是:我应该创建自己的自定义异常,还是应该使用预定义的异常? 我将在下面留下我的一部分代码

public class StudentRepository {

private static List<Student> studentList = new ArrayList<>();
private static Set<Student> studentsByAge = new TreeSet<>(new AgeComparator());
private static Set<Student> studentsByLastName = new TreeSet<>(new LastNameComparator());

public static Student addStudent(String firstName, String lastName, String gender, LocalDate dateOfBirth) {


    if (firstName.trim().isEmpty() || lastName.trim().isEmpty()) {
        throw new NullPointerException("Last name or first name field may be empty");
    } else if (!(gender.equalsIgnoreCase("m") || gender.equalsIgnoreCase("f"))) {
        throw new IllegalArgumentException("Gender should be 'M or 'F");
    } else if (dateOfBirth.isBefore(LocalDate.of(1900, 1, 1)) ||
            dateOfBirth.isAfter(LocalDate.now())) {
        throw new IllegalArgumentException("Date of birth should be between 1900 and current year");
    }

    Student newStudent = new Student(firstName, lastName, dateOfBirth, gender);
    studentList.add(newStudent);
    return newStudent;
}

public static void deleteStudentByCnp(String cnp) {
    Student studentToDelete = null;

    for (Student student : studentList) {
        if (student.getCnp().equals(cnp)) {
            studentToDelete = student;
            studentList.remove(studentToDelete);
            break;
        } else {
            throw new NullPointerException("The student does not exist");
        }
    }
}

您可以查看 Oracle 关于已检查与未检查异常主题的建议,这应该更清楚: https : //docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html

该页面的摘要如下

这是底线准则:如果可以合理地期望客户端从异常中恢复,请将其设为已检查异常。 如果客户端无法从异常中恢复,请将其设为未经检查的异常。

您还可以在此处阅读有关自定义异常与标准异常用法的更多信息: https : //stackify.com/java-custom-exceptions/

通常这取决于客户端的行为 - 客户端可以用这个异常做什么。 如果它只是记录错误而仅此而已 - 那么 IllegalArgumentException 应该就足够了,但是如果您随后将此错误返回给客户端,例如使用 REST - 那么创建具有适当结构的自定义异常将是有意义的,该异常将被序列化并返回以响应保持响应错误的一致结构。

无论如何,请不要使用NullPointerException除了某些意外为 null 的情况(即程序员的错误)。 在您的情况下,我会用自定义异常替换 NullPointerExceptions。

假设这些规则(性别必须是MF等)被视为先决条件(因为文档指出:您传递的参数必须遵守这些规则),抛出的正确异常是IllegalArgumentException 除了 param 不能为 null 的先决条件,在这种情况下NullPointerException是合适的。 谈论可恢复性不适用于这种异常——方法的作者不知道调用者是否是那种可以“合理地从异常中恢复”的代码。 他们很有可能不能(比如,它是通过网络提供的文本,并且没有机制向调用者发回信号:呃,你没有遵循那里商定的规范,或者它来自配置文件),所以在这里未经检查可能更好。 IllegalArgumentException恰到好处。

但是, NullPointerException在这里显然是非常糟糕的用法 那就是表示一个事情是空的,这不是预期的,就是这样,所以不要像这样滥用它!

请注意,您的代码有很多问题:

  • 2 性别? 现在是 2021 年。这可能永远不会被接受,但现在肯定不是。 为什么你需要知道学生的性别? 将正确的敬语放在字母上? 摆脱性别并为“荣誉”添加一个字段。 许多国家都有指导方针,禁止在不相关时询问性别。 我在这里似乎无关紧要。 (荣誉可能是;如果您需要,请要求)。
  • 如果您想忽略它并强制使用 2 个性别,请强制使用它,然后编写一个枚举。 您想避免某些输入可以声明但无效的整个想法 - 因为那样您需要继续编写代码以对无效状态做出反应。 如果一个对象或参数根本不可能是错误的,那就更好了。 枚举不可能是错误的,或者至少,只有在例如它为空时才会是错误的,这是一种更简单的检查。
  • 您的“日期”错误显示为“当前年份”,但实际上是在检查当前日期。
  • 性别错误有错别字。
  • 您的姓氏/名字消息不清楚,并且不遵循 Java 样式。 你应该陈述规则,而不是问题。 '名字和姓氏不得为空'。 没有什么“可能”的。
  • 您的delete方法将检查列表中的第一个学生。 如果它的 CNP 匹配,则将其删除,然后就完成了。 如果不匹配,您的代码会立即出错。 除了列表中的第一个之外,它从不扫描任何学生。 该异常抛出需要在for循环之外。
  • Map在这里听起来像是更好的数据结构; 目前,随着学生越来越多,您的删除代码将花费越来越长的时间。
  • 当您使代码更通用时,“名字”和“姓氏”的概念也很可疑。 这是个好消息:它简化了我们作为开发人员的生活。 只需有一个“全名”字段。 现在,您不再需要计算如何将名字和姓氏组合在一起。 您只需打印“全名”字段的值。 如果您需要更短的名称,请将其添加为字段。 性别也一样:不要根据性别找出正确的敬语,只需将“敬语”字段的值放在那里。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM