Page 1 of 1

About Question enthuware.ocpjp.v8.2.1340 :

Posted: Sat Dec 05, 2015 6:41 pm
by 232vin
Hi,

After some analysis, I'm thinking that option 2 is wrong because it's not symmetric, one of the rules of the equals method.
return theval%2 == 0? true :false;

Code: Select all

//in main method inside the class

GoodOne o = new GoodOne();
o.theval = 0;
GoodOne g = new GoodOne();
g.theval= 1;
	
System.out.println(o.equals(g));	//true
System.out.println(g.equals(o)); //false

Am I right? Is there anyone here who discover that?

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Sat Dec 05, 2015 8:04 pm
by admin
You are talking about option 3 (not 2).
Yes, that is also one of the reasons why the equals method is invalid. Another reason is that it violates the equals/hashcode contract as explained by the explanation.
HTH,
Paul.

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Sun Dec 06, 2015 6:06 am
by 232vin
Oh yes! I'm sorry, it's 3.hehe
Thanks for the help!
Vinicius.

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Wed Jun 22, 2016 2:52 am
by Sarkhan
i think rigth answer talks about n>=3.numbers 0<n<3 it doesnt return true;

GoodOne obj = new GoodOne();
obj.theval = 2;

GoodOne obj2 = new GoodOne();
obj2.theval = 2;

System.out.println(obj.equals(obj2));

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Wed Jun 22, 2016 6:52 am
by admin
Why do you think so? Did you try running the code?

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Sun Oct 02, 2016 3:26 pm
by bstinch
I think this is a bit confusing because it defines EQUAL only requiring theval%3 equal 0. If object1.theval = 3 and object2.theval = 30, object1.equals(object2) returns true. But in a 'common sense' perspective, these are two different objects. Syntactically I understand the rule, but I think it is an example of a bad implementation of the concept.

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Sun Oct 02, 2016 9:10 pm
by admin
There is not much scope for common sense here because the whole purpose of overriding equals is to let the programmer/application decide what constitutes equality for two objects of a given class. What seems nonsensical to an outsider may make perfect sense for the application developer.

Of course, they are two different objects ( that is why == should return false) but they are "equal" for the purpose of the application. It has a lot more to do with business requirement than common sense.

HTH,
Paul.

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Tue Jun 27, 2017 7:57 am
by ssszzz
The suggestion: make class GoodOne to be final, otherwise the contract might be violated:

Code: Select all

    public static void main(String... strings) {
        GoodOne x = new GoodOne();
        GoodOne y = new ExtendedGoodOne();
        // symmetric: for any _reference values_ x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
        System.out.println(x.equals(y) + " " + y.equals(x)); // output: true, false
    }

    static class ExtendedGoodOne extends GoodOne {
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof ExtendedGoodOne)) return false;
            ExtendedGoodOne t = (ExtendedGoodOne) o;
            return super.equals(o); //theval == t.theval;
        }
    }

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Tue Jun 27, 2017 8:16 am
by admin
Why do you think so?

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Tue Jun 27, 2017 9:24 am
by ssszzz
It seems that ExtendedGoodOne#equals does not violate the contact. It was generated using standard ide plugin.
And we can test it using Set. The following example shows, that GoodOne and ExtendedGoodOne can't be in one Set together (if we change order of addition).
But instances of ExtendedGoodOne and its subclass - can.

Code: Select all

    public static void main(String... strings) {
        GoodOne x = new GoodOne();
        GoodOne y = new ExtendedGoodOne();
        // symmetric: for any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
        System.out.println(x.equals(y) + " " + y.equals(x)); // output: true, false

        // add instances of GoodOne and ExtendedGoodOne to one Set
        Set<GoodOne> set1 = new HashSet<>(), set2 = new HashSet<>();
        set1.add(y); set1.add(x);
        set2.add(x); set2.add(y);
        System.out.println(set1.size() + " " + set2.size()); // output: 1, 2

        // add instances of ExtendedGoodOne and its subclass to one Set
        GoodOne z = new ExtendedGoodOne() {}; // not an instance of ExtendedGoodOne, but an instance of anonymous class, which extends ExtendedGoodOne
        System.out.println(z.getClass() == x.getClass()); // output: false
        Set<GoodOne> set3 = new HashSet<>(), set4 = new HashSet<>();
        set3.add(y); set3.add(z);
        set4.add(z); set4.add(y);
        System.out.println(set3.size() + " " + set4.size()); // output: 1, 1
    }
So, it seems there is nothing wrong with equals of ExtendedGoodOne, but something wrong with GoodOne#equals. It would be better, I think, to prohibit extending of GoodOne to be sure that there is no doubt about сorrectness of its equals method from this point of view.

By the way, the standard ide plugins offers comparison by 'instanceof' instead of comparison by 'getClass()'.
It seems this is also due to violation of symmetric while overriding.

Re: About Question enthuware.ocpjp.v8.2.1340 :

Posted: Tue Jun 27, 2017 11:48 am
by admin
A superclass is not responsible for the subclass. A superclass is not obligated to make sure that a subclass will work logically or correctly. As long as a class's equals method adheres to the equals contract, it is valid irrespective of what the subclass does.

Equals contract does not mandate that a class and its subclass objects must work well when added to a Set. So just because adding GoodOne and ExtendedGoodOne objects in a Set is not working as per your expectation, doesn't mean GoodOne's equals implementation is invalid.

HTH,
Paul.