Java 在两个变量之间交替写入空检查?

Java 在两个变量之间交替写入空检查?,java,Java,我有点困惑。 我有两个对象A和B。 它们可以是null,也可以不是null,我必须在所有这些情况下执行一些不同的业务逻辑 目前我有: if(A != null && B != null) { /* operation1 */ } if(A == null && B == null) { /* operation2 */ } if(A != null && B == null) { /* operation3 */ } if(A == null

我有点困惑。 我有两个对象
A
B
。 它们可以是
null
,也可以不是
null
,我必须在所有这些情况下执行一些不同的业务逻辑

目前我有:

if(A != null && B != null) { /* operation1 */ } 
if(A == null && B == null) { /* operation2 */ }
if(A != null && B == null) { /* operation3 */ } 
if(A == null && B != null) { /* operation4 */ }

你能给我推荐一种更优雅的书写
if
s的方法吗?

为了避免多次检查相同的条件:

if (A != null) {
    if (B != null) {
        // operation1
    } else {
        // operation3
    }
} else {
    if (B != null) {
        // operation4
    } else {
        // operation2
    }
}

但这并不能真正让代码看起来更优雅。

下面是使用嵌套if/else的等效解决方案:

if(A != null)
{
    if(B != null)
    {
        /* operation1 */
    }
    else
    {
        /* operation3 */
    }
}
else
{
    if(B != null)
    {
        /* operation4 */
    }
    else
    {
        /* operation2 */
    }
}
正如您可以清楚地看到的,“如果a…b…c…条件成立,则执行xyz”的语义在这种方法中就不那么清晰了。因此,您提出的“不雅”方法实际上是一段逻辑清晰的代码。充其量,您可以执行以下操作:

// Using a helper class with method names that 
// clearly communicate intent/meaning in the null checks:
class Logics
{
    public static boolean allNull(Object... objs)
    {
        for(Object o : objs)
            if(o != null)
                return false;
        return true;
    }
    public static boolean noneNull(Object... objs)
    {
        for(Object o : objs)
            if(o == null)
                return false;
        return true;
    }
}
...
if(Logics.noneNull(A, B)) { /* operation1 */ } 
if(Logics.allNull(A, B)) { /* operation2 */ }
if(A != null && B == null) { /* operation3 */ } 
if(A == null && B != null) { /* operation4 */ }

你可以做到以下几点,尽管这比你已经拥有的更好还是更差(这还不错)还有争议:


您可以结合以下内容执行类似操作:

谓词isNull=Objects::isNull;//或o->o!=无效的
谓词isNotNull=Objects::nonNull;//或o->o==null
如果(isNull.test(A)){
if(isNotNull.test(B)){
/*操作1*/
}
否则{
/*操作2*/
}
}
否则{
如果(isNull.test(B)){
/*操作3*/
}
否则{
/*操作4*/
}
}

事实上,如果您希望在调用方法中保持if条件可见,那么您的代码是一个比叠置if条件的解决方案更好的选择。所有这些if-else和内部if-else语句都使触发每个操作的条件变得不那么明显。所以你可以保持你的方法。看

您可以做的一个小改进是从if条件中提取方法,并以记录决策的方式命名新方法:

if(是否有ACARANDENOUGHGAS(A,b)){//驱动操作}
if(是否有AcarandNogas(A,b)){//行走操作}
...
私有布尔值是youhaveAcarandenoughgas(…){返回A!=null&&B!=null;}
如果您想要/需要更新奇的东西,可以使用命令模式或策略。根据经验,重复的if-else语句或开关是符号,您可以使用多态性获得相同的结果。看

接口操作{
void execute();
}
类操作生成器{
公共静态操作构建(类型A、类型B){
如果(A!=null&&B!=null){返回新的OperationOne();}
如果(A==null&&B==null){returnnewoperationtwo();}
如果(A!=null&&B==null){/*操作3*/}
如果(A==null&&B!=null){/*操作4*/}
}
类OperationOne实现操作{
私有操作ONE(){…}
@凌驾
void execute(){…}
}
类操作两个实现操作{
私有操作二(){}
@凌驾
void execute(){…}
}
}
用这个你只要

Operation op=OperationBuilder.build(A,B);
op.execute();
下面是为什么这比您开始时的更好。想象一下你有

if(codition1){
  //complicated stuff here that makes you scroll and scroll
}
if(codition2){
  //complicated stuff here that makes you scroll and scroll
}
etc

您可能无法在同一屏幕上看到所有条件,因此您无法了解正在发生的情况。另一方面,构建器保持所有条件的严密性和干净性,同时再次将操作逻辑与噪声分离。

如果需要执行4种不同的操作,除了使用
else If
,或嵌套
If(A!=null){If(B!=null){}
,实际上,除了嵌套if-else语句之外,您可以做的事情并不多。嵌套if-else语句实际上是一种代码味道,所以您不应该这么做。开关与您已有的开关是一样的,无论如何,它们不适用于此类比较,而不会使代码复杂化。这种样式使读取条件变得更加困难。问问自己,在什么情况下你会做操作2,例如,你最终会做一些容易出错的心理操作。这是一个不错的黑客行为,但事实上它增加了代码的复杂性:因此理解代码会更加困难,并且会更加努力确保代码不会出错。所以我不会这么做,注意数字
00
01
10
11
看起来像二进制数,但实际上是八进制和十进制数。为什么不使用实数二进制数,在它们前面加上
0b
<代码>0b00,
0b01
0b10
0b11
Predicate<Object> isNull = Objects::isNull; // or o -> o != null
Predicate<Object> isNotNull = Objects::nonNull; // or o -> o == null

if (isNull.test(A)) { 
    if (isNotNull.test(B)) {
        /* operation1 */ 
    }
    else {
        /* operation2 */
    }
}
else {
    if(isNull.test(B)) { 
        /* operation3 */ 
    }
    else {
        /* operation4 */ 
    }
}
if(codition1){
  //complicated stuff here that makes you scroll and scroll
}
if(codition2){
  //complicated stuff here that makes you scroll and scroll
}
etc