“JDK1.5”(开发代码猛虎)的一个重要主题就是通过新增一些特性来简化开发,这些特性包括泛型、foreach循环、自动拆装箱、枚举、可变参数、内省、静态导入等。使用这些特性有助于我们编写更加清晰,强悍,安全的代码。
- 泛型(Generic)
- C++通过模板技术可以指定集合的元素类型,而java在1.5之前一直没有相对应的功能,一个集合可以放任何类型的对象,相应地从集合里面拿对象的时候我们也不得不对他们进行强制的类型转换。猛虎引入了泛型,它允许指定集合里元素的类型,这样你可以强类型在编译时刻进行类型检查的好处。
1 Collection<String> c = new ArrayList<String>(); 2 c.add(new Date()); 3 //编译器会给出一个错误: 4 add(java.lang.String) in java.util.Collection<java.lang.String> cannot be applied to (java.util.Date)
- foreach循环(Enhanced for loop)
- foreach循环的加入简化了集合的遍历。假设我们要遍历一个集合对其中的元素进行一些处理。典型的代码为:
1 void processAll(Collection c) { 2 for(Iterator i = c.iterator();i.hasNext();) { 3 MyClass myObject = (MyClass) i.next(); 4 myObject.process(); 5 } 6 } 7 //使用foreach循环,我们可以把代码改写成: 8 void processAll(Colllection<MyClass> c) { 9 for(MyClass myObject : c) { 10 myObject.process(); 11 } 12 } 13 //这段代码要比上面清晰许多,并且避免了强制类型转换。
- 自动拆装箱(Autoboxing/unboxing)
- 自动拆装箱大大方便了基本类型数据和它们包装类的使用
- 自动装箱:基本类型自动转为包装类(int >> Integer)
- 自动拆箱:包装类自动转为基本类型(Integer >> int)
- 在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀,现在自动转换机制能解决我们的问题
1 int a = 3; 2 COllection<Integer> c = new ArrayList<Integer>(); 3 c.add(a);//自动转换为Integer 4 5 Integer b = new Integer(2); 6 c.add(b+2);//这里Integer先自动转换为int进行加法运算,然后int再次转换为Integer
- 类型安全的枚举(Type safe enums)
- JDK1.5加入了一个全新的“类”--枚举类型。为此JDK1.5引入了一个新关键字enum。我们可以这样定义一个枚举类型。
1 public enum Color { 2 RED,WHITE,BLUE 3 } 4 public enum Coin { 5 6 penny(1), nickel(5), dime(10), quarter(25); 7 8 Coin(int value) { 9 this.value = value; 10 } 11 12 private final int value; 13 14 public int value() { 15 return value; 16 } 17 } 18 //然后可以这样来使用: 19 Color myColor = Color.RED; 20 //枚举类型还提供了两个有用的静态方法values()和valueOf().我们可以很方便地使用它们,例如: 21 for(Color c : Color.values()) { 22 System.out.printl(c); 23 }
- 可变参数(Var args)
- 可变参数使程序员可以声明一个接受可变数目参数的方法。注意,可变参数必须是函数生命中的最后一个参数。加入我们要写一个简单的方法打印一些对象:
1 util.write(obj1); 2 util.write(obj1,obj2); 3 util.write(obj1,obj2,obj3); 4 ...
在JDK1.5之前,我们可以用重载来实现,但是这样就需要写很多的重载函数,显得不是很有效。如果使用可变参数的话,我们只需要一个函数就行了:1 public void write(Object... objs) { 2 for(Object obj : pbjs) { 3 System.out.println(obj); 4 } 5 }
在引入可变参数以后,Java的反射包也更加方便使用了,对于1 c.getMethod("test", new Object[0]).invoke(c.newInstance(), new Object[0]); 2 //现在我们可以这样写了 3 c.getMethod("test").invoke(c.newInstance()); 4 //这样代码比原来清楚了很多
- 内省(Introspector)
- 内省是java语言对Bean类属性、事件的一种缺省处理方法。例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新的值。通过getName/setName来访问name属性,这就是默认的规则。Java中提供了一套API用访问某个属性的getter和setter方法,通过这些API可以使你不需要了解这个规则(但你最好还是要搞清楚),这些API存放于包java.beans中。
- 一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。
- 静态导入(Static import)
- 要使用静态成员(方法和变量)我们给出提供这个方法的类。使用静态导入可以使被导入类的所有静态变量和静态方法在当前类直接可见,使用这些静态成员无需再给出他们的类名
1 import static java.lang.Math.*; 2 ... 3 r = sin(PI * 2);//无需再写 r = Math.sin(Math.PI * 2); 4 不过,过度使用这个特性也会一定程度上降低代码的可读性。