1,自动装箱与拆箱
自动装箱是指把基本数据类型封装成类对象,拆箱是指把类对象拆成基本数据类型。
例如下列代码在java 5.0以后都是可以编译通过的
//自动装箱
Integer in = 3;
Short sh = 2;
Long lo = 3L;Double dbl = 3.4D;
Float fl = 1.2F;Byte bt = 12;
Character cht = 'c';// 自动拆箱
int i = new Integer(3);
short s = new Short((short)1);
long l = new Long(3L);double d = new Double(2.3D);
float f = new Float(1.2F);byte b = new Byte((byte)23);
char ch = new Character('a');
而在java5.0以前则不行,因为两边的数据类型不一样,一个是基本数据类型一个是对象,必须通过调用wrapper类的方法来实现对象和基本数据类型之间的转化
关于包装类在这里不详述。
2,新的for/in循环,
只需要在for循环里指出遍历的元素类型,和遍历的对象即可:
package com.book.ch10.java5;import java.util.ArrayList;
import java.util.List;public class JForInArray {public static void main(String[] args) {String[] array = { "a", "b", "c", "d" };for (String s : array) {System.out.println("遍历数组:" + s);}List<String> list = new ArrayList<String>();list.add("A");list.add("b");list.add("C");list.add("D");for (String obj : list) {System.out.println("遍历集合:" + obj);}}}
3,可变长参数法
定义一个可变长参数的方法是在参数类型的后面加上省略号,然后加上可变长参数名。可变长参数在方法内部表现为数组,可以使用传统的数组遍历方式来使用数组,也可以使用新的for/in循环:
package com.book.ch10.java5;public class JVarargsTest {public static double avg(double... values) {//可变长参数的定义方法double total = 0;int count = values.length;for (double i : values) {//可变长参数的使用total += i;}return total / count;}public static void main(String[] args) {System.out.printf("平均数为 %s. %n", avg(3, 4.2, 2));System.out.printf("平均数为 %s. %n", avg());System.out.printf("平均数为 %s. %n", avg(new double[] { 3, 4.2, 2 }));}}
4,协变式返回类型
允许在覆盖父类方法的时候,使父类方法的返回值更加具体。例如ArrayList类的get(int index)返回的是Object,继承ArrayList之后可以覆盖get方法,并修改返回值为String,因为String也是Object的子类。在java5.0版本以前,这是不允许的。
package com.book.ch10.java5;import java.util.ArrayList;
import java.util.List;@SuppressWarnings(value="serial")
public class JCovariantReturnTypesTest extends ArrayList {@Override//可以这样来覆盖父类中的方法,在5.0以前是不允许在覆盖的时候返回值类型跟父类不一样的public String get(int index) {return (String)super.get(index);}public static void main(String...args){JCovariantReturnTypesTest list = new JCovariantReturnTypesTest();list.add("字符串");// 可以直接返回 String 类型 而不是父类中的 ObjectString result = list.get(0);System.out.printf("%s", result);}}
5,静态导入
即impot Static指令导入某个类的静态方法和静态变量,在使用的时候就可以直接使用变量名和方法名,而不用再带上“类名. ”了。
package com.book.ch10.java5;// 静态导入变量
import static java.lang.Math.PI;
// 静态导入方法
import static java.lang.Math.sin;
// 静态导入所有的方法跟变量
import static java.lang.Math.*;public class JStaticImportTest {public static void main(String[] args){// 直接使用方法和变量,无需 Math 前缀System.out.printf("sin(%s) = %s%n", PI, sin(PI));System.out.printf("cos(%s) = %s%n", PI, cos(PI));}}
6,泛型
在这里只介绍最基本的语法,后面将详细介绍
类与方法都可以被泛型化,泛型避免了一些运行时错误,使得许多错误在编译阶段就能发现。
类泛型ArrayList<E>代表的意思是ArrayList存放的数据类型是E类型,E代表一个类的类型
方法泛型public E get(int index)代表方法的返回值是E型的
看一个例子:
package com.book.ch10.java5;import java.util.ArrayList;
import java.util.Date;
import java.util.List;public class JGenericTest {public static void main(String[] args){// 范型 限制为 Date 类型List<Date> list = new ArrayList<Date>();list.add(new Date());list.add(new Date());list.add(new Date());// 无需 ClassCast. Date date = list.get(0);System.out.printf("%s %n", date);for(Date dd : list){System.out.printf("for/in 循环:%1$tF %1$tT%n", dd);}}}
注意,泛型编程只能使用类,不能使用基本类型。
集合中使用多个泛型的一个例子:
package com.book.ch10.java5;import java.util.Date;
import java.util.HashMap;
import java.util.Map;public class JHashMapGeneric {public static void main(String[] args) {Map<String, Date> map = new HashMap<String, Date>();//多个泛型map.put("time_1", new Date());map.put("time_2", new Date());map.put("time_3", new Date());for(String key : map.keySet()){Date date = map.get(key);System.out.printf("Key: %1$s, Value: %2$tF %2$tT%n", key, date);}}}
再来看一下泛型通配符:通配符只能用来进行类型安全检查,而不能用来声明具体的类泛型
<?>代表任何类型,不过单独使用?基本没有什么用(单独一个?也就是不用泛型的意思),一般与extends和super一起用
<?>与extends一起表示指定类型及其所有子类
<?>与super一起表示指定类型及其所有父类
由于通配符只能进行类型安全检查,不能用来声明具体的泛型类,故下面的用法是错误的
List <?> = new ArrayList<?> //不能用来做声明用
看下面用通配符做类型检查的一个例子:
package com.book.ch10.java5;import java.util.ArrayList;
import java.util.Date;
import java.util.List;public class JWildCard {//通配符指定接受的list可以是Number及其子类public static void numberList(List<? extends Number> list){for(Number num : list){System.out.printf("输出数字:%1$s %n", num);}}//同上public static void dateList(List<? extends Date> list){for(Date date : list){System.out.printf("输出日期:%1$tF %1$tT%n", date);}}public static void main(String[] args){List<Date> dateList = new ArrayList<Date>();//类型声明要用具体的泛型List<Integer> intList = new ArrayList<Integer>();dateList.add(new Date());dateList.add(new Date());intList.add(3);intList.add(6);numberList(intList);dateList(dateList);}}
泛型化一个类是在类名后面定义泛型类型,泛型化一个方法需要在方法名的返回类型前定义泛型类型:下面写一个自己的泛型:
package com.book.ch10.java5;import java.util.Date;public class JGenericMethod {// 范型化类. 在类名后使用<>定义了范型类型 T.static class A<T> {// 定义之后直接使用 T 即可public T generic(T t){return t;}}static class B {// 范型化方法. 在方法返回类型前使用<>定义范型类型 Tpublic <T> T generic(T t){return t;}// 范型化方法. 在方法返回类型前使用<>定义范型类型 T, 该范型类型只能为 Date 及其子类public <T extends Date> T genericDate(T t){return t;}}public static void main(String[] args){A<String> a = new A<String>();String ss = a.generic("一个字符串");B b = new B();String ss2 = b.generic("另一个字符串");Date date = b.genericDate(new Date());}}
7,枚举类型
枚举类型不能在方法内部声明,只能声明为一个类变量,
public enum Sex{MALE,FEMAL,UNKNOW};
枚举类型里德变量是实实在在的对象,可以把他们看成是static,final,public的
package com.book.ch10.java5;public class JEnumeration {public static enum Sex { MALE, FEMALE, UNKOWN, };public static void main(String[] args){System.out.printf("Sex.FEMALE.toString(): \t%s %n", Sex.FEMALE.toString());System.out.printf("Sex.FEMALE.ordinal(): \t%s %n", Sex.FEMALE.ordinal());System.out.printf("Sex.FEMALE.getClass(): \t%s %n", Sex.FEMALE.getClass());System.out.printf("%n遍历所有的 Sex 枚举变量: ");for(Sex sex : Sex.values()){System.out.printf("%s, ", sex);}switch(Sex.FEMALE){case MALE:// do somethingbreak;case FEMALE:// do somethingbreak;case UNKOWN:// do somethingbreak;default:// do something}}}
下面来看一下扩展枚举类型,enum和class,interface一样是一种对象。因此它可以扩展,添加属性或方法,跟interface不能有构造函数一样,enum也有一些限制:
enum内部可以有构造方法,但不能有public的构造方法
enum内置对象间必须用逗号隔开,声明完所有的内置对象后用分号结束
enum内置对象必须使用声明的构造函数,否则编译错误
看一个例子:
package com.book.ch10.java5;public class JEnumTest {static enum Type {// 内置的枚举类型对象// 各枚举类型对象之间用逗号隔开。MANAGER("经理", 10000), ASSISTANT("助理", 6000), WORKER("员工", 4000),;//分号结束// 扩展的属性private String name;private double pay;// 构造函数 不能为 public Type(String name, double pay){this.name = name;this.pay = pay;}}static class Person {public Person(String name, Type type){// 注意person的类型
this.name = name;this.type = type;}private String name;private Type type;public String getName() {return name;}public void setName(String name) {this.name = name;}public Type getType() {return type;}public void setType(Type type) {this.type = type;}}public static void printInfo(Person person){System.out.printf("姓名:%1$s, \t职业:%2$s, \t岗位薪水:%3$s %n", person.getName(), person.getType().name, person.getType().pay);}public static void main(String[] args){Person p1 = new Person("张三", Type.MANAGER);Person p2 = new Person("李四", Type.WORKER);Person p3 = new Person("王五", Type.ASSISTANT);printInfo(p1);printInfo(p2);printInfo(p3); }
}