javaweb学习——5.JDK5.0的新特性

前言

继续记录javaweb的一些知识点

开始

JDK经过这么多年的发展,5.0的版本中有一些新的特性:泛型、枚举、静态导入、自动拆装箱、增强for循环,可变参数。
此外再加一个反射的记录。

1.泛型

1.什么是泛型,为什么使用?
泛型一般使用在集合上
把一个字符串类型放到一个集合里面,这个字符串类型就失去了本身的类型,变成了object类型,这个时候想要对这个值进行类型转换,就很容易出现错误,解决这个问题可以使用泛型。

在泛型里面写是一个对象,String,不能写基本的数据类型比如int,要写进本数据类型所对应的包装类

byte——Byte
short——Short
int——Integer
long——Long

float——Float
double——Double
char——charcter
boolean——Blloean

2.如何使用泛型?
常用集合:list set map
泛型的语法:集合<String>,比如List<String>
在list上使用泛型:
list的三种实现有:ArrayList,LinkedList,Vector(要明白这三个的区别)

package jdk5;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.junit.Test;

public class fanxing {

    @Test
    public void fanxingTest() {
        List<String> list = new ArrayList<String>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");

        //遍历list有三种方式:普通for循环,增强for循环和迭代器
        //普通for循环
        for(int i=0;i<list.size();i++) {
            String string = list.get(i);
            System.out.println(string);
        }
        System.out.println("----------------------------");
        //增强for循环
        for (String string : list) {
            System.out.println(string);
        }
        System.out.println("----------------------------");
        //使用迭代器
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

}

在set上使用泛型:

@Test
    public void setTest() {

        Set<String> set = new HashSet<String>();
        set.add("www");
        set.add("qqq");
        set.add("zzz");

        //遍历set,有两种方式,迭代器和增强for循环
        //增强for循环
        for (String string : set) {
            System.out.println(string);
        }
        System.out.println("----------------------------");
        //使用迭代器
        Iterator<String> iterator = set.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }

    }

在map上使用泛型:
map的结构:key-value形式

@Test
    public void mapTest() {

        Map<String,String> map = new HashMap<String,String>();
        map.put("aaa", "111");
        map.put("bbb", "222");
        map.put("ccc", "333");

        //遍历map,有两种方式:1.获取所有的key,通过key得到value,使用get方法       2.获取key和value的关系

        //1.获取所有的key,通过key得到value,使用get方法
        //获取所有的key
        Set<String> set = map.keySet();
        //遍历所有的key
        for (String key : set) {
            //通过key得到value
            String value = map.get(key);
            System.out.println(key+" : "+value);
        }
        System.out.println("----------------------------");

        //2.获取key和value的关系
        Set<Entry<String, String>> set2 = map.entrySet();
        //遍历set
        for (Entry<String, String> entry : set2) {
            //entry是key和value关系
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+" : "+value);
        }
    }

3.泛型使用在方法上
通过一些联系来展现:

package jdk5;

import java.util.Arrays;

//练习:   编写一个泛型方法,实现指定位置上数组元素的交换
//方法逻辑相同,只是数据类型不同,这个时候使用泛型方法
public class fanxingInMethod {

    public static void main(String args[]) {
        //创建一个数组,实现11和13的交换
        Integer[] arr1 = {10,11,12,13,14};
        System.out.println(Arrays.toString(arr1));
        swap1(arr1,1,3);
        System.out.println(Arrays.toString(arr1));

        //创建一个String类型的数组,实现bb和dd位置的交换
        String[] arr2 = {"aa","bb","cc","dd","ff"};
        System.out.println(Arrays.toString(arr2));
        swap1(arr2, 1, 3);
        System.out.println(Arrays.toString(arr2));
    }

//  private static void swap1(int[] arr1, int i, int j) {
//      //定义一个中间变量
//      int temp = arr1[i];
//      arr1[i] = arr1[j];
//      arr1[j] = temp;
//      
//  }
//  
//  private static void swap1(String[] arr2, int i, int j) {
//      //定义一个中间变量
//      String temp = arr2[i];
//      arr2[i] = arr2[j];
//      arr2[j] = temp;
//      
//  }


    //使用泛型方法,需要定义一个数据类型,使用大写字母T,表示任意的类型,写在返回值的前面,表示定义了一个类型T
    //下面就可以使用这个类型T
    public static <T> void swap1(T[] arr,int a,int b) {
        //定义一个中间变量
        T temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

}

作业:可以写一个泛型方法,接收任意一种数组,颠倒数组中的全部元素。

4.泛型在类上的使用(了解)
在一个类上定义一个类型,这个类型可以在类里面直接使用

package jdk5;

public class fanxingInClass<T> {

