首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么“a^=b^=a^=b”与"a^=b;b^=a;a^=b;“不同?

为什么“a^=b^=a^=b”与"a^=b;b^=a;a^=b;“不同?
EN

Stack Overflow用户
提问于 2014-02-26 14:19:39
回答 5查看 7.4K关注 0票数 20

我尝试了一些代码来交换Java中的两个整数,而不使用第三个变量,使用XOR。

下面是我尝试过的两个交换函数:

代码语言:javascript
复制
package lang.numeric;

public class SwapVarsDemo {

    public static void main(String[] args) {
        int a = 2984;
        int b = 87593;
        swapDemo1(a,b);
        swapDemo2(a,b);
    }

    private static void swapDemo1(int a, int b) {
        a^=b^=a^=b;
        System.out.println("After swap: "+a+","+b);
    }

    private static void swapDemo2(int a, int b) {
        a^=b;
        b^=a;
        a^=b;
        System.out.println("After swap: "+a+","+b);
    }

}

该代码产生的输出如下:

代码语言:javascript
复制
After swap: 0,2984
After swap: 87593,2984

我很想知道,为什么这样说:

代码语言:javascript
复制
        a^=b^=a^=b;

和这个不一样?

代码语言:javascript
复制
        a^=b;
        b^=a;
        a^=b;
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-02-26 14:46:48

问题是评价的顺序:

请参阅JLS section 15.26.2

首先计算左操作数以产生一个变量。如果此计算突然完成,则赋值表达式出于同样的原因突然完成;右操作数不计算,也不发生赋值。 否则,保存左操作数的值,然后计算右操作数.如果此计算突然完成,则赋值表达式出于相同的原因突然完成,并且不会发生赋值。 否则,将使用左边变量的保存值和右侧操作数的值来执行由复合赋值运算符指示的二进制操作。如果此操作突然完成,则分配表达式将基于相同的原因突然完成,并且不会发生赋值。 否则,二进制操作的结果被转换为左手变量的类型,并经过值集转换(§5.1.13)到适当的标准值集(而不是扩展指数值集),并将转换结果存储到变量中。

所以你的表情是:

a^=b^=a^=b;

  1. 评估a
  2. 评估b^=a^=b
  3. xor这两个(因此第一步中的a还没有应用^=b )
  4. 将结果存储在a

换句话说,表达式等价于以下java代码:

代码语言:javascript
复制
    int a1 = a;
    int b2 = b;
    int a3 = a;
    a = a3 ^ b;
    b = b2 ^ a;
    a = a1 ^ b;

您可以从方法的分解版本中看到这一点:

代码语言:javascript
复制
  private static void swapDemo1(int, int);
    Code:
       0: iload_0       
       1: iload_1       
       2: iload_0       
       3: iload_1       
       4: ixor          
       5: dup           
       6: istore_0      
       7: ixor          
       8: dup           
       9: istore_1      
      10: ixor          
      11: istore_0  
票数 40
EN

Stack Overflow用户

发布于 2014-02-26 14:27:05

因为a ^= b ^= a ^= b;被解析为:

代码语言:javascript
复制
a ^= (b ^= (a ^= b));

可简化为:

代码语言:javascript
复制
a ^= (b ^= (a ^ b));

因此,b将具有b ^ (a ^ b)值,最后a将为a ^ (b ^ (a ^ b)

票数 7
EN

Stack Overflow用户

发布于 2014-02-26 14:29:35

检查操作符优先级(ref:由于搜索java操作符优先级而产生的http://introcs.cs.princeton.edu/java/11precedence/ )。这里出现了对Oracle的引用(http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html),尽管它有点密集)。

特别是,^=是从右到左(不是从左到右)处理的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22044163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档