The for-each loop
for (type_name variable_name : [instance of Iterable<T>] or [array]) {}
跟
.net
的
foreach
不同的是,
Iterable
中的
type parameter
或
array
中的
element type
必須是
for
中使用的
type
或者其子類。
以下情況不適合使用
foreach
:
1.??????
當需要刪除或者替換
current element
時。
2.??????
當需要同時訪問一個以上的
Iterable<T>
或者
array
時。
Autoboxing
一般的代碼經常會使用
boxing
跟
unboxing
,如:
List list = new ArrayList();
int i = 0;
list.add(new Integer(i)); // boxing
i = ((Integer) list.get(0)).intValue(); // unboxing
采用了
autoboxing
之后,
java
能夠自動在
primitive type
它相應的
wrapper
之間進行轉換。
// autoboxing
list.add(i);
i = list.get(0);
以
Integer
為例,以下幾點是需要注意的:
1.??????
當試圖將值為
null
的
Integer
轉為
int
時,會有
NullPointerException
。
int i = (Integer) null;
2.??????
對于
==
操作符,當它作用在
int
上時是做值的比較,作用于
Integer
上時是做
reference
的比較。
int i1 = 0;
Integer i2 = new Integer(0);
i1 == i2; // return true
i2 == i1; // return true
(Integer) i1 == i2; // return false
3.??????
如果頻繁使用
autoboxing
將不利于代碼的運行效率。
Enums
public enum Test { // 1
A, B(1), C { public boolean test1() { return true; } } /* 5 */ ; // 2
private int i = 0;
Test() {} // 3
private Test(int i) { this.i = i; } // 3
public boolean test1() { return false; } // 5
public boolean test2(Test test) { return test != A && test !=B; } // 6
// 7
public boolean test3() {
????? switch (this) {
case A: return false;
case B: return false;
default: return true;
}
}
}
Enum
跟一般的類有很多相似之處,它們都能夠實現多個接口,能夠定義方法、類變量,除了這些相似點之外,
enum
有如下的特性:
1.??????
必須使用
enum
關鍵字來定義,不能用
extends
指定父類,假如
enum
的名字為
Test
,則它自動繼承
Enum<Test>
。與此同時,
enum
還自動實現
Serializable
跟
comparable
接口,并且自動重載了部分
Object
的方法。
2.??????
所有的可用
enum constant
必須放在第一行,用逗號格開,以分號結束(如果后面沒有其他的代碼,則分號可以省略)。通過專門設計,使得
Serial form
可以支持后續新增的
enum constant
。
3.??????
可以定義若干不同的構造函數,構造函數只能用
private
修飾符(可以省略掉
private
),當構造函數需要輸入參數時,
enum constant
的定義中必須提供這些參數的值。
4.??????
自動增加了
values()
和
valueOf
(
Class<T>, String
)、
valueOf(String)
三個靜態方法。
5.??????
可以為
enum constant
定義
constant-specific
方法。
6.??????
在代碼中可以引用前面所定義的類型。
7.??????
由于
switch
可以應用于
int
跟
enum
類型,在代碼中可以使用
”switch (this) {…}”
語句。
8.??????
在
java.util
中有專為
enum
設計的高效率的
EnumSet
跟
EnumMap
,其中
EnumSet
提供對方法以使
enum
支持位與(
bit flags
)操作。
Varargs
在方法的參數列表上,如果類型后面加上三個點,則表示該參數可能作為數組或者多個參數傳入,如:
public void test(int… arguments) {}
…
test(1);
test(1, 2, 3);
test(new int[0]);
跟
.net
類似的,
varargs
必須作為方法的最后一個參數。如果對使用
varargs
的方法進行重載,則在調用該方法時,有可能
compiler
無法識別代碼究竟調用的是哪個方法,此時會有編譯錯誤。
Static Import
Static import
用來
import
類中的靜態變量或靜態方法,使用了
static import
之后,這些使用這些靜態變量和靜態方法時將不需要使用類名。
import static java.lang.Math.PI;
import static java.lang.Math.*;
Annotations
Annotation
的定義
public @interface Test {
????? int value();
????? String name() default “test”;
}
定義
annotation
使用
@interface
關鍵字。
annotation
能使用的類型為
primitive
、
String
、
Class
、
enums
以及以以上類型為
element type
的數組。使用
default
關鍵字能夠設定默認值,默認值必須是
compile time constants
。
Annotation
的使用的語法跟
java doc
的語法相似,為了區分這兩者,
annotation
的命名不能使用已有的
java doc
中所用的名字。
在
java.lang.annotation
中存在若干
mata-annotation
,用于
annotate
其他的
annotation
。
Annotation
的使用
首先,必須
import annotation
所在的包,
annotation
可以放在在任何
static
、
public
、
final
關鍵字可以使用的地方,建議把
annotation
放在最前面。
@Test(value=0)
public class A {
@Test(Value=0, name=”abc”) public void test(@Test(0) Object o) {}
}
對
annotation
中各個變量的賦值作為
name value pair
被放在括號內,同時用逗號格開,如果
annotation
中沒有任何變量或者所有變量都有默認值,則可以省去賦值部分(連同括號),如果
annotation
中有一個名字為
value
的變量,同時沒有其他的變量或者其他的變量都有默認值,則可以只提供值而省略
element name
和等號。
讀出
annotation
的包含的信息
通過
reflection
可以讀出
annotation
所包含的信息,有一部分
annotation
通過使用
meta-annotation
被聲明為
runtime
不可知,這時通過分析
byte code
才能得到其信息。