Java (a!=b)和(a!=b)之间的区别是什么?

Java (a!=b)和(a!=b)之间的区别是什么?,java,comparison,operators,Java,Comparison,Operators,在a中,我们发现了以下代码: // p, t, q and tail are Node<E> objects. p = (p != t && t != (t = tail)) ? t : q; 考虑到这些都是相同类型的对象,无论是什么类型。这与: t != tail 还是我在比较机制中遗漏了一些关键的东西 编辑 如果有人想知道的话,可以在java.util第352行的类中找到 t != (t = tail) 相当于 oldt = t; t = tail; ..

在a中,我们发现了以下代码:

// p, t, q and tail are Node<E> objects.
p = (p != t && t != (t = tail)) ? t : q;
考虑到这些都是相同类型的对象,无论是什么类型。这与:

t != tail
还是我在比较机制中遗漏了一些关键的东西


编辑

如果有人想知道的话,可以在
java.util
第352行的类中找到

t != (t = tail)
相当于

oldt = t;
t = tail;
... oldt != t...
synchronized(x) {
    t = tail;

    if(t != t) {
        // ...
    }
}
i、 e.
t
的原始值与
tail
进行比较,此外
t
被指定为
tail
的值

这是一种简短的写作方式

if (t != tail) {
    t = tail;
}
第一个代码:

t != (t = tail)
将tail赋值给t,然后将t与新值进行比较


第二个答案将t与tail进行比较。注意:另一个答案是Java实际上在做什么

synchronized(x) {
     if(t != (t = tail));
}
相当于

oldt = t;
t = tail;
... oldt != t...
synchronized(x) {
    t = tail;

    if(t != t) {
        // ...
    }
}
基本上,对所分配内容的引用由()运算符返回

public class Test {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;

        if(a != (b = a)) {
            System.out.println("however, there is an issue with a != (a = b), Java bug");
        } else {
            System.out.println("assignment first, obvious by inspection");
        }
    }
}
然而,同样的代码在C中也能工作。如果我不得不猜测,这在Java中是无意的,在类似这样的事情上与C的任何偏离都是愚蠢的。Oracle可能不希望对它进行评论,假设它是无意的错误,很可能是这样

我会在下次和他们谈话的时候说的。我仍然对他们在国防部的整个住所的惨败感到愤怒,那次惨败涉及到我母亲的主页与苹果公司勾结设置为ask.com。在我不得不点击400多次,以便在我女儿的手机重新下载失败后重试后,苹果在不到一周的时间内修复了iTunes但视频库,所以这个问题仅限于甲骨文。它也影响了微软,所以每个人都为之疯狂

#include <iostream>

static int ref = 0;

class t {
public:
    t(int x) : x(x), r(ref) { ref++; }
    t(const t& o) : x(o.x), r(o.r) { }
    t& operator=(const t& o) { x = o.x; r = o.r; return *this; }
    bool operator!=(const t& o) const { return r != o.r; }
private:
    int x;
    int r;
};

int main() {
    t a(1);
    t b(2);

    if(a != (a = b)) {
        std::cout <<  "assignment\n";
    } else {
        std::cout <<  "no assignment\n";
    }

    return 0;
}
#包括
静态int ref=0;
t类{
公众:
t(intx):x(x),r(ref){ref++;}
t(常数t&o):x(o.x),r(o.r){}
t&operator=(常量t&o){x=o.x;r=o.r;返回*this;}
布尔运算符!=(常量t&o)常量{返回r!=o.r;}
私人:
int x;
INTR;
};
int main(){
tα(1);
tb(2);
如果(a!=(a=b)){

std::cout single'='是一个矫揉造作的运算符。这是一种扭曲的方法,将t指定给tail,然后检查它对tail的引用不等式(此时该值总是false)区别在于,第一个t得到tail的值,第二个不是。@YassineBadache我讨厌在任何代码中看到这些构造。在核心java中使用它确实不太令人放心:)对于好奇的人来说:
ConcurrentLinkedQueue
中从“简单”实现到这个“复杂”实现的步骤似乎是(!)正如你所知,@Eugene他的风格和这种极端的微优化已经出现了。以前版本的代码(使用
继续重试;
)也是我在代码评审中永远不会接受的东西,但代码库的这一部分是非常特殊和微妙的。我只是想(或者只是希望?——至少:我必须假设)Doug Lea有着深刻的技术原因,可以这样做,我很想听到他们的声音,不过……我想说得更好。Oracle开发人员有时会有一些奇怪的处理方式。我想知道他们是否有自己的理由。谢谢!@AbdulAhad我知道你在回答中所说的,但如果你是对的,情况总是会被评估为错误的(除非其他线程在赋值之后和条件之前更改了t的值),这不是真的。请尝试运行
int t=1;int tail=2;if(t!=(t=tail))System.out.println(“不相等”);
。您将看到“不相等”是印刷的。@Eran好吧,这似乎不是完全一样的事情……有时这很重要:。但是,我也没有深入到OP的问题代码中,以非常确定我认为你所说的“短途”至少是误导性的(如果不是错的话)。赋值
t=tail
总是发生,而且不仅仅是当它们不相等时。关键是条件检查值是否因该赋值而改变。这在回答的第一部分中比较清楚,但是
可以被适当的
if
替换。编辑:(关于您在上面的第一个评论):我认为这一点是为了检测是否有另一个线程修改了
尾部
@Marco13。很高兴不仅仅是我这么想。由于这是一个并发数据结构,可能有人在您查看它时已经删除了尾部。据我所知,这是这段代码所做的,嗯,实际上不是。使用的对t的第一个引用是在等号右侧赋值之前进行计算的。我和你一样认为是第一个,但这段代码证明它是错误的:
Object p=null,t=“t”,tail=“tail”,q=“q”;p=(p!=t&&t!=(t=tail))?t:q;System.out.println(p);//show“tail”
仍然不走运。再试一次:)