    //在类里面可以直接使用T的类型
    T aa;
    public void test(T bb) {

    }

    //写一个静态方法,在类上面定义的泛型不能再静态方法中使用,要在静态方法上在定义。
    public static <A> void test1(A cc) {

    }
}

2.枚举

1.什么是枚举
需要在一定范围内取值,这个值只能是这个范围内中的任意一个
应用场景:红绿灯,三种颜色,但是每次只能亮三种颜色中的一个
2.用代码来看看:
使用传统的方式体现枚举

package meiju;

public class meiju {

    //传统的方式
    private int color;

    public void test() {
        this.color = Color1.RED; 
    }

}

class Color1{

    public static final int RED = 1;
    public static final int YELLOW = 2;
    public static final int GREEN = 3;

}
/**************************************************************************************/

package meiju;

public class meiju {

    //第二种方式
    private Color2 color1;

    public void test() {
        this.color1 = Color2.RED;
    }

}


class Color2{

    //构造方法私有化
    private Color2() {

    }
    public static final Color2 RED = new Color2();
    public static final Color2 YELLOW = new Color2();
    public static final Color2 GREEN = new Color2();
}

使用枚举,有关键字enum,枚举的构造方法也是私有的

package meiju;

public class meiju {

    //使用枚举
    private Color3 color3;

    public void test() {
        this.color3 = color3.RED;
    }
}

enum Color3{
    RED,GREEN,YELLOW;
}

/**********************************************************************************/
//特殊枚举,在枚举的类里面有构造方法,抽象方法
enum Color4{
    RED("red"){

        @Override
        public void print1() {
            System.out.println("red");

        }},GREEN("green"){

            @Override
            public void print1() {
                System.out.println("green");

            }},YELLOW("yellow"){

                @Override
                public void print1() {
                    System.out.println("yellow");

                }
            };
    private Color4(String name){

    }
    //当在枚举里面写了一个抽象方法的时候,需要在每个实例上面都实现抽象方法
    public abstract void print1();

}

3.枚举的练习

package meiju;

import org.junit.Test;

//练习:枚举对象、枚举对象下标、枚举对象名称表示之间的转换
public class meijuTest {

    //知道枚举的对象,怎么得到枚举的名称和下标
    @Test
    public void test1() {
        //得到枚举对象
        Color100 color100 = Color100.RED;
        //枚举的名称
        String name =color100.name();
        //枚举的下标
        int index =color100.ordinal();
        System.out.println(name+" "+index);
    }

    //知道枚举的名称,怎么得到枚举的对象和下标
    @Test
    public void test2() {
        String name1 = "GREEN";
        //得到枚举对象
        Color100 c1 = Color100.valueOf(name1);
        //得到枚举的下标
        int index1 = c1.ordinal();
        System.out.println(index1);
    }

    //知道枚举的下标,怎么得到枚举的对象和名称
    @Test
    public void test3() {

        int index3 = 2;
        //得到枚举对象
        Color100[] cs = Color100.values();
        //根据下表得到对象
        Color100 c3 = cs[index3];
        //得到枚举的名称
        String name3 = c3.name();
        System.out.println(name3);
    }
}

enum Color100{

    RED,GREEN,YELLOW;

}

3.静态导入

可以在java代码里面使用静态导入的方式,导入静态方法或常量
写法:

import static xxx.xxx.xxx

演示:

package importststic;

//演示静态导入
import static java.lang.System.out;
public class importStaticTest {

    public static void main(String[] args) {
        //传统写法
        System.out.println("hello1");
        //静态导入之后的写法
        out.println("hello2");
    }

}

4.自动拆装箱

装箱:把基本数据类型转换成包装类
拆箱:把包装类转换成基本数据类型
在JDK1.4是如何实现拆装箱的:

//在JDK1.4中实现拆装箱
    public void test1() {

        //装箱
        Integer mInteger = new Integer(10);

        //拆箱
        int a = mInteger.intValue();
    }

自动拆装箱:

public static void main(String[] args) {
        //自动装箱
        Integer integer = 10;

        //自动拆箱
        int i = integer;
    }

JDK是向下兼容的,在JDK1.4里的代码在5.0也可以运行。

5.增强for循环

语法:for(遍历出来的值:要遍历的集合)
数组或实现Iterable接口的集合可以使用增强for循环
list set集合实现了Iterator接口,可以使用增强for循环
map集合没有实现Iterator,不能使用增强for循环
增强for循环出现的目的:替代迭代器
增强for的底层就是迭代器

6.可变参数

应用场景:
假如有三个方法,实现两个数相加,实现三个数相加,实现四个数相加
如果实现的多个方法,这些方法里面的逻辑基本相同,唯一不同的是方法参数的个数,可以使用可变参数

public static void main(String[] args) {

        add1(10,20);

    }


