gpt4 book ai didi

Groovy == 不符合规范

转载 作者:行者123 更新时间:2023-12-02 01:00:32 27 4
gpt4 key购买 nike

所以根据the official documentation ==行为类似于 compareTo在可比较对象上调用时。

现在我有这样的课:

class LargeNum implements Serializable, Comparable<BigInteger>

它定义了方法
@Override
int compareTo(BigInteger o) throws NullPointerException, ClassCastException {
println "compared"
return compareStuff()
}

你会期待这段代码:
LargeNum t = new LargeNum(1)
println t == new BigInteger(1)

打印出“比较”并调用 compareStuff ,虽然它没有。我收到的唯一输出是: false
我真的很困惑为什么会这样。覆盖 equals也不能完全解决问题。

最佳答案

在这种情况下,文档不清楚 - .compareTo(Object obj)被调用而不是 .equals(Object obj)如果您使用 ==两个相同类型对象之间的运算符 T实现 Comparable<T> .在您的示例类(class)中 LargeNum实现 Comparable<BigInteger> - 在这种情况下

new LargeNum(1) == new LargeNum(1)

将调用 .equals(Object obj)方法而不是 .compareTo(Object obj) .

如果您实现 Comparable<LargeNum>你比较
new LargeNum(1) == new LargeNum(1)
.compareTo(Object obj)开始。考虑以下示例:

class LargeNum implements Comparable<LargeNum> {

private final BigInteger number

LargeNum(BigInteger number) {
this.number = number
}

@Override
int compareTo(LargeNum num) {
println "compared"
return number <=> num.number
}
}

LargeNum num1 = new LargeNum(1)
LargeNum num2 = new LargeNum(1)

println num1 == num2

运行此示例会产生以下输出:
compared
true

我可以覆盖 ==带有 .equals(Object obj) 的运算符这种情况下的方法?

简短的回答 - 不。要了解为什么以及会发生什么,我们需要深入研究一下字节码。以下部分代码:
LargeNum num1 = new LargeNum(1)
LargeNum num2 = new LargeNum(1)
BigInteger bigInt1 = new BigInteger(1)

println num1 == num2

println num1 == bigInt1

表示为以下反编译为 Java 的字节码:
LargeNum num1 = (LargeNum)ScriptBytecodeAdapter.castToType(var1[1].callConstructor(LargeNum.class, 1), LargeNum.class);
LargeNum num2 = (LargeNum)ScriptBytecodeAdapter.castToType(var1[2].callConstructor(LargeNum.class, 1), LargeNum.class);
BigInteger bigInt1 = (BigInteger)ScriptBytecodeAdapter.castToType(var1[3].callConstructor(BigInteger.class, 1), BigInteger.class);
var1[4].callCurrent(this, ScriptBytecodeAdapter.compareEqual(num1, num2));
return var1[5].callCurrent(this, ScriptBytecodeAdapter.compareEqual(num1, bigInt1));

它表明 num1 == bitInt1实际上是 ScriptBytecodeAdapter.compareEqual(num1, bigInt1) .如果我们看一下 source code我们会发现在我们的例子中这个方法执行方法:
DefaultTypeTransformation.compareEqual(left, right);

现在,如果我们看一下 the implementation of this method看起来我们会发现这样的东西:

public static boolean compareEqual(Object left, Object right) {
if (left == right) return true;
if (left == null) return right instanceof NullObject;
if (right == null) return left instanceof NullObject;
if (left instanceof Comparable) {
return compareToWithEqualityCheck(left, right, true) == 0;
}
// handle arrays on both sides as special case for efficiency
Class leftClass = left.getClass();
Class rightClass = right.getClass();
// some other stuff here
}

它表明对于任何 Comparable以下部分的对象被执行:
if (left instanceof Comparable) {
return compareToWithEqualityCheck(left, right, true) == 0;
}

The implementation of this method揭示如果两个对象是相同类型或者它们可以被强制转换为公共(public)类型, .compareTo(Object obj)方法被触发。否则它只会返回 -1 .如果我们尝试比较 LargeNum,就会发生这种情况。和 BigInteger - 这两个类之间没有共同点,所以至少对于 Groovy 来说,它们没有可比性。

我不知道这是否是错误,没有回退到 .equals(Object obj)方法。或者,您始终可以直接调用特定方法,例如:
num1.equals(bigInt1)

或者
num1.compareTo(bigInt1) // num1 <=> bigInt1

但是我知道 == 的这种行为 Comparable 的运算符可能非常反直觉和烦人。特别是如果你定义你的类来实现 Comparable<Object> - 我希望任何对象都被传递给被覆盖的 .compareTo(Object obj)但它不是:/

希望能帮助到你。

关于Groovy == 不符合规范,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50988701/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com