如何在Java中检查两个参数是否为空或两者都为空。

7
我想验证以下条件,但我的if条件有问题,并返回无效结果。 我的验证条件如下: productIdproductAltID可以有值,也可以都是null 如果productIdproductAltID都为null,则productSellDateproductReturnDate必须有值。
如果productSellDateproductReturnDate都为null,则productIdproductAltID应该有值。
请查看以下代码,我得到了错误的结果,不确定我在哪里出错了:
public class validate {

    public static void main(String[] args) {

        String productId = null;
        String productAltID = "adfafadsf";
        Date productSellDate = null;
        Date productReturnDate = new Date();

        if (productId != null || productAltID != null || productSellDate !=null && productReturnDate != null) {
            System.out.println("validation success");
        } else {
            System.out.println("validation failed");
        }

    }
}

// 有效场景

Combination 1: Valid Scenario
        String productId = null;
        String productAltID = null;
        Date productSellDate = new Date();
        Date productReturnDate = new Date();


Combination 2: Valid Scenario
        String productId = null;
        String productAltID = "3432fefsf";
        Date productSellDate = new Date();
        Date productReturnDate = new Date();

Combination 3: Valid Scenario
        String productId = "sdf3234234324";
        String productAltID = "3432fefsf";
        Date productSellDate = null;
        Date productReturnDate = null;

Combination 4: Valid Scenario
        String productId = null;
        String productAltID = "3432fefsf";
        Date productSellDate = null;
        Date productReturnDate = null;

逻辑运算符 &&|| 之前被计算。尝试在 if 条件语句中添加括号。或者更好的方法是,根据问题描述创建各种条件的方法,这样可以写成:if (isSomeCondition(...) || isSomeOtherCondition(...) || isYetSomeOtherCondition(...)) - Andrew S
我认为你基本上需要一个 else if 组件,或者尝试使用类似于 if ((productId != null || productAltID != null) || (productSellDate != null && productReturnDate != null)) { 的东西。 - MadProgrammer
@DaveBrady,你能提供一个实际结果与预期值不同的例子吗?现有代码似乎没问题。 - Nowhere Man
你的问题可以通过展示一些无效数据示例来改进。此外,描述业务规则的散文可以写得更清晰。 - Basil Bourque
3个回答

5

正如注意到的,运算符&&||具有更高的结合性,因此逻辑并非您想要的结果。请参阅Oracle教程中的运算符页面。

一点文学编程可以避免这种情况发生。

boolean hasAnId = productId != null || productAltID != null;
boolean hasDates = productSellDate != null && productReturnDate != null;
if ( hasAnId || hasDates ) ...

4

简述

drekbour的回答是正确的,操作符优先级规则和缺少括号意味着您的| |&&运算符执行顺序与您的意图不同。

这里提供了一种替代方法,使用Objects.nonNull和流来执行您想要的逻辑,以便以可读格式呈现。

Stream
.of( productId , productAltID )
.anyMatch( Objects :: nonNull )              // One or more ID fields have a value.
||                                           // … or …
Stream
.of( productSellDate , productReturnDate )
.allMatch( Objects :: nonNull )              // All dates have a value.

详情

Objects.nonNull

修改 drekbour 的代码,我建议使用 Objects.nonNullObjects.isNull 以便更容易阅读。
此外,我会使用更具描述性的变量名称。
boolean atLeastOneIdHasValue = Objects.nonNull( productId ) || Objects.nonNull( productAltID ) ;  // One or both ID fields have a value.
boolean bothDatesHaveValue = Objects.nonNull( productSellDate ) && Objects.nonNull( productReturnDate ) ;  // Both dates have a value.
boolean valid = ( atLeastOneIdHasValue || bothDatesHaveValue ) ;

另一种方法使用

将您的变量制成流:

Stream.of( productId , productAltID )

然后检查是否有任何或所有匹配我们的标准。

  • 调用 Stream#anyMatch 方法来检查此流中是否有任何元素与提供的谓词匹配。
  • 调用 Stream#allMatch 方法来检查此流中是否所有元素都与提供的谓词匹配。

在我们的情况下,谓词只是对 Objects.nonNull 的调用。

boolean atLeastOneIdHasValue = Stream.of( productId , productAltID ).anyMatch( x -> Objects.nonNull( x ) ) ;  // One or more ID fields have a value.
boolean bothDatesHaveValue = Stream.of( productSellDate , productReturnDate ).allMatch( x -> Objects.nonNull( x ) ) ;  // All dates have a value.
boolean valid = ( atLeastOneIdHasValue || bothDatesHaveValue ) ;

我们可以使用方法引用作为谓词来缩短代码:Objects::nonNull
boolean atLeastOneIdHasValue = Stream.of( productId , productAltID ).anyMatch( Objects :: nonNull ) ;  // One or more ID fields have a value.
boolean bothDatesHaveValue = Stream.of( productSellDate , productReturnDate ).allMatch( Objects :: nonNull ) ;  // All dates have a value.
boolean valid = ( atLeastOneIdHasValue || bothDatesHaveValue ) ;

查看这个 在IdeOne.com上运行的代码


避免使用Date

顺便提一下,不要使用Date类,也不要使用CalendarSimpleDateFormatTimestamp等。这些都是过时的,是可怕的日期时间类的一部分,早在多年前就被现代的java.time类(由JSR 310定义)所取代。

  • 对于仅包含日期(年月日)的情况,请使用LocalDate
  • 对于以UTC为基准的瞬间(偏移量为0小时-分钟-秒),请使用Instant
  • 对于以特定时区为基准的瞬间,请使用ZonedDateTime

这可能是一本好书的一部分! - Randy

3

这样说吧:

public static boolean isValid(
    String productId, String productAltId, Date sellDate, Date returnDate
) {
    if (null == productId && null == productAltId) {
        return null != sellDate && null != returnDate; // dates MUST have value
    }
    // here productId or productAltId have value, no need to check dates
    return true;
}

测试:

System.out.println(isValid(null, null, new Date(), new Date())); // true
System.out.println(isValid(null, "ab", new Date(), new Date())); // true
System.out.println(isValid("cd", "ab", null, null));             // true
System.out.println(isValid("cd", null, null, null));             // true

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接