在Java编程中,有些知识 并不能仅通过语言规范或者标准API文档就能学到的。在本文中,我会尽量收集一些最常用的习惯用法,特别是很难猜到的用法。(Joshua Bloch的《Effective Java》对这个话题给出了更详尽的论述,可以从这本书里学习更多的用法。)
我把本文的所有代码都放在公共场所里。你可以根据自己的喜好去复制和修改任意的代码片段,不需要任何的凭证。
class Person { String name; int birthYear; byte[] raw; public boolean equals(Object obj) { if(!obj instanceofPerson) return false; Person other = (Person)obj; return name.equals(other.name) && birthYear == other.birthYear && Arrays.equals(raw, other.raw); } public int hashCode() { ... } }
class Person { String a; Object b; bytec; int[] d; public int hashCode() { return a.hashCode() + b.hashCode() + c + Arrays.hashCode(d); } public boolean equals(Object o) { ... } }
class Person implementsComparable<Person> { String firstName; String lastName; intbirthdate; // Compare by firstName, break ties by lastName, finally break ties by birthdate public int compareTo(Person other) { if(firstName.compareTo(other.firstName) != 0) returnfirstName.compareTo(other.firstName); else if (lastName.compareTo(other.lastName) != 0) returnlastName.compareTo(other.lastName); else if (birthdate < other.birthdate) return-1; else if (birthdate > other.birthdate) return1; else return0; } }
class Values implementsCloneable { String abc; doublefoo; int[] bars; Date hired; public Values clone() { try{ Values result = (Values)super.clone(); result.bars = result.bars.clone(); result.hired = result.hired.clone(); returnresult; }catch(CloneNotSupportedException e) { // Impossible thrownew AssertionError(e); } } }
// join(["a", "b", "c"]) -> "a and b and c" String join(List<String> strs) { StringBuilder sb = newStringBuilder(); booleanfirst = true; for(String s : strs) { if(first) first = false; elsesb.append(" and "); sb.append(s); } returnsb.toString(); }
Random rand = newRandom(); // Between 1 and 6, inclusive intdiceRoll() { return rand.nextInt(6) + 1; }
void filter(List<String> list) { for(Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String item = iter.next(); if(...) iter.remove(); } }
String reverse(String s) { return new StringBuilder(s).reverse().toString(); }
下面的三个例子使用了不同的方式完成了同样的事情。
实现Runnnable的方式:
void startAThread0() { new Thread(newMyRunnable()).start(); } class MyRunnable implementsRunnable { public void run() { ... } }
继承Thread的方式:
void startAThread1() {
new MyThread().start();
}
class MyThread extendsThread {
public void run() {
...
}
}
匿名继承Thread的方式:
void startAThread2() { new Thread() { publicvoid run() { ... } }.start(); }
I/O流例子:
void writeStuff() throwsIOException { OutputStream out = newFileOutputStream(...); try{ out.write(...); }finally{ out.close(); } }
锁例子:
void doWithLock(Lock lock) { lock.acquire(); try{ ... }finally{ lock.release(); } }
InputStream in = (...); try{ while(true) { intb = in.read(); if(b == -1) break; (... process b ...) } }finally{ in.close(); }
InputStream in = (...); try{ byte[] buf = newbyte[100]; while(true) { intn = in.read(buf); if(n == -1) break; (... process buf with offset=0and length=n ...) } }finally{ in.close(); }
BufferedReader in = newBufferedReader( newInputStreamReader(newFileInputStream(...), "UTF-8")); try{ while(true) { String line = in.readLine(); if(line == null) break; (... process line ...) } }finally{ in.close(); }
PrintWriter out = newPrintWriter( newOutputStreamWriter(newFileOutputStream(...), "UTF-8")); try{ out.print("Hello "); out.print(42); out.println(" world!"); }finally{ out.close(); }
int factorial(intn) { if(n < 0) thrownew IllegalArgumentException("Undefined"); else if (n >= 13) thrownew ArithmeticException("Result overflow"); else if (n == 0) return 1; else return n * factorial(n - 1); }
int findIndex(List<String> list, String target) { if(list == null|| target == null) throw new NullPointerException(); ... }
void frob(byte[] b, intindex) {
if(b == null)
throw new NullPointerException();
if(index < 0|| index >= b.length)
throw new IndexOutOfBoundsException();
...
}
void frob(byte[] b, intoff, intlen) { if(b == null) throw new NullPointerException(); if(off < 0|| off > b.length || len < 0|| b.length - off < len) throw new IndexOutOfBoundsException(); ... }
使用循环:
// Fill each element of array 'a' with 123 byte[] a = (...); for(inti = 0; i < a.length; i++) a[i] = 123;
(优先)使用标准库的方法:
Arrays.fill(a, (byte)123);
使用循环:
// 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(inti = 0; i < 8; i++) b[6+ i] = a[3+ i];
(优先)使用标准库的方法:
System.arraycopy(a, 3, b, 6, 8);
使用循环(扩大规模):
// Make array 'a' larger to newLen
byte[] a = (...);
byte[] b = newbyte[newLen];
for(int i = 0; i < a.length; i++) // Goes up to length of A
b[i] = a[i];
a = b;
使用循环(减小规模):
// Make array 'a' smaller to newLen byte[] 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;
(优先)使用标准库的方法:
1
|
a = Arrays.copyOf(a, newLen);
|
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; }
byte[] unpackBigEndian(intx) { return new byte[] { (byte)(x >>> 24), (byte)(x >>> 16), (byte)(x >>> 8), (byte)(x >>> 0) }; } byte[] unpackLittleEndian(intx) { returnnew byte[] { (byte)(x >>> 0), (byte)(x >>> 8), (byte)(x >>> 16), (byte)(x >>> 24) }; }