Java JDK5的一些新特性

1,自动装箱与拆箱

自动装箱是指把基本数据类型封装成类对象,拆箱是指把类对象拆成基本数据类型。

例如下列代码在java 5.0以后都是可以编译通过的

<span style="font-size: 15px;">//自动装箱
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');
</span>


而在java5.0以前则不行,因为两边的数据类型不一样,一个是基本数据类型一个是对象,必须通过调用wrapper类的方法来实现对象和基本数据类型之间的转化

关于包装类在这里不详述。

2,新的for/in循环,

只需要在for循环里指出遍历的元素类型,和遍历的对象即可:

<span style="font-size: 15px;">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);
        }
 
    }
 
}
</span>


3,可变长参数法

定义一个可变长参数的方法是在参数类型的后面加上省略号,然后加上可变长参数名。可变长参数在方法内部表现为数组,可以使用传统的数组遍历方式来使用数组,也可以使用新的for/in循环:

<span style="font-size: 15px;">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 }));
    }
 
}
</span>


4,协变式返回类型

允许在覆盖父类方法的时候,使父类方法的返回值更加具体。例如ArrayList类的get(int index)返回的是Object,继承ArrayList之后可以覆盖get方法并修改返回值为String,因为String也是Object的子类。在java5.0版本以前,这是不允许的。

<span style="font-size: 15px;">package com.book.ch10.java5;
 
import java.util.ArrayList;
import java.util.List;
 
@SuppressWarnings(value="serial")
public class JCovariantReturnTypesTestextends 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 类型 而不是父类中的 Object
        String result = list.get(0);
        System.out.printf("%s", result);
    }
     
 
}
</span>


5,静态导入

即impot Static指令导入某个类的静态方法和静态变量,在使用的时候就可以直接使用变量名和方法名,而不用再带上“类名. ”了。

<span style="font-size: 15px;">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));
    }
     
}
</span>


6,泛型

在这里只介绍最基本的语法,后面将详细介绍

类与方法都可以被泛型化,泛型避免了一些运行时错误,使得许多错误在编译阶段就能发现。

类泛型ArrayList<E>代表的意思是ArrayList存放的数据类型是E类型,E代表一个类的类型

方法泛型public E get(int index)代表方法的返回值是E型的

看一个例子:

<span style="font-size: 15px;">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);
        }
         
         
    }
 
}
</span>


注意,泛型编程只能使用类,不能使用基本类型。

集合中使用多个泛型的一个例子:

<span style="font-size: 15px;">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);
        }
         
    }
 
}
</span>


再来看一下泛型通配符:通配符只能用来进行类型安全检查,而不能用来声明具体的类泛型

<?>代表任何类型,不过单独使用?基本没有什么用(单独一个?也就是不用泛型的意思),一般与extends和super一起用

<?>与extends一起表示指定类型及其所有子类

<?>与super一起表示指定类型及其所有父类

由于通配符只能进行类型安全检查,不能用来声明具体的泛型类,故下面的用法是错误的

List <?> = new ArrayList<?>   //不能用来做声明用

看下面用通配符做类型检查的一个例子:

<span style="font-size: 15px;">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);
    }
 
}
</span>


泛型化一个类是在类名后面定义泛型类型,泛型化一个方法需要在方法名的返回类型前定义泛型类型:下面写一个自己的泛型:

<span style="font-size: 15px;">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 {
        // 范型化方法. 在方法返回类型前使用<>定义范型类型 T
        public <T> T generic(T t){
            return t;
        }
        // 范型化方法. 在方法返回类型前使用<>定义范型类型 T, 该范型类型只能为 Date 及其子类
        public <Textends 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());
         
    }
     
}
</span>


7,枚举类型

枚举类型不能在方法内部声明,只能声明为一个类变量,

public enum Sex{MALE,FEMAL,UNKNOW};

枚举类型里德变量是实实在在的对象,可以把他们看成是static,final,public的

<span style="font-size: 15px;">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 something
            break;
        case FEMALE:
            // do something
            break;
        case UNKOWN:
            // do something
            break;
        default:
            // do something
        }
         
    }
 
}
</span>


下面来看一下扩展枚举类型,enum和class,interface一样是一种对象。因此它可以扩展,添加属性或方法,跟interface不能有构造函数一样,enum也有一些限制:

enum内部可以有构造方法,但不能有public的构造方法

enum内置对象间必须用逗号隔开,声明完所有的内置对象后用分号结束

enum内置对象必须使用声明的构造函数,否则编译错误

看一个例子:

<span style="font-size: 15px;">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的类型 </span><br><span style="font-size: 15px;">                  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); 
    }  
}
</span>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值