gpt4 book ai didi

Java 8、等于、== 和 Lambda

转载 作者:行者123 更新时间:2023-12-03 07:10:15 25 4
gpt4 key购买 nike

(实际问题在最后)

世界你好!这里发生了一些令人不安的事情,我无法理解......

尽管我很懒,但我讨厌一遍又一遍地重新实现愚蠢的 euqals() 方法;也是 hashCode() 方法,但仍然将“相等”重点放在选定的成员变量上。我还可以通过使用检查类实例的默认接口(interface)或使用反射来减少实现,但我认为我可以使用此静态实用程序方法和 labmda:

public class StackOverflow_TestEq {

static public interface JcLambda_pG1_pG1_rBool<T> {
boolean test(T p1, T p2);
}

static public <T> boolean equals_internal(final T pThisObject, final Object pOtherObject, final JcLambda_pG1_pG1_rBool<T> pEqualizer) {
if (pThisObject == null) return pOtherObject == null;
if (pOtherObject == null) return false;

final Class<? extends Object> thisClass = pThisObject.getClass();
if (!thisClass.isInstance(pOtherObject)) return false;

@SuppressWarnings("unchecked") final T other = (T) pOtherObject;
final boolean res = pEqualizer.test(pThisObject, other);
// System.out.println("Testing " + pThisObject + " vs " + other + " => " + res);
return res;
}

/*
* TEST DEFINES
*/

static private interface CNameable {
String getName();
}
static private class CA implements CNameable {
String name = "Bier";
@Override public String toString() {
return getClass().getSimpleName() + "." + name;
}
@Override public String getName() {
return name;
}
}
static private class CB implements CNameable {
String name = "Schnaps";
@Override public String toString() {
return getClass().getSimpleName() + "." + name;
}
@Override public String getName() {
return name;
}
}
@SuppressWarnings("synthetic-access") static private class CC extends CA {
@SuppressWarnings({ "hiding" }) String name = "Wein";
@Override public String toString() {
return getClass().getSimpleName() + "." + name;
}
@Override public String getName() {
return name;
}
}
@SuppressWarnings("synthetic-access") static private class CD extends CA {
@SuppressWarnings({ "hiding" }) String name = "Bier";
@Override public String toString() {
return getClass().getSimpleName() + "." + name;
}
@Override public String getName() {
return name;
}
}

/*
* TEST
*/

@SuppressWarnings("synthetic-access") public static void main(final String[] args) {
final CA a = new CA();
final CB b = new CB();
final CC c = new CC();
final CD d = new CD();
final JcLambda_pG1_pG1_rBool<CNameable> res = new JcLambda_pG1_pG1_rBool<CNameable>() {
@Override public boolean test(final CNameable pP1, final CNameable pP2) {
// return pP1.getName().equals(pP2.getName());
return pP1.getName() == pP2.getName();
}
};

System.out.println("\nExplicit eq");
System.out.println("a=a:" + equals_internal(a, a, (p1, p2) -> p1.getName().equals(p2.getName())));
System.out.println("a=b:" + equals_internal(a, b, (p1, p2) -> p1.getName().equals(p2.getName())));
System.out.println("a=c:" + equals_internal(a, c, (p1, p2) -> p1.getName().equals(p2.getName())));
System.out.println("a=d:" + equals_internal(a, d, (p1, p2) -> p1.getName().equals(p2.getName())));

System.out.println("\nExplicit ==");
System.out.println("a=a:" + equals_internal(a, a, (p1, p2) -> p1.getName() == p2.getName()));
System.out.println("a=b:" + equals_internal(a, b, (p1, p2) -> p1.getName() == p2.getName()));
System.out.println("a=c:" + equals_internal(a, c, (p1, p2) -> p1.getName() == p2.getName()));
System.out.println("a=d:" + equals_internal(a, d, (p1, p2) -> p1.getName() == p2.getName()));

System.out.println("\nImplicit");
System.out.println("a=a:" + equals_internal(a, a, res));
System.out.println("a=b:" + equals_internal(a, b, res));
System.out.println("a=c:" + equals_internal(a, c, res));
System.out.println("a=d:" + equals_internal(a, d, res));

System.out.println("\nExplicit eqName");
System.out.println("a=a:" + equals_internal(a, a, (p1, p2) -> p1.name.equals(p2.name)));
System.out.println("a=b:" + equals_internal(a, b, (p1, p2) -> p1.name.equals(p2.name)));
System.out.println("a=c:" + equals_internal(a, c, (p1, p2) -> p1.name.equals(p2.name)));
System.out.println("a=d:" + equals_internal(a, d, (p1, p2) -> p1.name.equals(p2.name)));

System.out.println("\nExplicit ==name");
System.out.println("a=a:" + equals_internal(a, a, (p1, p2) -> p1.name == p2.name));
System.out.println("a=b:" + equals_internal(a, b, (p1, p2) -> p1.name == p2.name));
System.out.println("a=c:" + equals_internal(a, c, (p1, p2) -> p1.name == p2.name));
System.out.println("a=d:" + equals_internal(a, d, (p1, p2) -> p1.name == p2.name));
}



}

输出:

Explicit eq
a=a:true
a=b:false
a=c:false
a=d:true

Explicit ==
a=a:true
a=b:false
a=c:false
a=d:true

Implicit
a=a:true
a=b:false
a=c:false
a=d:true

Explicit eqName
a=a:true
a=b:false
a=c:true
a=d:true

Explicit ==name
a=a:true
a=b:false
a=c:true
a=d:true

所以...我期待所有 5 个变体(eq==ImpliciteqName , ==name) 给我返回相同的结果 (true, false, false, true)...

但是 eqName==name 则不然。为什么它们返回 a=c 作为 true 而不是 false

这与那里发生的名称隐藏有关吗?因此,比较 lambda 始终访问 CA.name,而不是访问 CC.name

最佳答案

来分析为什么下面的结果是true

equals_internal(a, c, (p1, p2) -> p1.name == p2.name)

你必须看equals_internal的签名:

equals_internal(final T pThisObject, final Object pOtherObject, final JcLambda_pG1_pG1_rBool<T> pEqualizer)

所以在这种情况下,T类型为a ,即CA .

因此JcLambda_pG1_pG1_rBool<T>您传递给静态方法的是 JcLambda_pG1_pG1_rBool<CA> ,这意味着 p1p2类型为CA ,所以p1.name == p2.name比较 name基类的属性CA ,和"Bier" == "Bier"由于字符串池,为 true。

equals_internal(a, c, (p1, p2) -> p1.name.equals(p2.name))的结果是 true出于同样的原因(仅在这里,您不必依赖字符串池为 String 返回相同的 "Bier" 实例,因为您正在使用 String.equals )。

在前 3 种情况中,结果不同,因为您使用的是 getName()方法,该方法在子类中被重写,并返回 name子类的属性。

总而言之,不同的行为是由以下事实引起的:与方法不同,实例变量无法被覆盖。

关于Java 8、等于、== 和 Lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45436127/

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