有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java 8,等于,==和Lambdas

(最后的实际问题)

你好,世界! 我这里发生了一些令人不安的事情,我无法控制自己

虽然我很放荡,但我讨厌一次又一次地重复那些愚蠢的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));
    }



}

输出:

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)都能返回相同的结果(真、假、假、真)

但是eqName==name没有。为什么他们将a=c返回为true而不是false

这和那里正在发生的名字阴影有关吗?所以比较lambda不是访问CC.name,而是总是访问CA.name


共 (1) 个答案

  1. # 1 楼答案

    简单一点,考虑到这一点:

    static class A {
        public String name = "A";
    }
    
    static class B extends A {
        public String name = "B";
    }
    
    public static void main(String[] args) {
        B b = new B(); // line 57
    
        System.out.println(b.name); // B
        System.out.println(((A) b).name); // A
    }
    

    如果要调试并在理论上的line 57处停止,Eclipse调试器会说b实例有两个名为name的字段