In Java programming, some knowledge cannot be learned only through language specifications or standard API documents. This article lists it for you.
1. Realization
1. Now equals()
class Person { String name; int birthdayYear; byte[] raw; public boolean equals(Object obj) { if (!obj instanceof Person) return false; Person other = (Person)obj; return name.equals(other.name) && birthdayYear == other.birthYear && Arrays.equals(raw, other.raw); } public int hashCode() { ... }} 2. HashCode()
class Person { String a; Object b; byte c; int[] d; public int hashCode() { return a.hashCode() + b.hashCode() + c + Arrays.hashCode(d); } public boolean equals(Object o) { ... }}3. Implement compareTo()
class Person implements Comparable<Person> { String firstName; String lastName; int birthday; // Compare by firstName, break ties by lastName, finally break ties by birthdate public int compareTo(Person other) { if (firstName.compareTo(other.firstName) != 0) return firstName.compareTo(other.firstName); else if (lastName.compareTo(other.lastName) != 0) return lastName.compareTo(other.lastName); else if (birthdate < other.birthdate) return -1; else if (birthdate > other.birthdate) return 1; else return 0; }} Always implement generic version Comparable instead of primitive type Comparable. Because this can save code volume and reduce unnecessary hassle.
Just care about the signs (negative/zero/positive) that return the result, their size does not matter.
Comparator.compare() implementation is similar to this one.
4. Implement clone()
class Values implements Cloneable { String abc; double foo; int[] bars; Date hired; public Values clone() { try { Values result = (Values)super.clone(); result.bars = result.bars.clone(); result.hired = result.hired.clone(); return result; } catch (CloneNotSupportedException e) { // Impossible throw new AssertionError(e); } }}2. Preventive testing
1. Defensive checking value
int factorial(int n) { if (n < 0) throw new IllegalArgumentException("Undefined"); else if (n >= 13) throw new ArithmeticException("Result overflow"); else if (n == 0) return 1; else return n * factorial(n - 1);} 2. Preventive testing objects
int findIndex(List<String> list, String target) { if (list == null || target == null) throw new NullPointerException(); ...}3. Preventive detection array index
void frob(byte[] b, int index) { if (b == null) throw new NullPointerException(); if (index < 0 || index >= b.length) throw new IndexOutOfBoundsException(); ...}Don't think that the array index given will not cross the bounds. To detect it explicitly.
4. Preventive detection array interval
void frob(byte[] b, int off, int len) { if (b == null) throw new NullPointerException(); if (off < 0 || off > b.length || len < 0 || b.length - off < len) throw new IndexOutOfBoundsException(); ...}Don't think that the given array interval (for example, starting from off, reading len elements) will not go beyond the bounds. To detect it explicitly.
3. Array
1. Fill array elements
Using loops:
// Fill each element of array 'a' with 123byte[] a = (...);for (int i = 0; i < a.length; i++) a[i] = 123; (Preferential) Methods for using the standard library: Arrays.fill(a, (byte)123);
2. Copy an array element in a range
Using loops:
// Copy 8 elements from array 'a' starting at offset 3// to array 'b' starting at offset 6,// assuming 'a' and 'b' are distinct arraysbyte[] a = (...);byte[] b = (...);for (int i = 0; i < 8; i++) b[6 + i] = a[3 + i]; (Preferential) Methods to use the standard library: System.arraycopy(a, 3, b, 6, 8);
3. Adjust the array size
Use loops (scaling up):
// Make array 'a' larger to newLenbyte[] a = (...);byte[] b = new byte[newLen];for (int i = 0; i < a.length; i++) // Goes up to length of A b[i] = a[i];a = b;
Use loops (reduce the size):
// Make array 'a' smaller to newLenbyte[] a = (...);byte[] b = new byte[newLen];for (int i = 0; i < b.length; i++) // Goes up to length of B b[i] = a[i];a = b;
(Preferential) Methods to use the standard library:
1a = Arrays.copyOf(a, newLen);
4. Packing 4 bytes into an int
int packBigEndian(byte[] b) { return (b[0] & 0xFF) << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8 | (b[3] & 0xFF) << 0;} int packLittleEndian(byte[] b) { return (b[0] & 0xFF) << 0 | (b[1] & 0xFF) << 8 | (b[2] & 0xFF) << 16 | (b[3] & 0xFF) << 24;}5. Decompose int into 4 bytes
byte[] unpackBigEndian(int x) { return new byte[] { (byte)(x >>> 24), (byte)(x >>> 16), (byte)(x >>> 8), (byte)(x >>> 0) };} byte[] unpackLittleEndian(int x) { return new byte[] { (byte)(x >>> 0), (byte)(x >>> 8), (byte)(x >>> 16), (byte)(x >>> 24) };}Always use the unsigned right-shift operator (>>>) to wrap the bits, do not use the arithmetic right-shift operator (>>).
The above is all about this article, I hope it will be helpful to everyone's learning.