在Java编程中,有些知识 并不能仅通过语言规范或者标准API文档就能学到的。在本文中,我会尽量收集一些最常用的习惯用法,特别是很难猜到的用法。(Joshua Bloch的《Effective Java》对这个话题给出了更详尽的论述,可以从这本书里学习更多的用法。)
我把本文的所有代码都放在公共场所里。你可以根据自己的喜好去复制和修改任意的代码片段,不需要任何的凭证。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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() { ... }
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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
;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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);
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
|
// join(["a", "b", "c"]) -> "a and b and c"
String join(List<String> strs) {
StringBuilder sb =
new
StringBuilder();
boolean
first =
true
;
for
(String s : strs) {
if
(first) first =
false
;
else
sb.append(
" and "
);
sb.append(s);
}
return
sb.toString();
}
|
1
2
3
4
5
6
|
Random rand =
new
Random();
// Between 1 and 6, inclusive
int
diceRoll() {
return
rand.nextInt(
6
) +
1
;
}
|
1
2
3
4
5
6
7
|
void
filter(List<String> list) {
for
(Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
String item = iter.next();
if
(...)
iter.remove();
}
}
|
1
2
3
|
String reverse(String s) {
return
new
StringBuilder(s).reverse().toString();
}
|
下面的三个例子使用了不同的方式完成了同样的事情。
实现Runnnable的方式:
1
2
3
4
5
6
7
8
9
|
void
startAThread0() {
new
Thread(
new
MyRunnable()).start();
}
class
MyRunnable
implements
Runnable {
public
void
run() {
...
}
}
|
继承Thread的方式:
1
2
3
4
5
6
7
8
9
|
void
startAThread1() {
new
MyThread().start();
}
class
MyThread
extends
Thread {
public
void
run() {
...
}
}
|
匿名继承Thread的方式:
1
2
3
4
5
6
7
|
void
startAThread2() {
new
Thread() {
public
void
run() {
...
}
}.start();
}
|
I/O流例子:
1
2
3
4
5
6
7
8
|
void
writeStuff()
throws
IOException {
OutputStream out =
new
FileOutputStream(...);
try
{
out.write(...);
}
finally
{
out.close();
}
}
|
锁例子:
1
2
3
4
5
6
7
8
|
void
doWithLock(Lock lock) {
lock.acquire();
try
{
...
}
finally
{
lock.release();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
|
InputStream in = (...);
try
{
while
(
true
) {
int
b = in.read();
if
(b == -
1
)
break
;
(... process b ...)
}
}
finally
{
in.close();
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
InputStream in = (...);
try
{
byte
[] buf =
new
byte
[
100
];
while
(
true
) {
int
n = in.read(buf);
if
(n == -
1
)
break
;
(... process buf with offset=
0
and length=n ...)
}
}
finally
{
in.close();
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
BufferedReader in =
new
BufferedReader(
new
InputStreamReader(
new
FileInputStream(...),
"UTF-8"
));
try
{
while
(
true
) {
String line = in.readLine();
if
(line ==
null
)
break
;
(... process line ...)
}
}
finally
{
in.close();
}
|
1
2
3
4
5
6
7
8
9
|
PrintWriter out =
new
PrintWriter(
new
OutputStreamWriter(
new
FileOutputStream(...),
"UTF-8"
));
try
{
out.print(
"Hello "
);
out.print(
42
);
out.println(
" world!"
);
}
finally
{
out.close();
}
|
1
2
3
4
5
6
7
8
9
10
|
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
);
}
|
1
2
3
4
5
|
int
findIndex(List<String> list, String target) {
if
(list ==
null
|| target ==
null
)
throw
new
NullPointerException();
...
}
|
1
2
3
4
5
6
7
|
void
frob(
byte
[] b,
int
index) {
if
(b ==
null
)
throw
new
NullPointerException();
if
(index <
0
|| index >= b.length)
throw
new
IndexOutOfBoundsException();
...
}
|
1
2
3
4
5
6
7
8
|
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();
...
}
|
使用循环:
1
2
3
4
|
// Fill each element of array 'a' with 123
byte
[] a = (...);
for
(
int
i =
0
; i < a.length; i++)
a[i] =
123
;
|
(优先)使用标准库的方法:
Arrays.fill(a, (byte)123);
使用循环:
1
2
3
4
5
6
7
|
// 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];
|
(优先)使用标准库的方法:
System.arraycopy(a, 3, b, 6, 8);
使用循环(扩大规模):
1
2
3
4
5
6
|
// Make array 'a' larger to newLen
byte
[] 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;
|
使用循环(减小规模):
// 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);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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
;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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
)
};
}
|