“JDK1.5”的一个重要主题就是通过新增一些特性来简化开发,这些特性包括泛型,for-else 循环,自动装包/拆包,枚举,可变参数, 静态导入 。使用这些特性有助于我们编写更加清晰,精悍,安全的代码。
下面我们简单介绍一下这些新特性。
1.泛型(Generic)
在没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。当使用泛型集合后,可以将集合中的元素限定为一个特定类型,集合中只能存储同一类型的对象,这样更安全;并且从集合获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,这样更方便。
在JDK1.5中,还可以按原来的方式将各种不同类型的数据装到一个集合中,但编译器会报告unchecked警告。
//没有使用泛型
ArrayList collection1 = new ArrayList();
collection1.add(1);
collection1.add(1L);
collection1.add("abc");
int i = (Integer)collection1.get(0); //需要强制类型转换
//使用泛型
ArrayList<String> collection2 = new ArrayList<String>();
collection2.add("abc");
String element = collection2.get(0); //不需要强制类型转换
泛型原理:泛型是提供给javac编译器来使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,当编译器编译完后带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其他类型的数据,例如,用反射得到集合,再调用其add方法即可。
下面这个实例可以说明这一点:
ArrayList<String> collection2 = new ArrayList<String>();
ArrayList<Integer> collection3 = new ArrayList<Integer>();
System.out.println(collection3.getClass() == collection2.getClass()); //返回true指向同一份字节码
collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc"); //使用反射将字符串添加到Integer集合中
System.out.println(collection3.get(0)); //返回 abc
2.For-Each循环
for each是jdk5.0新增加的一个循环结构,可以用来以此处理数组或集合中的每个元素而不用为指定下标。
格式如下:for(variable:collection)statement
定义一个变量用于暂存集合中的每一个元素,集合表达式必须是一个数组或者是一个实现了lterable接口的类(例如ArrayList)对象。
public class ClsTest {
public static void main(String[] args) {
int[] a=new int[10];
for(int b:a){
System.out.println(b);
} }
}
3.自动装包/拆包(Autoboxing/unboxing)
Integer iObj = 3; //自动装箱(将基本数据类型装换成Integer对象再赋给引用变量)
System.out.println(iObj + 12); //自动拆箱(将Integer数据类型装换成int)
public static void main(String[] args) {
// TODO Auto-generated method stub
WeekDay weekDay2 = WeekDay.FRI;
System.out.println(weekDay2); //自己提供了toString 方法
System.out.println(weekDay2.name());
System.out.println(weekDay2.ordinal()); //自己在枚举元素里边第几个
System.out.println(WeekDay.valueOf("SUN").toString());//把一个串变成WeekDay对象
System.out.println(WeekDay.values().length); //把所有的元素转换成数组
}
public enum WeekDay{
SUN,MON,TUE,WED,THI,FRI,SAT;
}
5.可变参数(Varargs)
@Test
public void testSum(){
sum (1,2,3,4); //第一种方式
int arr[]={1,2,3,4}; //第二种方式
sum(arr);
}
public void sum(int ...nums){
//可变参数你就把他看成数组
int sum=0;
for(int i:nums){
sum+=i;
}
System.out.println(sum);
}
//可变参数需要注意的问题
public void aa(int x,int ...nums){ //必须这样写
}
注意事项:
调用可变参数的方法时,编译器将自动创建一个数组保存传递给方法的可变参数,因此,程序员可以在方法体中以数组的形式访问可变参数
可变参数只能处于参数列表的最后,所以一个方法最多只能有一个可变长度的参数
6.静态导入(Static Imports)
要在页面中直接使用用静态成员(方法和变量)我们必须将方法或变量静态导入。使用静态导入可以使被导入类的所有静态变量和静态方法在当前类直接可见,使用这些静态成员无需再给出他们的类名。
如:
import static java.lang.Math.max;
import static java.lang.Math.abs; //导入方法
public class StaticImport {
public static void main(String[] args){
System.out.println(max(3, 6)); //求最大值(应该是Math.max(3, 6))
System.out.println(abs(3 - 6)); //获取绝对值(应该是Math.abs(3 - 6))
}
}
使用这个特性也会一定程度上降低代码地可读性。