-->

为什么不是Java具备的条件,以及和条件,或者运营商的复合赋值版本? (&& =

2019-07-20 11:12发布

因此,对于在布尔二元运算符,Java有&|^&&||

让我们来总结一下他们在这里简单做什么:

  • JLS 15.22.2布尔逻辑运算符&,^和|
  • JLS 15.23条件与运算&&
  • JLS 15.24条件或运算符||

对于& ,结果值是true如果两个操作数的值是true ; 否则,结果是false

对于| 时,结果值是false如果两个操作数的值是false ; 否则,结果是true

对于^ ,结果值是true ,如果操作数的值是不同的; 否则,结果是false

&&运算符是像&但评估其右边的操作数只有在其左侧操作数的值是true

|| 运营商好像| ,但评估其右边的操作数只有在其左侧操作数的值是false

现在,所有5间,那些3有复合赋值的版本,即|=&=^= 。 所以我的问题是显而易见的:为什么不是Java提供&&=||=呢? 我发现我需要那些比我更需要&=|=

我不认为“因为它太长”是一个很好的答案,因为Java具有>>>= 。 必须有这种遗漏一个更好的理由。


从15.26赋值运算符 :

有12个赋值运算符; [...] = *= /= %= += -= <<= >>= >>>= &= ^= |=


注释有人认为,如果&&=||=得以实施,那么这将是不首先评估右手边的唯一运营商。 我认为这个概念是一个复合赋值操作符先计算右手边是一个错误。

从15.26.2复合赋值运算符 :

形式的化合物,赋值表达式E1 op= E2相当于E1 = (T)((E1) op (E2))其中T是的类型E1 ,除了E1只计算一次。

为了证明这一点,下面的片段抛出一个NullPointerException ,而不是一个ArrayIndexOutOfBoundsException

    int[] a = null;
    int[] b = {};
    a[0] += b[-1];

Answer 1:

原因

运算符&&=||=并非适用于Java的 ,因为大多数的开发者,这些运营商包括:

  • 容易出错
  • 无用

例如用于&&=

如果你的Java允许&&=运算符,则该代码:

bool isOk = true; //becomes false when at least a function returns false
isOK &&= f1();
isOK &&= f2(); //we may expect f2() is called whatever the f1() returned value

将相当于:

bool isOk = true;
if (isOK) isOk = f1();
if (isOK) isOk = f2(); //f2() is called only when f1() returns true

这第一个代码是容易出错的 ,因为许多开发商会认为f2()始终称为无论F1()返回的值。 它像bool isOk = f1() && f2(); 其中f2()被调用,只有当f1()返回true

如果开发人员希望f2()被调用,只有当f1()返回true ,因此,第二代码是以上更不易出错。

否则&=是足够的,因为开发人员希望f2()将总是叫:

相同的例子,但对于&=

bool isOk = true;
isOK &= f1();
isOK &= f2(); //f2() always called whatever the f1() returned value

此外,JVM应为以下之一运行该上面的代码:

bool isOk = true;
if (!f1())  isOk = false;
if (!f2())  isOk = false;  //f2() always called

比较&&&结果

是运营商的结果&&&一样当布尔值应用?

让我们来看看使用Java代码:

public class qalcdo {

    public static void main (String[] args) {
        test (true,  true);
        test (true,  false);
        test (false, false);
        test (false, true);
    }

    private static void test (boolean a, boolean b) {
        System.out.println (counter++ +  ") a=" + a + " and b=" + b);
        System.out.println ("a && b = " + (a && b));
        System.out.println ("a & b = "  + (a & b));
        System.out.println ("======================");
    }

    private static int counter = 1;
}

输出:

1) a=true and b=true
a && b = true
a & b = true
======================
2) a=true and b=false
a && b = false
a & b = false
======================
3) a=false and b=false
a && b = false
a & b = false
======================
4) a=false and b=true
a && b = false
a & b = false
======================

所以是的 ,我们可以更换&&通过&布尔值;-)

因此,更好地利用&=代替&&=

同为||=

同样的理由,作为&&=
操作者|=是容易出错小于||=

如果开发者想f2()不时称为f1()返回true ,那么我建议以下选择:

