Java 1.5版本,就是Java 2 Standard Edition 5,Version 1.5,简称Java 5。版本代号Tiger。
一. 泛型(Generics)
C++通过模板技术可以指定集合的元素类型,而Java在1.5之前一直没有相对应的功能。一个集合可以放任何类型的对象,相应地从集合里面拿对象的时候我们也不得不对他们进行强制得类型转换。
泛型提供一种途径,让你告诉编译器容器中存放的是什么,这样它就可以做一些检查工作。不符合规则的情况下,编译是通不过的。通过引入泛型,我们将获得编译时类型的安全和运行时更小地抛出ClassCastExceptions的可能。
@Test
public void testGenerics() { List<String> c = new ArrayList<String>(); c.add("Hello"); c.add("World"); c.add("Hihi"); // c.add(new Date()); // 编译出错:The method add(String) in the type List<String> is not applicable for the arguments (Date)
// Removes 4-letter words from c. Elements must be strings for (Iterator i = c.iterator(); i.hasNext(); ) // 旧方式处理 if (((String) i.next()).length() == 4) i.remove(); // Removes the 4-letter words from c for (Iterator<String> i = c.iterator(); i.hasNext(); ) // 新方式处理 if (i.next().length() == 4) i.remove(); System.out.println(c);
二. For-Each循环(The For-Each Loop)
在这类For循环中,你应该将":"看成"in",所以,在该例中可以看成"for Object o in c"。你可以发现这种For循环更具可读性,For-Each循环的加入简化了集合的遍历。
@Test
public void testForEach() { List<String> list = new ArrayList<String>(); for(int i=0; i<10; i++) list.add("str" + i); // 老款遍历的方法 for (int i = 0; i < list.size(); i++) { String str = list.get(i); } // 迭代遍历的for方式;相对while循环而言,能够避免变量名错误 for (Iterator<String> iter = list.iterator(); iter.hasNext();) { String str = (String)iter.next(); }
// For-Each循环 for (String str : list) { // 直接用了 System.out.println(str); } }
三. 自动装箱/拆箱(Autoboxing/Unboxing)
自动装箱/拆箱,提供基本数据类型与包装类的自动互相转换功能。自动装包/拆包大大方便了基本类型数据和它们包装类地使用。
@Test
public void testBoxing() { List<Integer> list = new ArrayList<Integer>(); list.add(1); // 自动转换成Integer list.add(2); list.add(3); int i = 2; Integer integer = new Integer(i); list.add(integer + 2); // 变量integer自动转换为int进行加法运算,再转换为Integer System.out.println(list); // [1, 2, 3, 4] System.out.println(list.get(i) + " " + list.get(integer)); // 3 3
// 注意下面两行语句的差别,实践时要特别注意! list.remove(i); list.remove(integer); System.out.println(list); // [1, 4] }
四. 类型安全枚举(Typesafe Enums)
JDK1.5加入了一个全新类型的“类”-枚举类型。为此JDK1.5引入了一个新关键字enum。
- 它们提供编译时类型安全。
- 它们都是对象,因此你不需要将他们放入集合中。
- 它们作为一种类的实现,因此你可以添加一些方法。
- 它们为枚举类型提供了合适的命名空间。
- 它们打印的值具有情报性(informative)― 如果你打印一个整数枚举(intenum),你只是看见一个数字,它可能并不具有情报性。
// Typesafe Enums:定义一个红绿灯 enum TrafficLight { Green, Yellow, Red, }
@Test public void testEnum() throws Exception { // 类型安全的枚举(Enums):定义一个红绿灯 TrafficLight currentLight = TrafficLight.Yellow; for (TrafficLight light : TrafficLight.values()) System.out.println(light); }
五. 可变参数(Varargs)
可变参数(Varargs):可变参数可以是零个、一个、两个...多个;但不能是null值。注意,可变参数必须是函数声明中的最后一个参数。在JDK1.5之前,我们可以用重载来实现上述功能,但是这样就需要写很多的重载函数。如果使用可变参数的话我们只需要一个函数就行了。
@Test
public void testVarargs() throws Exception { // 可变参数(Varargs):参考可以零个、一个、两个...多个;但不能是null值。 printStr(); printStr("你好"); printStr("我好", "你也好"); }
// 可变参数(Varargs):参考可以零个、一个、两个...多个;但不能是null值。 // 如果要求用户至少输入一个参数的话,那么参数应该是:printStr(String str1, String... strs),然后做相关处理 private void printStr(String... strs) { for(String str: strs) System.out.println(str); }
六. 静态导入(Static Import)
import static 语句可以导入一个类中的某个静态方法或是所有静态方法。
import static java.lang.Math.*;
@Test public void testStaticImport() throws Exception { // 静态导入(Static Import):可以直接使用Math的方法、属性 double d = round(PI * 2); System.out.println("round(2*PI)=" + d); }
七. 注解(Annotations)
元数据特征志于使开发者们借助厂商提供的工具可以进行更简易的开发。
@Override // Annotations,如果更改此方法的返回类型,则会出错,因为已经指定Override,必须跟父类一样返回String。 public String toString() { return "Just Test"; }
完整代码:
package com.clzhang.sample.thinking; import static java.lang.Math.*; import java.util.*; import org.junit.Test; public class JDK15LangFeature { @Test public void testGenerics() { List<String> c = new ArrayList<String>(); c.add("Hello"); c.add("World"); c.add("Hihi"); // c.add(new Date()); // 编译出错:The method add(String) in the type List<String> is not applicable for the arguments (Date) // Removes 4-letter words from c. Elements must be strings for (Iterator i = c.iterator(); i.hasNext(); ) // 旧方式处理 if (((String) i.next()).length() == 4) i.remove(); // Removes the 4-letter words from c for (Iterator<String> i = c.iterator(); i.hasNext(); ) // 新方式处理 if (i.next().length() == 4) i.remove(); System.out.println(c); } @Test public void testForEach() { List<String> list = new ArrayList<String>(); for(int i=0; i<10; i++) list.add("str" + i); // 老款遍历的方法 for (int i = 0; i < list.size(); i++) { String str = list.get(i); } // 迭代遍历的for方式;相对while循环而言,能够避免变量名错误 for (Iterator<String> iter = list.iterator(); iter.hasNext();) { String str = (String)iter.next(); } // For-Each循环 for (String str : list) { // 直接用了 System.out.println(str); } } @Test public void testBoxing() { List<Integer> list = new ArrayList<Integer>(); list.add(1); // 自动转换成Integer list.add(2); list.add(3); int i = 2; Integer integer = new Integer(i); list.add(integer + 2); // 变量integer自动转换为int进行加法运算,再转换为Integer System.out.println(list); // [1, 2, 3, 4] System.out.println(list.get(i) + " " + list.get(integer)); // 3 3 // 注意下面两行语句的差别,实践时要特别注意! list.remove(i); list.remove(integer); System.out.println(list); // [1, 4] } // Typesafe Enums:定义一个红绿灯 enum TrafficLight { Green, Yellow, Red, } @Test public void testEnum() throws Exception { // 类型安全的枚举(Enums):定义一个红绿灯 TrafficLight currentLight = TrafficLight.Yellow; for (TrafficLight light : TrafficLight.values()) System.out.println(light); } @Test public void testVarargs() throws Exception { // 可变参数(Varargs):参考可以零个、一个、两个...多个;但不能是null值。 printStr(); printStr("你好"); printStr("我好", "你也好"); } // 可变参数(Varargs):参考可以零个、一个、两个...多个;但不能是null值。 // 如果要求用户至少输入一个参数的话,那么参数应该是:printStr(String str1, String... strs),然后做相关处理 private void printStr(String... strs) { for(String str: strs) System.out.println(str); } @Test public void testStaticImport() throws Exception { // 静态导入(Static Import):可以直接使用Math的方法、属性 double d = round(PI * 2); System.out.println("round(2*PI)=" + d); } @Override // Annotations,如果更改此方法的返回类型,则会出错,因为已经指定Override,必须跟父类一样返回String。 public String toString() { return "Just Test"; } }