Makes `EmptyByteBuf#hashCode` and `AbstractByteBuf#hashCode` consistent (#7870)

Motivation:
The `AbstractByteBuf#equals` method doesn't take into account the
class of buffer instance. So the two buffers with different classes
must have the same `hashCode` values if `equals` method returns `true`.
But `EmptyByteBuf#hashCode` is not consistent with `#hashCode`
of the empty `AbstractByteBuf`, that is violates the contract and
can lead to errors.

Modifications:
Return `1` in `EmptyByteBuf#hashCode`.

Result:
Consistent behavior of `EmptyByteBuf#hashCode` and `AbstractByteBuf#hashCode`.
This commit is contained in:
Nikolay Fedorovskikh 2018-04-16 15:11:42 +05:00 committed by Norman Maurer
parent f874a37ecb
commit 81a7d1413b
3 changed files with 14 additions and 2 deletions

View File

@ -168,7 +168,7 @@ public final class ByteBufUtil {
final int intCount = aLen >>> 2;
final int byteCount = aLen & 3;
int hashCode = 1;
int hashCode = EmptyByteBuf.EMPTY_BYTE_BUF_HASH_CODE;
int arrayIndex = buffer.readerIndex();
if (buffer.order() == ByteOrder.BIG_ENDIAN) {
for (int i = intCount; i > 0; i --) {

View File

@ -36,6 +36,7 @@ import java.nio.charset.Charset;
*/
public final class EmptyByteBuf extends ByteBuf {
static final int EMPTY_BYTE_BUF_HASH_CODE = 1;
private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0);
private static final long EMPTY_BYTE_BUFFER_ADDRESS;
@ -976,7 +977,7 @@ public final class EmptyByteBuf extends ByteBuf {
@Override
public int hashCode() {
return 0;
return EMPTY_BYTE_BUF_HASH_CODE;
}
@Override

View File

@ -82,4 +82,15 @@ public class EmptyByteBufTest {
}
}
}
@Test
public void consistentEqualsAndHashCodeWithAbstractBytebuf() {
ByteBuf empty = new EmptyByteBuf(UnpooledByteBufAllocator.DEFAULT);
ByteBuf emptyAbstract = new UnpooledHeapByteBuf(UnpooledByteBufAllocator.DEFAULT, 0, 0);
assertEquals(emptyAbstract, empty);
assertEquals(emptyAbstract.hashCode(), empty.hashCode());
assertEquals(EmptyByteBuf.EMPTY_BYTE_BUF_HASH_CODE, empty.hashCode());
assertTrue(emptyAbstract.release());
assertFalse(empty.release());
}
}