zoukankan      html  css  js  c++  java
  • JDK5.0新特性(静态导入、自动装箱/拆箱、增强for循环、可变参数、枚举、泛形)

    JDK5中新增了很多新的java特性,利用这些新语法可以帮助开发人员编写出更加高效、清晰,安全的代码。

    这些新特性主要有:
    1.静态导入
    2.自动装箱/拆箱
    3.增强for循环
    4.可变参数
    5.枚举
    6.泛型
    7.元数据

    1.静态导入
    静态导入用于简化程序对静态属性和方法的调用

    语法:Import static 包名.类名.静态属性|静态方法|*
    例如:
    import static java.lang.System.out
    import static java.lang.Math.*

    2.自动装箱/拆箱
    自动装箱:指开发人员可以把一个基本数据类型直接赋给对应的包装类。
    自动拆箱:指开发人员可以把一个包装类对象直接赋给对应的基本数据类型。

    Integer i = 1; //装箱
    int j = i; //拆箱

    典型应用:
    List list = new ArrayList();
    list.add(1);
    int j=(Integer)list.get(0);//拆箱

    3.增强for循环

    引入增强for循环的原因:在JDK5以前的版本中,遍历数组或集合中的元素,需要先获得数组的长度或集合的迭代器,比较麻烦!

    JDK5中定义了一种新的语法--增强for循环,以简化此类操作。增强for循环只能在数组或实现Iterable接口的集合类上。

    语法格式:
    for(变量类型 变量:需要迭代的数组或集合){
    }

    代码:
    @Test
    public void test1() {
    int arr[] = { 1, 2, 3 };
    for (int num : arr) {
    System.out.println(num);
    }
    }

    输出:
    1
    2
    3

    @Test
    public void test2() {
    List list = new ArrayList();
    list.add(1);
    list.add(2);
    list.add(3);
    for (Object obj : list) {
    int i=(Integer)obj;
    System.out.println(i);
    }
    }


    输出:
    1
    2
    3

    @Test
    public void test3() {
    Map map=new HashMap();// HashMap按hash函数保存数据,保存的数据与存的顺序可能不一样
    map.put("1", "aaa");
    map.put("2", "bbb");
    map.put("3", "ccc");

    //传统方式1
    Set set=map.keySet();
    Iterator it =set.iterator();
    while(it.hasNext()){
    String key=(String)it.next();
    String value=(String)map.get(key);
    System.out.println(key+"="+value);
    }

    }

    输出:
    3=ccc
    2=bbb
    1=aaa

    @Test
    public void test4() {
    Map map=new LinkedHashMap();
    map.put("1", "aaa");
    map.put("2", "bbb");
    map.put("3", "ccc");

    //传统方式1
    Set set=map.keySet();
    Iterator it =set.iterator();
    while(it.hasNext()){
    String key=(String)it.next();
    String value=(String)map.get(key);
    System.out.println(key+"="+value);
    }

    }

    输出:
    1=aaa
    2=bbb
    3=ccc

    @Test
    public void test5() {
    Map map = new LinkedHashMap();
    map.put("1", "aaa");
    map.put("2", "bbb");
    map.put("3", "ccc");

    // 传统方式2
    Set set = map.entrySet();
    Iterator it = set.iterator();
    while (it.hasNext()) {
    Map.Entry entry = (Entry) it.next();
    String key = (String) entry.getKey();
    String value = (String) entry.getValue();
    System.out.println(key + "=" + value);
    }

    }

    输出:
    1=aaa
    2=bbb
    3=ccc


    @Test
    public void test6() {
    Map map = new LinkedHashMap();
    map.put("1", "aaa");
    map.put("2", "bbb");
    map.put("3", "ccc");

    // 增强for取map的第1种方式
    for (Object obj : map.keySet()) {
    String key = (String) obj;
    String value = (String) map.get(key);
    System.out.println(key + "=" + value);
    }

    }

    输出:
    1=aaa
    2=bbb
    3=ccc


    @Test
    public void test7() {
    Map map = new LinkedHashMap();
    map.put("1", "aaa");
    map.put("2", "bbb");
    map.put("3", "ccc");

    // 增强for取map的第2种方式
    for (Object obj : map.entrySet()) {
    Map.Entry entry = (Entry) obj;
    String key = (String) entry.getKey();
    String value = (String) entry.getValue();
    System.out.println(key + "=" + value);
    }

    }

    输出:
    1=aaa
    2=bbb
    3=ccc


    // 使用增强for需要注意的问题:增强for只适合取数据,要修改数组或集合中的数据,要用传统方式
    @Test
    public void test8() {
    int arr[]={1,2,3};
    for(int i:arr)
    {
    i=10;
    }
    System.out.println(arr[0]);
    System.out.println(arr[1]);
    System.out.println(arr[2]);

    List list = new ArrayList();
    list.add("1");
    for(Object obj:list)
    {
    obj=10;
    }
    System.out.println(list.get(0));
    }

    输出:
    1
    2
    3
    1

    4.可变参数

    测试JDK中具有可变参数的类Arrays.asList()方法。分别传多个参、传数组,传数组又传参的情况。
    注意:传入基本数据类型数组的问题

    从JDK5开始,Java允许为方法定义长度可变的参数。语法:
    public void foo(int ...args){
    }

    注意事项:
    调用可变参数的方法时,编译器将自动创建一个数组保存传递给方法的可变参数,因此,程序员可以在方法体中以数组的形式访问可变参数

    可变参数只能处于参数列表的最后,所以一个方法最多只能有一个长度可变的参数

    代码:
    @Test
    public void testSum() {
    sum(1,2,3,4,5,6);
    }

    public void sum(int ...nums) {
    //可变参数你把他看成数组
    int sum=0;
    for(int i:nums){
    sum+=i;
    }
    System.out.println(sum);
    }

    输出:
    21

    @Test
    public void testAa() {
    aa(1,2,3,4,5,6);
    }

    //可变参数需要注意的问题:public void aa(int ...nums,int x) { 这样不行,参数会被直接看成一个数组,x没有值
    public void aa(int x,int ...nums) {
    //可变参数你把他看成数组
    int sum=0;
    for(int i:nums){
    sum+=i;
    }
    System.out.println(sum);
    }

    输出:
    20

    @Test
    public void bb(){
    List list=Arrays.asList("1","2","3");
    System.out.println(list);

    String arr[]={"1","2","3","4"};
    list = Arrays.asList(arr);
    System.out.println(list);

    int nums[]={1,2,3,5};//这个细节一定要小心,注意可变参数类型,int nums[]是基本类型数组,这个数组就是一个对象,Arrays.asList(nums)的参数是对象集合。
    list=Arrays.asList(nums);
    System.out.println(list);
    }

    输出:
    [1, 2, 3]
    [1, 2, 3, 4]
    [[I@1e63e3d]

    5.枚举

    1).枚举的作用
    一些程序在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,jdk5以前采用自定义类来解决,jdk5以后可以直接采用枚举解决。

    JDK5新增的enum关键字用于定义一个枚举类。

    一个枚举也可以有构造函数、字段和方法。

    2).枚举类具有如下特性:

    枚举类也是一种特殊形式的Java类。

    枚举类中声明的每一个枚举值代表枚举类的一个实例对象。

    与Java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的(这点不难理解)。

    枚举类也是可以实现接口或继承抽象类。

    JDK5中扩展了swith语句,它除了可以接收int,byte,char,short外,还可以接收一个枚举类型。

    若枚举类只有一个枚举值,则可以当作单态设计模式使用。

    Java中声明的枚举类,均是java.lang.Enum类的孩子,它继承了Enum类的所有方法。常用方法:
    name()
    ordinal()
    valueof(Class enumClass,String name)
    values()此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它用于遍历枚举的所有枚举值。

    代码:
    1>.
    @Test
    public void test() {
    print(Grade.B);
    }

    public void print(Grade g) {
    String value = g.getValue();
    System.out.println(value);
    }

    // 如何定义枚举的构造函数、方法和字段,去封装更多的信息
    enum Grade {
    A("100-90"), B("89-80"), C("79-70"), D("69-60"), E("59-0");

    private String value;// 封装每个对象对应的分数

    private Grade(String value) {
    this.value = value;
    }

    public String getValue() {
    return this.value;
    }
    }

    输出:
    89-80

    2>.
    @Test
    public void test() {
    print(Grade.B);
    }

    public void print(Grade g) {
    String value = g.localValue();
    System.out.println(value);
    }

    //带抽象方法的枚举
    enum Grade {
    A("100-90") {
    public String localValue() {
    return "优";
    };
    },
    B("89-80") {
    public String localValue() {
    return "良";
    };
    },
    C("79-70") {
    public String localValue() {
    return "一般";
    };
    },
    D("69-60") {
    public String localValue() {
    return "差";
    };
    },
    E("59-0") {
    public String localValue() {
    return "不及格";
    };
    };

    private String value;// 封装每个对象对应的分数

    private Grade(String value) {
    this.value = value;
    }

    public String getValue() {
    return this.value;
    }

    public abstract String localValue();
    }

    输出:

    3>.测试枚举的常用方法
    @Test
    public void test2(){
    System.out.println(Grade.C.name());
    System.out.println(Grade.C.ordinal());

    String str="B";
    //Grade g=Grade.valueOf(Grade.class,str);
    Grade g=Grade.valueOf(str);//str给出的值若无效则会报错
    System.out.println(g);

    Grade gs[]=Grade.values();
    for(Grade g1:gs){
    System.out.println(g1);
    }

    }

    输出:
    C
    2
    B
    A
    B
    C
    D
    E

    6.泛形(Generic)

    1)泛形的作用

    JDK5以前,对象保存到集合中就会失去其特性,取出时通常要程序员手工进行类型的强制转换,这样不可避免就会引发程序的一些安全性问题。例如:

    ArrayList list=new ArrayList();
    list.add("abc");
    Integer num=(Integer)list.get(0);//运行时会出错,但编码时发现不了

    JDK5中的泛形允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)。示例。


    List<String> list1=new ArrayList<String>();
    list1.add("aaaa");
    String s=list1.get(0);

    2)掌握泛形的基本使用

    掌握泛形集合的存取

    3)泛形的几个注意事项

    使用泛形时几个常见问题:

    使用泛形时,泛形类型须为引用类型,不能是基本数据类型
    ArrayList<Object> list=new ArrayList<String>();//错
    ArrayList<String> list=new ArrayList<Object>();//错
    ArrayList<String> list=new ArrayList();//对
    ArrayList list=new ArrayList<String>();//对
    用泛形时,如果两边都使用到泛形,两边必须要一样

    注意:泛形是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。

    泛形的基本术语,以ArrayList<E>为例:<>念typeof
    ArrayList<E>中的E称为类型参数变量
    ArrayList<Integer>中的Integer称为实际类型参数
    整个称为ArrayList<E>泛形类型
    整个ArrayList<Integer>称为参数化的类型ParameterizedType

    4)自定义泛形---泛形方法
    Java程序中的普通方法、构造方法和静态方法中都可以使用泛形。
    方法使用泛形前,必须对泛形进行声明,语法:<T>,T可以是任意字母,但通常必须要大写。<T>通常需要放在方法的返回值声明之前。例如:
    public static <T> void doxx(T t);

    练习:

    编写一个泛形方法,实现指定位置上的数组元素的交换。(代码3)

    编写一个泛形方法,接收一个任意数组,并颠倒数组中所有元素。(代码3)

    注意:

    只有对象类型才能作为泛形方法的实际参数。
    在泛形中可以同时有多个类型,例如:
    public static <K,V> V getValue(K key){return map.get(key);}

    5)自定义泛形---泛形类和反射泛形

    如果一个类多处都要用到同一个泛形,这时可以把泛形定义在类上(即类级别的泛形),语法格式如下:
    public class GenericDao<T>{
    private T field1;
    public void save(T obj){}
    public T getId(int id){}
    }

    注意,静态方法不能使用类定义的泛形,而应单独定义泛形。
    泛形的典型应用:BaseDao和反射泛形

    public BaseDao(){
    Type type=this.getClass().getGenericSuperclass();
    ParameterizedType pt=(ParameterizedType)type;
    class=(Class)pt.getActualTypeArguments()[0];
    }

    6)

    代码1:

    package cn.itcast.generic;

    //自定义带泛形的方法
    public class Demo2 {

    public void testa(){
    a("aaa");
    }

    public <T> T a(T t){
    return null;
    }

    public <T,E,K> void b(T t,E e,K k){

    }
    }

    代码2:

    package cn.itcast.generic;

    //自定义类上的泛形
    //类上面声明的泛形作用于整个类,静态方法上的泛形需要单独声明
    public class Demo3<T,E,K> {

    public void testa(){

    }

    public T a(T t){
    return null;
    }

    public void b(T t,E e,K k){

    }

    public static <T> void c(T t){

    }
    }

    代码3:

    package cn.itcast.generic;

    public class Demo4 {

    // 编写一个泛形方法,实现指定位置上的数组元素的交换
    public <T> void swap(T arr[], int pos1, int pos2) {
    T temp = arr[pos1];
    arr[pos1] = arr[pos2];
    arr[pos2] = temp;
    }

    // 编写一个泛形方法,接收一个任意数组,并颠倒数组中所有元素。
    public <T> void reverse1(T arr[]) {
    int start = 0;
    int end = arr.length - 1;

    while (true) {
    if (start >= end)
    break;

    T temp = arr[start];
    arr[start] = arr[end];
    arr[end] = temp;

    start++;
    end--;
    }
    }

    public <T> void reverse2(T arr[]) {
    int lenth = arr.length;
    for (int i = 0; i < lenth / 2; i++) {
    T temp = arr[i];
    arr[i] = arr[lenth - i - 1];
    arr[lenth - i - 1] = temp;
    }
    }
    }

  • 相关阅读:
    COJ 1002 WZJ的数据结构(二)(splay模板)
    生成网络流图
    最小费用最大流MCMF zkw费用流
    COJ 2003 选根 (树的重心)
    最小费用最大流MCMF 最小增广
    PDO 基础知识
    使 用 Jquery 全选+下拉+单选+事件+挂事件
    搜 房 网 站 设 计 练 习
    百分比进度条
    在PHP系统里连接MySQL 数据访问,+ + + + + 数据删除
  • 原文地址:https://www.cnblogs.com/xiaohuihui123/p/4341223.html
Copyright © 2011-2022 走看看