Jay*_*667 2 java lambda equals-operator java-8
(最后的实际问题)
你好,世界!我在这里发生了一些令人不安的事情,我无法绕过头...
像我一样懒惰,我讨厌一遍又一遍地重新实施愚蠢的euqals()方法; 还有hashCode()方法,但仍然关注选定成员变量的"相等".我还可以通过使用检查类实例或使用反射的默认接口来减少实现,但我想我已经使用了这个静态实用程序方法和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));
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
所以......我期待所有的5个变种(eq,==,Implicit,eqName,==name)给我回了相同的结果(真,假,假,真)...
但是eqName,==name不要.为什么他们返回a=c作为true代替false?
它与那里发生的阴影名称有关吗?所以不是访问CC.name比较lambda总是访问CA.name?
分析为什么以下结果是 true
equals_internal(a, c, (p1, p2) -> p1.name == p2.name)
Run Code Online (Sandbox Code Playgroud)
你必须看看签名equals_internal:
equals_internal(final T pThisObject, final Object pOtherObject, final JcLambda_pG1_pG1_rBool<T> pEqualizer)
Run Code Online (Sandbox Code Playgroud)
所以在这种情况下,T是类型a,即CA.
因此,JcLambda_pG1_pG1_rBool<T>传递给静态方法的是a JcLambda_pG1_pG1_rBool<CA>,这意味着p1并且p2是类型CA,因此p1.name == p2.name比较name基类的属性CA,并且"Bier" == "Bier"由于字符串池而为true.
结果equals_internal(a, c, (p1, p2) -> p1.name.equals(p2.name))是true出于同样的原因(只有在这里你不必依赖于String池,因为你正在使用String它们"Bier",所以两者都返回相同的实例String.equals).
在前3个案例中,结果是不同的,因为您正在使用getName()在子类中重写的方法,并返回子类的name属性.
总而言之,不同的行为是由以下事实引起的:与方法不同,实例变量无法被覆盖.