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
才能得到其信息。