53

我想知道是否可以进行三元运算但不返回任何内容。

如果在 Java 中不可能,那么在其他语言中是否可能,如果可以,哪些适用?

name.isChecked() ? name.setChecked(true):name.setChecked(false);
4

6 回答 6

60

不,你不能。但是这个if-else声明有什么意义呢?您真的要保存 7 个字符吗?

if (name.isChecked()) {
    name.setChecked(true);
} else {
    name.setChecked(false);
}

或者如果你喜欢糟糕的风格:

if (name.isChecked()) name.setChecked(true); else name.setChecked(false);

别介意你可以这样做(在这种情况下):

name.setChecked(name.isChecked());

三元或“条件”运算符的要点是在表达式中引入条件。换句话说,这:

int max = a > b ? a : b;

是为此的简写:

int max;
if ( a > b ) {
    max = a;
} else {
    max = b;
}

如果没有产生值,则条件运算符不是捷径。

于 2012-02-26T05:42:11.980 回答
15

我想知道是否可以进行三元运算但不返回任何内容。

不,这是不可能的:

  1. 第二和第三个操作数必须是非空表达式;即它们必须产生一些实际价值。

    “第二个或第三个操作数表达式调用 void 方法是编译时错误。” - JLS 15.25

  2. 三元表达式是表达式,不能用作语句。

    “某些类型的表达式可以通过在它们后面加上分号来用作语句。” ...并且三元表达式不是其中一种- JLS 14.8

如果您真的非常想使用三元表达式但不使用表达式的值,那么最简单的方法是将值分配给虚拟变量,并添加注释以抑制有关未使用变量的警告。

但更好的主意是使用简单的if语句。

如果在 Java 中不可能,那么在其他语言中是否可能,如果可以,哪些适用?

我有点生疏,但我相信 C、C++ 和 Perl 都允许在不使用其值的地方使用任意表达式。

于 2012-02-26T06:12:07.333 回答
7

有时,您可以对方法参数使用三元运算来解决您的请求。

name.setChecked(name.isChecked() ? true : false);

顺便说一句,您的问题的最佳解决方案是

name.setChecked(name.isChecked());
于 2012-02-26T06:01:53.640 回答
0

在java中下面的代码是不可能的:

(your-condition) ? (true-statements) : (false-statements)

对于示例,您无法编译以下片段代码:

(1==1) ? System.out.println("") : System.out.println("");

您实现以下编译错误:

The left-hand side of an assignment must be a variable
于 2012-02-26T05:48:46.027 回答
0

您必须返回一些值,如果您希望它像 void 方法一样执行某些操作而不返回值,它将无法工作。

希望这可以帮助...

于 2016-12-20T05:21:49.483 回答
0

我认为问题中的用例只是一个糟糕的例子,因为它等同于以下语句:

name.setChecked(name.isChecked());

......这也没有意义。但是意图很明确,确实有很多相关的用例。

唯一可行且通用的解决方案是添加这样的辅助方法:

static void ternaryVoid(boolean condition, Runnable ifTrue, Runnable ifFalse) {
    (condition ? ifTrue : ifFalse).run();
}

并像这样使用它:

ternaryVoid(name.isChecked(), () -> name.setChecked(true), () -> name.setChecked(false));

但它失去了三元运算符的优雅,只有在代码的多个部分使用并且纳秒无关紧要时才值得“努力”。

但是,与 if-else 语句相比,这有什么意义呢?您真的要保存 7 个字符吗?

我很惊讶这样的陈述以一种反问的形式出现。是的,节省 4 行代码并使代码更优雅很重要,尤其是在函数式编程的上下文中。

此外,方法是否void返回完整的Void. 本质上,它们返回完成任务的通知。这就是为什么从逻辑上讲,三元表达式无论返回什么或什么都不返回都同样有意义:

condition ? doThis() : doThat();

下面是一个类的真实世界示例,它每秒可以处理数百万次增量更新:

public class DataHandler {

    private final TreeMap<Integer, Long> tree = new TreeMap<>();

    public void onUpdate(int price, long amount) {
        if (amount == 0) {
            tree.remove(price);
        } else {
            tree.put(price, amount);
        }
    }
}

如果允许,该onUpdate()方法将是一个很好的三元表达式,如下所示:

public void onUpdate(int price, long amount) {
    (amount == 0) ? tree.remove(price) : tree.put(price, amount); // compilation error
}

幸运的是,在某些情况下,这两个目标方法都返回值,并且这些值的类型相同Long在这种情况下也是如此。这允许使onUpdate方法返回前一个amountat price(这甚至很有用)

public Long onUpdate(int price, long amount) {
    return (amount == 0) ? tree.remove(price) : tree.put(price, amount);
}

...或者(例如,如果方法由接口确定),使用虚拟变量并抑制其无用警告:

public void onUpdate(int price, long amount) {
    @SuppressWarnings("unused")
    Long dummy = (amount == 0) ? tree.remove(price) : tree.put(price, amount);
}

否则,这些解决方案不适用,并且正如其他人所回答的那样,不存在。例如,可以尝试以下操作:

Consumer<Void> dummy = (x) -> {};
dummy.accept(/*...*/);

但有趣的是,第二行编译时既没有任何东西也没有任何东西作为参数。

似乎最好的通用解决方案是上述辅助方法ternaryVoid()

于 2020-07-28T20:42:30.347 回答