Java 使用条件运算符选择哪个对象调用特定方法?

Java 使用条件运算符选择哪个对象调用特定方法?,java,coding-style,conditional-operator,Java,Coding Style,Conditional Operator,我有两个集合,以及根据是否满足某些条件添加到其中一个集合中的项目 有点不小心,我无意中发现了这样一个事实:写作是合法的 (test(foo) ? cOne : cTheOther).add(foo); 而不是 if (test(foo)) { cOne.add(foo); } else { cTheOther.add(foo); } 虽然第一种方法让我觉得自己很聪明(总是一个加号),但我不确定长期的可读性、可维护性等。我看到的基本优势是,如果我知道我总是要做同样的事情,那么改变一种方法就

我有两个集合,以及根据是否满足某些条件添加到其中一个集合中的项目

有点不小心,我无意中发现了这样一个事实:写作是合法的

(test(foo) ? cOne : cTheOther).add(foo);
而不是

if (test(foo)) {
 cOne.add(foo);
} else {
 cTheOther.add(foo);
}
虽然第一种方法让我觉得自己很聪明(总是一个加号),但我不确定长期的可读性、可维护性等。我看到的基本优势是,如果我知道我总是要做同样的事情,那么改变一种方法就变成了一个位置(而不是两个,或者如果我正在实现的话,可能是多个位置)。主要的缺点发生在情况并非如此时(即,我需要为某些情况添加方法调用,而不是其他情况)

您认为这两种方法(或其他解决方案)的优缺点是什么?


如果您不认为使用条件运算符来设置调用方法的对象的特定实例是正确的选择,那么在某些情况下它是合理的吗?

与示例一样,可读性和可维护性始终是最明智的想法


关于条件运算符,您最多只能有两个值,如果您的条件超过该最大值,则可能无法读取。条件运算符不是处理不同值的标准方法。

我认为“完整”的长版本可读性更好一些,而且从长远来看肯定更便于维护。

更简单的代码片段是

SomeClass component = test(foo) ? cOne : cTheOther;
component.add(foo);

换句话说,将作业与使用分开。

我更喜欢第一个(或matt的中间解决方案)。只是比较短。如果在项目中经常使用条件运算符,人们就会习惯它,并且“可读性”会增加


或者换句话说:如果你习惯Perl,你可以很容易地阅读它。

我反对在if语句的每个分支中长时间调用函数,因为并不总是清楚要调用的函数是否是相同的,如果你需要更改被调用的函数,这两个地方需要更改(好的,'add'是一个简单的例子)。因此,我通常会将正确的对象分配给变量(通常在if语句中,因为通常会有一些其他的事情发生),但会将所有常用代码拉到条件之外。

用于此目的的条件运算符非常罕见,因此眼睛不会真正寻找它

我喜欢我的Java代码看起来是一致的,这样我和未来的维护人员就可以很容易地发现分支、太多的复杂性等问题。因为我在其他地方使用ifs,我通常可以通过使用条件语句来承担这样做的成本

如果我使用的是一种通过表达式(如Python)执行大量“技巧”的语言,那就不同了。

我首选的方法是:

final boolean    result;
final Collection c;

result = test(foo);

if(result)
{
    c = cOne;;
} 
else 
{
    c = cOther;;
}

c.add(foo);
首先,我不喜欢调用,也不喜欢将值赋给temp变量(test(foo)调用),原因有两个:

  • 调试更容易(System.out.println,甚至调试器-如果该方法有副作用,那么在调试器中查看它就会再次调用它-从而导致副作用)
  • 即使没有副作用,它也会阻止您多次调用它,从而使代码更高效。编译器/热点应该处理删除不需要的temp变量的问题
  • 其次,我不喜欢有这样的代码,如果你模糊了你的眼睛,它看起来是一样的。如果你模糊了你的眼睛,使用cOne.add(foo)和cOther.add(foo)“look”是一样的。例如,如果你把它改成一个列表,用add(int,E)代替add(E)那么您只有一个地方可以更改代码,这意味着犯错误的更改更少(比如cOne.add(1,foo)和cOther.add(2,foo),而它们都应该是add(1,foo))

    编辑(基于评论)

    有两种选择,这取决于代码的布局方式。我可能会选择以下方式:

    private Collection<Whatever> chooseCollection(final Whatever             foo,
                                                  final Collection<Whatever> a,
                                                  final Collection<Whatever> b)
    {
        final boolean              result;
        final Collection<Whatever> c;
    
        result = test(foo);
    
        // could use a conditional - I just hate using them
        if(result)
        {
            c = a;
        }
        else
        {
            c = b;
        }
    
        return (c);
    }
    
    for(......)
    {
        final Collection<Whatever> c;
        final Whatever             foo;
    
        foo = ...;
        c = chooseCollection(foo, cOne, cOther);
        c.add(foo;
    }
    
    私人收藏选择收藏(最终),
    最终收藏a,
    最终收集(b)
    {
    最终布尔结果;
    最终收集c;
    结果=试验(foo);
    //可以使用有条件的-我只是讨厌使用它们
    如果(结果)
    {
    c=a;
    }
    其他的
    {
    c=b;
    }
    返回(c);
    }
    
    然后做一些类似的事情:

    private Collection<Whatever> chooseCollection(final Whatever             foo,
                                                  final Collection<Whatever> a,
                                                  final Collection<Whatever> b)
    {
        final boolean              result;
        final Collection<Whatever> c;
    
        result = test(foo);
    
        // could use a conditional - I just hate using them
        if(result)
        {
            c = a;
        }
        else
        {
            c = b;
        }
    
        return (c);
    }
    
    for(......)
    {
        final Collection<Whatever> c;
        final Whatever             foo;
    
        foo = ...;
        c = chooseCollection(foo, cOne, cOther);
        c.add(foo;
    }
    
    (……)的
    
    {
    最终收集c;
    最后,不管是什么,富;
    foo=。。。;
    c=选择集合(foo、cOne、cOther);
    c、 添加(foo;
    }
    

    本质上,我为{}块内部的任何内容创建了一个方法,如果它有意义的话(通常是这样)。我喜欢有很多小方法。

    除了matt b所说的,当您决定使用条件运算符时,您可以进一步使用此格式:

    SomeClass component = test(foo) 
       ? cOne 
       : cTheOther;
    component.add(foo);
    

    它使代码更像if-else,更易于阅读。

    使用条件运算符的一个潜在问题是参数开始变得更复杂。例如,如果以下行抛出NullPointerException:

    String aString = obj1.getValue() == null ? obj2.getString() : obj1.getValue().getString();
    
    三个解引用中的哪一个是导致NPE的原因?
    obj1
    obj2
    obj1.getValue()
    有时可以通过前面代码中的推理来解决,但并不总是

    也就是说,比较以下两段代码:

    final String aString = obj1 == null ? "default" : obj1.getString();
    
    vs

    大多数人会争辩说,条件句更容易阅读,当然也更简洁

    现在,有了这个问题,我会使用条件调用方法吗?不,它增加了很多视觉复杂性,我们必须记住,调试的难度是编写代码的两倍。这意味着代码越简单,您或其他人在六个月内理解它就越简单。我非常乐意使用条件调用方法他两里