Hi Jim, I have updated the webrev to include changes to check testBit() instead of using isValid(). Please find the updated webrev for review: http://cr.openjdk.java.net/~jdv/7107905/webrev.03/
Thanks, Jay -----Original Message----- From: Jim Graham Sent: Tuesday, April 12, 2016 12:21 AM To: Jayathirth D V; Philip Race; Prasanta Sadhukhan Cc: 2d-dev@openjdk.java.net Subject: Re: Review Request for JDK-7107905: equals() method in IndexColorModel doesnt exist and it relies on ColorModel.equals() which is not strict Hi Jay, There was one thing I pointed out in the first review that got lost in the shuffle. When the validBits are not null you use isValid(i) to test the values, but that method does 3 things: - tests the index for validity, but we already know it is valid - tests validBits for null, but we already know it is not - calls validBits.testBit() - this is the only part we need For performance, I'd switch to just testing for the bits directly, as in: validBits.testBit(i) == cm.validBits.testBit(i) ...jim On 4/11/2016 12:46 AM, Jayathirth D V wrote: > Hi Jim, > > Thanks for the review. > I have made all recommended changes and created new subtask for > JDK-6588409(https://bugs.openjdk.java.net/browse/JDK-8153943 ). > > Please review updated webrev: > http://cr.openjdk.java.net/~jdv/7107905/webrev.02/ > > Thanks, > Jay > > -----Original Message----- > From: Jim Graham > Sent: Friday, April 08, 2016 12:28 AM > To: Jayathirth D V; Philip Race; Prasanta Sadhukhan > Cc: 2d-dev@openjdk.java.net > Subject: Re: Review Request for JDK-7107905: equals() method in > IndexColorModel doesnt exist and it relies on ColorModel.equals() > which is not strict > > Hi Jayathirth, > > This looks good. > > One thing to note for efficiency, "instanceof" also checks for null. > It only returns true for non-null objects, so you don't need to > explicitly test for null at the top of ICM.equals(). (Though, you > should include a > test(s) in the unit test that verifies that no ICM returns true for > equals(null) to be sure.) You can see that CM.equals() is implemented this > way. > > Also, for performance, ICM should include a quick "if (this == cm) return > true;" check, like CM.equals(). I'd recommend: > > - first instanceof > - then == test > - then super.equals() > - finally, test equality of data fields > > More comments inline: > > On 4/7/16 6:46 AM, Jayathirth D V wrote: >> - Yes https://bugs.openjdk.java.net/browse/JDK-6588409 has mentioned >> the same thing. Can I create a subtask to address java.awt.image changes? > > That would be good. > >> For now, it would be good to implement hashCode() on ICM now that you are >> creating an equals() method for it. >> >> - I am not completely sure of what is the optimal way of adding >> hashCode() API so I took help from internet and IDE to make the changes. I >> am including super.hashCode() as it adds uniqueness to ICM. > > You did a great job. To save time in the future, you should all have copies > of the latest version of "Effective Java" by Josh Bloch. It has a whole > chapter on equals/hashCode. It's a very handy reference for all sorts of > good programming practice for the Java language. > >> Also, ColorModel.hashCode() is a poor implementation. It doesn't use the >> paradigms recommended by Effective Java and looks like it produces poor >> hashes as a result (just in the first two elements of the hashCode I see a >> collision due to poor choice of numbers). >> - I think since we are not using Prime numbers and it might result in >> improper hash code. I have made similar changes to hashCode() of ColorModel. > > Looks great. > >> - In the same file itself we are following Java coding guidelines of >> having braces after if like "if () {". I am not completely sure of including >> "{" in new line. > > You are correct, that matching local code is a good consideration when > considering code style. In this case, though, the indentation on these if > statements is an example of what we're trying to avoid so it would be better > to fix these particular statements (don't bother fixing the other lines in > the file at this point, that can wait until we have to update other parts of > the file, but don't propagate a bad style in new code). > In particular: > > Never do this: > > if (some complex test || > some additional tests || > some additional tests || > some additional tests || > some continuation of the test) { > the body of the code; > more body of the code; > } > Quick question - where does the body of the if statement start? Does your > eye see it in a fraction of a second or do you have to search for it? > > That is the worst option for indenting an if statement with continuation > lines. Never do that in new code. Do either of the following two versions: > > Java Code Style guidelines recommends indenting 8 spaces for > conditional > continuations: > if (some complex test || > some additional tests || > some additional tests || > some additional tests || > some continuation of the test) { > the body of the code; > more body of the code; > } > > Jim's personal extension to the JCS recommends (and the 2D team historically > tended to agree): > if (some complex test || > some additional tests || > some additional tests || > some additional tests || > some continuation of the test) > { > the body of the code; > more body of the code; > } > > Both of those immediately draw the eye to the separating point between the > conditional and the body of the code. > >> I'd also add a few test cases that test that 2 separately and identically >> constructed ICM instances are equals() == true, tested with one of each of >> the constructors... >> >> - I have made changes to test case for verifying all constructors with >> same ICM. Also added verification for hashCode value. > > Unfortunately, some of your tests for hashCode make an invalid assumption. > It is technically correct for the hash codes of 2 different objects to be the > same regardless of whether they are equals() or not. > In fact, a perfectly valid implementation of hashCode() could return a > constant number and it would be correct from the perspective of the > equals/hashCode contract. (Such code, however, would not be optimal, but it > would be valid/correct-to-spec.) The only condition that is required is that > the hash codes match if the objects are equals(), but they are allowed to > match if the objects are !equals(). In other words: > > boolean equals1 = (o1.equals(o2)); > boolean equals2 = (o2.equals(o1)); > boolean equalsH = (o1.hashCode() == o2.hashCode()); > > if (equals1 != equals2) that is an error - we should test this if > (equals1 && !equalsH) that is an error - we should test this // No > other conditions are an error, no other testing should be done > > In particular, the cases where you test the hash codes for being the same on > objects that are not intended to be equals() should be deleted. > It would be good to also add tests to make sure that they are > symmetrically equals (or symmetrically not equals) as well (i.e. > o1.equals(o2) matches o2.equals(o1) in all cases whether they match or not). > > Since it is less than optimal for hash codes to match if the objects are not > equal, it might potentially be something to check on, but it should not > generate a unit test failure and so should not appear in the unit test for > this bug. Such a "code collision test" would be part of a performance test > run periodically for QA, but we have never bothered with hashCode > optimization unless a customer submits a complaint about the performance of > some object in a hash map due to hash collisions (and I doubt that ColorModel > objects are being used in such a manner), so I wouldn't recommend it here. > > ...jim >