如何在Java上验证构造函数参数?

时间:2018-03-17 10:45:57

标签: java validation

假设我们使用Java SE(没有库)并且具有以下情况。我们有一个班级:

public class DriverInfo {
    private final int age;

    public DriverInfo(int age) {
        this.age = age;
    }

    // getter here
}

在某些国家/地区,如果您年满18岁,则可以开车。换句话说 - 我们需要对年龄参数进行一些验证。类似的东西:

if (age < 18) {
    throw new IllegalArgumentException("Age is not valid!");
}

所以,我的问题是 - 这个验证应该在哪里?我的想法如下:

  • 在构造函数上添加上面描述的 if()。如果从代码上的多个位置调用构造函数,则验证将起作用。我担心的是类构造函数应该(恕我直言)不包含任何逻辑。我是对的吗?
  • 在构造函数之外的某处验证 - 无论是工厂方法,构建器类等。但是我们强迫开发人员不使用构造函数实例化类,而是使用一些人工工厂/构建器。
  • 使用Validate验证构造函数参数。它不是标准的Java,但我看到有人这样做。至于我看起来不正确,因为我们正在为构造函数添加逻辑 - 这对我来说不合适。
  • 我错过了其他任何好方法吗?

任何想法都会受到高度赞赏。有没有人可以建议如何处理所描述的居住情况?

4 个答案:

答案 0 :(得分:2)

构造函数中的验证完全没问题。这&#34;构造函数中没有逻辑&#34;规则不适用于它,遗憾的是猜测它的措辞。 构造函数的任务是从外部获取依赖项(依赖注入)并确保它们有效,然后可能将它们存储在实例属性中 - 简而言之创建有效实例

这样,有效和无效的规则保存在对象内部,而不是在某些工厂中分离。

如果实例无效,则抛出一个异常,解释参数有什么问题,绝对没问题。它可以防止无效实例在系统中漫游。

此外,对于不可变对象,您可以保证所有现有实例始终有效,这很棒。

对对象有一些验证方法是可行的并且可能很有用,但我希望任何一天都能进行构造函数验证。但如果它不可能,那么它总比没有好,它仍然保持对象内的有效性规则。就像某个框架为你构造你的可变对象并需要无参数构造函数...你可以忘记调用它,但它总比没有好。

答案 1 :(得分:0)

我认为您还可以使用其他两种技术。

  1. 将变量传递给 super()并在父类中验证它们。 例如

      

    超级(年龄)

  2. 您可以使用 getters setters 并在那里验证变量。我尝试在java中使用setter。

    public class validate_object_variable {
    private int age;    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        if(this.age >= 18)
        this.age = age;
        else {
            throw new IllegalArgumentException("Age is not valid!");
        }
    }
    
     public static void main(String args[]) {
            validate_object_variable obj = new validate_object_variable();
            obj.setAge(10);
            System.out.println(obj.getAge());
     }
     }
    

    这使我能够通过有效异常干净地退出调用者。

    <强>输出

    enter image description here 我认为在构造函数中抛出异常不是一个好主意。但是,在不妨碍对象创建的情况下,分别使用setter验证变量是一个不错的选择。

答案 2 :(得分:0)

在我看来,你应该在类DriverInfo中有一个方法,如:

public boolean isDriverLegalAge(int age){
    if (age < 18) {
        return false;
    } else {
        return true;
    }
}

构造函数只应用于构建对象。与该对象内部逻辑相关的所有内容都应该在方法内部。

有关构造函数用途的更多信息,请参阅以下链接:https://stackoverflow.com/a/19941847/2497743

答案 3 :(得分:0)

我认为您也可以“使用var movie = new Movie { Location = "uknown"}模式来处理此类用例。虽然构造函数验证非常好,并且通常Builder会引入很多Boiler Plate代码但是如果你想避免在构造函数中进行验证并且想要使用不可变类(没有setter验证),那么你可以尝试给构建器。

通常在面对许多构造函数参数时应使用构建器。您可以阅读有关构建器here的更多信息。

Builder

再次有很多方法可以做到这一点,这里没有对错。它更多地取决于人们喜欢什么,是否可供其他程序员阅读。