// here a comment is required to explain that 
// f2() is not called when f1() returns false, and so on...
bool isOk = f1() || f2() || f3() || f4();

要么:

// here the following comments are not required 
// (the code is enough understandable)
bool isOk = false;
if (!isOK) isOk = f1();
if (!isOK) isOk = f2(); //f2() is not called when f1() returns false
if (!isOK) isOk = f3(); //f3() is not called when f1() or f2() return false
if (!isOK) isOk = f4(); //f4() is not called when ...


Answer 2:

大概是因为像

x = false;
x &&= someComplexExpression();

看起来应该被分配给x和评价someComplexExpression()但该评价取决于的值的事实x不是从语法显而易见。

也正因为Java的语法是基于C,也没有人看到,迫切需要补充的经营者。 你可能会是与if语句更好,反正。



Answer 3:

正是这种方式在Java中,因为它是这样的C.

现在的问题是,为什么它是如此的C是因为当&和&&成为不同运营商(从B C的后裔之前的某个时候),在&=各种运营商简单地忽视。

但是我的回答的第二部分没有任何来源,以支持它。



Answer 4:

一个Java的原始目的是要“简单,面向对象,和熟悉的。” 作为适用于这种情况下,&=熟悉(C,C ++有它在这方面,熟悉意味着熟悉的人谁知道这两个)。

&& =不熟悉,并且它不会是简单的,在这个意义上,语言的设计者并没有寻求认为他们可以添加到语言各运营商的,所以不太额外运营商更简单。



Answer 5:

这主要是因为Java的语法是基于C(或至少是C家),并在C中的所有的赋值操作符被编译到算术或按位汇编指令对单个寄存器。 赋值操作符版本,避免临时对象,并可能会产生对早期非优化编译器效率更高的代码。 上述逻辑运算器(因为它们是用C称为)当量( &&=||= )不具有这样的明显的对应于单个组件的指令; 它们通常扩大到指令测试和分支序列。

有趣的是,像Ruby语言确实有|| =和&& =。

编辑:术语Java和C之间不同



Answer 6:

对于布尔乏,&&和|| 将使用短路评价而&和| 不这样做,所以你可能认为&& =和|| =也使用短路评价。 这是一个很好的用例此。 特别是如果你迭代一个循环,你想快速,高效和简洁。

相反,写作

foreach(item in coll)
{
   bVal = bVal || fn(item); // not so elegant
}

我想写

foreach(item in coll)
{
  bVal ||= fn(item);    // elegant
}

并且知道,一旦BVAL是真实的,FN()将不会被要求对迭代的剩余部分。



Answer 7:

& ”和“ && ”是不一样的“ && ”是短切操作时,如果第一个操作数是假,而“这不会做& ”会做吧(既数和布尔工作)。

我不同意,它更有意义的存在,但如果它不存在它不是那么糟糕。 我想这是不存在,因为C没有它。

实在想不出为什么。



Answer 8:

它允许在Ruby中。

如果我猜,我会说,它不经常使用,因此没有实现。 另一种解释可能是,分析器只着眼于字符=前



Answer 9:

我想不出什么更好的理由那么“它看起来不可思议的难看!”



Answer 10:

验证两个操作数,它是位运算符。 Java定义几个位运算符,其可被施加到整型,长,整型,短整型,char和字节。

&&

如果停止第一个操作数的计算结果为假,因为其结果将是错误的,这是一个逻辑运算符评估。 它可以应用到布尔值。

&&运算符是类似与运营商,但可以让你的代码有点更高效。 因为通过比较两个表达式&操作必须是真实的,整个表达式是真实的,没有任何理由,如果第一个返回false评估第二表达式。 &运算符始终计算两个表达式。 &&运算符的计算结果只如果第一个表达式为真第二个表达式。

有一个&& =赋值运算符不会真的添加新功能的语言。 该位运算符的运算是更富于表现力,你可以做整数运算按位,其中包括布尔运算。 逻辑运算符可以仅仅做布尔运算。



Answer 11:

A&B和&& b是不一样的东西。

一个&& b是布尔表达式,返回布尔值,并且a和b是一个位表达式返回int(如果a和b是整数)。

whare你觉得他们是一样的吗?



文章来源: Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=)