    public static void add1(int...nums) {

        //num可以理解成一个数组,这个数组存储传递过来的参数
        System.out.println(nums.length);

        //遍历数组即可实现参数相加

    }

使用可变参数是需要注意的地方:
(1)可变参数需要写在方法的参数列表中,不能单独定义
(2)在方法的参数列表中只能有一个可变参数
(3)方法的参数列表中的可变参数,必须放在参数的最后

7.反射

应用在一些通用性比较高的代码中,大多数框架都是使用反射来实现的

1.反射介绍
在框架的开发中,都是基于配置文件来开发的
在配置文件中配置了类,可以通过反射得到类中的所有内容,可以让类中的某个方法执行。
类中的所有内容:属性、没有参数的构造方法,有参数的构造方法,普通方法

2.反射的原理
首先需要把java文件保存在本地硬盘.java
编译.java文件,得到.class文件
通过jvm,把.class文件通过类加载器加载到内存中
万事万物皆对象,.class文件在内存中使用Class类表示
当使用反射的时候,首先要获取到Class类,得到了这个类之后,就可以得到.class文件里面的所有内容
这里写图片描述

3.使用反射操作类中的构造方法
操作无参数的构造方法

//操作无参数的构造方法        
    @Test
    public void test1() throws Exception {
        //得到class
        Class clazz3 = Class.forName("fanshe.Person");
        //得到Person类的实例
        Person person = (Person) clazz3.newInstance();
        //设置一些值
        person.setName("zhangsan");
        System.out.println(person.getName());
    }

操作有参数的构造方法

    //操作有参数的构造方法
    @Test
    public void test2() throws Exception {
        //得到class
        Class clazz3 = Class.forName("fanshe.Person");
        //使用有参数的构造方法
//      clazz3.getConstructors(); 获取所有的构造方法

        //传递的是有参数的构造方法里面参数类型,类型使用class形式传递
        Constructor constructor = clazz3.getConstructor(int.class,String.class); 
        Person p1 = (Person) constructor.newInstance(100,"lisi");
        System.out.println(p1.getId()+" "+p1.getName() );
    }

4.使用反射操作属性(Field类表示属性)

    //使用反射操作name属性
    @Test
    public void test3() {
        try {
            //得到class
            Class clazz3 = Class.forName("fanshe.Person");
            //得到name属性
//          clazz3.getDeclaredFields() 表示得到所有的属性
            Field f1 = clazz3.getDeclaredField("name");
            //得到Person类的实例
            Person person = (Person) clazz3.newInstance();
            //设置可以操作私有的属性
            f1.setAccessible(true);
            //设置name值
            f1.set(person, "wangwu");
            System.out.println(person.getName());
        }catch (Exception e) {
            e.printStackTrace();
        }

    }

4.使用反射操作普通方法(Method类表示普通方法)
//使用反射操作普通方法
@Test
public void test4() throws Exception{

    //得到class
    Class clazz3 = Class.forName("fanshe.Person");
    //得到普通方法

// clazz3.getDeclaredMethods() 得到全部的普通方法

    //第一个参数是方法名称,第二个参数是方法里面的参数类型
    Method m1 = clazz3.getDeclaredMethod("setName", String.class);
    //得到Person实例
    Person p4 = (Person) clazz3.newInstance();
    //让setName方法执行,执行设置值
    m1.invoke(p4, "zhaoliu");
    System.out.println(p4.getName());
}

当操作的方法是静态方法的时候,因为静态方法的调用方式是类名.方法名,所以不需要类的实例
此时使用反射操作静态方法的时候也不需要类的实例

m1.invoke(null,"zhaoliu");

在invoke方法的第一个参数写一个null,表示操作的是静态方法

后记

接到活了,干活去,后面回来补

猜你喜欢

转载自blog.csdn.net/zyw644451/article/details/81234289