避免空值,不变性,对象状态

我喜欢不变性的概念。 我也喜欢没有空值的概念(如果可能的话,也尽可能地没有NullDesignPattern,没有NullObjects ...)。

但是,以下情况如何:

我有一个对象User ,它有两个字段: birthdaydateInLifeMarried (可以是任何类似的字段;重要的是,起初这个字段为null并且在对象生命中的某个时刻改变)。

由于它是不可变的,我希望这两个字段都在构造函数中:

public User(birthday, dateInLifeMarried)

现在:

  • 我不想将null传递给第二个参数
  • 因为我不想添加一个setter,因为它是不可变的
  • 我不想用NullObjectPattern而不是null调用构造函数
  • 我只是与自己相矛盾,还是有一种优雅的方式来拥有它,我没有想到?


    那么你需要考虑你想要的表示是什么 - 不仅仅是构造函数签名。 我怀疑你将需要使用空引用(或至少类似的)为该领域。 但是你可以有两个构造函数:

    User(birthday)               // Unmarried user
    User(birthday, marriageDate) // Married user; marriageDate must not be null
    

    作为一个API的用户,我不确定我是否真的喜欢这个 - 但我想我宁愿让marriageDate为null。 特别是,写下这样的内容会很麻烦:

    LocalDate marriageDate = getMarriageDateOrNull();
    User user = marriageDate == null ? new User(birthday)
                                     : new User(birthday, marriageDate);
    

    或者,因为人们可以不止一次结婚,所以你总是可以接受一个可以继续使用的Iterable<LocalDate> marriageDates ,然后一个从未结过婚的用户会有一个空序列:)(你需要考虑已婚,离婚和结婚的情况,然后是寡居用户,建模现实生活很困难。)


    那么第二个构造函数呢?

    User(birthday)
    

    那叫第一个

    this(birthday, null)
    


    为了避免它,不要只是避免null。 考虑一下null是什么意思,然后在有意义的地方使用它。 值null表示未知的,未定义的或未指定的值。 如果你有意识地使用null,你可以使你的代码更容易使用,更易读,同时防止空指针异常。

    在你的例子中,结婚日期可以是未指定的,因此你应该允许null 。 但是,你不希望生日不明确,所以你不允许在那里空。 你可以像这样指定构造函数:

    User(LocalDate birthday)
    {
        this(birthday, null);
        // That's it! Nothing more to do here.
    }
    
    User(LocalDate birthday, LocalDate marriageDate)
    {
        if (birthday == null)
            throw new IllegalArgumentException();
        // Use it...
    }
    

    现在你(或任何使用你的代码的人)可以做这样的事情:

    LocalDate marriageDate = getMarriageDateOrNull();
    User user = new User(birthday, marriageDate);
    

    看到? 更清晰的代码,因为你授权null而不是避免它。

    链接地址: http://www.djcxy.com/p/20877.html

    上一篇: Avoiding nulls, immutability, object state

    下一篇: java optional parameter in methods