Summary of classic usage of Java
- 2020-05-05 11:14:05
- OfStack
In Java programming, there are some things you can't just learn from the language specification or the standard API documentation.
One, implement
1, now equals()
class Person {
String name;
int birthYear;
byte[] raw;
public boolean equals(Object obj) {
if (!obj instanceof Person)
return false;
Person other = (Person)obj;
return name.equals(other.name)
&& birthYear == other.birthYear
&& Arrays.equals(raw, other.raw);
}
public int hashCode() { ... }
}
The parameter must be of type Object, not a peripheral class. foo.equals(null) must return false, not NullPointerException. (note that null instanceof any class always returns false, so the code above can run.) Comparison of primitive type fields (e.g., int) USES ==, and comparison of array fields of primitive types USES Arrays.equals (). When overwrites equals(), remember to overwrite hashCode() accordingly, consistent with equals().
2, now 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) { ... }
}
When x and y have x.equals (y) == true, you must ensure that x.hashCode () == y.hashCode (). according to the converse statement, if x.hashCode()! = y.hashCode (), then x.equals (y) == false must be true. You don't need to guarantee that when x.equals (y) == false, x.hashCode ()! = y. hashCode (). However, if you can make it as valid as possible, this will improve the performance of the hash table. The simplest legal implementation of hashCode() is simply return 0; While this implementation is correct, it causes the HashMap data structures to run slowly.
3, compareTo()
class Person implements Comparable<Person> {
String firstName;
String lastName;
int birthdate;
// 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 the generic version Comparable instead of the original type Comparable. Because this can save code and reduce unnecessary trouble.
I only care about the plus and minus signs (negative/zero/positive) that return the results. Their size doesn't matter.
The implementation of Comparator.compare() is similar to this.
4, 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);
}
}
}
USES super.clone () to make the Object class responsible for creating new objects. The base type fields have been copied correctly. Again, we don't need to clone immutable types like String and BigInteger. manually makes a deep copy of all non-primitive type fields (objects and arrays) (deep copy). implements Cloneable's class, and the clone() method should never discard CloneNotSupportedException. Therefore, you need to catch the exception and ignore it, or wrap it with an undetected exception (unchecked exception). It is both possible and legal for to manually implement the clone() method without using the Object.clone () method.
Ii. Preventive testing
1. preventive test (Defensive checking
2. Preventive detection object
3, preventive detection array index
Don't think that all the array indexes you give won't cross the line. You want to explicitly detect it.
4. Preventive detection array interval
do not assume that input values are positive, small enough, and so on. These conditions are explicitly detected. A well-designed function should perform correctly for all possible input values. Make sure that all situations are taken into account and that there is no incorrect output (such as an overflow).
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);
}
do not assume that the object parameter will not be null (null). Explicitly detect this condition.
int findIndex(List<String> list, String target) {
if (list == null || target == null)
throw new NullPointerException();
...
}
void frob(byte[] b, int index) {
if (b == null)
throw new NullPointerException();
if (index < 0 || index >= b.length)
throw new IndexOutOfBoundsException();
...
}
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();
...
}
Do not think that the given array interval (for example, starting with off and reading len elements) is not overstepping the bounds. You want to explicitly detect it.
array
1, fill the array element
cycle:
// Fill each element of array 'a' with 123
byte[] a = (...);
for (int i = 0; i < a.length; i++)
a[i] = 123;
(preferred) ways to use the standard library:
Arrays.fill(a, (byte)123);
2, copy a range of array elements
usage cycle:
// Copy 8 elements from array 'a' starting at offset 3
// to array 'b' starting at offset 6,
// assuming 'a' and 'b' are distinct arrays
byte[] a = (...);
byte[] b = (...);
for (int i = 0; i < 8; i++)
b[6 + i] = a[3 + i];
(preferred) ways to use the standard library:
System.arraycopy(a, 3, b, 6, 8);
3, resize the array
usage cycle (scale up) :
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) { ... }
}
0
Use cycle (reduce size) :
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) { ... }
}
1
(preferred) way to use the standard library:
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) { ... }
}
2
4. Wrap four bytes (packing) into one 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 (Unpacking) into 4 bytes
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) { ... }
}
4
Always use the unsigned right shift operator (>) > > ) wrap bits (packing), do not use the arithmetic shift operator (>) > ).
The above is the entire content of this article, I hope to help you with your study.