美文网首页java基础入门
Java基础——jdk1.5新特性及集合与数组的转换

Java基础——jdk1.5新特性及集合与数组的转换

作者: 阿Q说代码 | 来源:发表于2019-02-20 17:37 被阅读20次

    jdk1.5的新特性

    泛型是一种泛泛的类型,泛指某一种类型,是在创建对象或者调用方法或者实现接口才明确的类型。

    泛型好处提高安全性(将运行期的类型转换错误提前到编译期),省去强转的麻烦。

    泛型使用注意事项

    1. <>中放的必须是引用数据类型;
    2. 前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型) (建议后面的也写全);
    3. 在创建对象或者调用方法或者实现接口明确泛型的时候,尽量不要明确成Object,因为这样做没有意义(泛型的由来就是由Object的转型的问题得到的);
    4. 泛型是JDK1.5出现的。

    代码演示:

    public static void demo1() {
        ArrayList list = new ArrayList();
        list.add(110);//添加一个Integer类型的 110,在没有使用泛型的时候 list可以添加任意的引用类型  
        list.add(true); //添加一个Boolean类型的 true
        list.add(new Person("张三", 23)); //添加一个Person
        Iterator it = list.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());  //将集合里面的元素打印出来
        }
    }
    
    public static void demo2() {
        ArrayList list = new ArrayList();
        list.add(110);          
        list.add(true);             
        list.add(new Person("张三", 23)); 
        Iterator it = list.iterator();
        while(it.hasNext()) {
            //如果我想使用Person的特有功能 需要强制转换成Person类型
            Person p = (Person)it.next();//编译不报错, 运行的时候立刻报错,因为存储的 110 和 true 并不是Person类型 单却强制转换成Person类型 会报出类型转换错误          
            System.out.println(p.getName() + "..." + p.getAge());
        }
    }
    
    //ArrayList存储字符串并遍历泛型版
    public static void demo3() {
        ArrayList<Person> list = new ArrayList<>();     //<Person>规定 list对象里面必须存储Person类型的元素,存储其他类型的编译就会报错
        list.add(new Person("张三", 23));
        list.add(new Person("李四", 24));
        list.add(new Person("王五", 25));
        list.add(new Person("赵六", 26));
    
        Iterator<Person> it = list.iterator();          //获取的迭代器也是Person类型的泛型
        while(it.hasNext()) {
            Person p = it.next();               //it.next()获取到的元素 就不再是Object了,泛型里面规定的类型 it.next()就获取什么样类型的元素,所以就不用强制类型转换了
            System.out.println(p.getName() + "..." + p.getAge());
        }
    }
    
    
    public static void main(String[] args) {
        //ArrayList<int> list = new ArrayList<int>();       //编译报错 <>中放的必须是引用数据类型 
        //ArrayList<Object> list = new ArrayList<Person>(); //编译报错 集合的泛型要保证前后的数据类型一致
        ArrayList<Object> list = new ArrayList<>();//泛型最好不要定义成Object,没有意义,1.7版本的新特性,菱形泛型,后面的<>可以不用填写
        list.add("aaa");
        list.add(true);
    }
    
    泛型类: public class 类名<泛型类型1,泛型类型2,....>{}
    public class Worker<QQ> {
        public void show(QQ qq){
            System.out.println(qq);
        }
    }
    public class Worker<QQ,MM,DD,RR> {  //可以写一个泛型 也可以写多个
        public void show(QQ qq){
            System.out.println(qq);
        }
    }
    
    泛型非静态方法: public <泛型类型> 返回类型 方法名(泛型类型 变量名){}

    代码演示:

    public class Demo1_Generic {
        public static void main(String[] args) {
            /*Tool t = new Tool();
            t.show("abc");      //调用show(String s)方法 传入一个"abc"
            t.show(100);*/      //调用show(Integer i)方法 传入一个100
            //如果想继续接着调用一个show(Student s)方法, 就需要继续修改Tool类,再继续编写一个show(Student s)方法 才能调用
            //如果想继续接着调用一个show(Animal a)方法, 就需要继续修改Tool类,再继续编写一个show(Animal a)方法 才能调用
            //如果想继续接着调用一个show(Worker w)方法, 就需要继续修改Tool类,再继续编写一个show(Worker w)方法 才能调用
            //这样修改  将无穷无尽,所以用下面的泛型类改进代码
    
            /*Tool1<String> t = new Tool1<>();  //想调用show方法 传入一个"abc" 那么就创建一个泛型为String的对象
            t.show("abc");
            
            Tool1<Integer> t1 = new Tool1<>();  //想调用show方法 传入一个100 那么就创建一个泛型为Integer的对象
            t1.show(100);
    
            Tool1<Student> t2 = new Tool1<>();  //想调用show方法 传入一个Student 那么就创建一个泛型为Student的对象
            t2.show(new Student());*/       
            //如果想接着调用show方法 传入一个Animal 就又要创建一个泛型为Animal的对象 ,每次都要创建一个新的对象 浪费空间 所以用下面的泛型方法改进
    
            Tool2 t = new Tool2();  
            t.show("abc");  //调用show方法的时候就明确了QQ是String类型
            t.show(100);//调用show方法的时候就明确了QQ是Integer类型
            t.show(new Student());//调用show方法的时候就明确了QQ是Student类型
            //想传什么样的类型都可以 而且代码非常的简单
        }
    }
    public class Tool {
        public void show(String s) {
            System.out.println(s);
        }
        public void show(Integer i) {
            System.out.println(i);
        }
    }
    
    public class Tool1<QQ> {
        public void show(QQ qq){
            System.out.println(qq);
        }
    }
    public class Tool2 {
        public <QQ>void show(QQ s){
            System.out.println(s);
        }
    }
    
    泛型静态方法: public static <泛型类型> 返回类型 方法名(泛型类型 变量名){}
    public class Tools<Q> { 
        /*public static void show(Q q) {        //编译报错,因为静态的 优先于对象而存在
                System.out.println(q);
        }*/
        public static<W> void print(W w) {      //静态方法必须声明自己的泛型
            System.out.println(w);
        }
    }
    
    泛型接口:public interface 接口名<泛型类型>

    子类在实现父接口的时候可以明确泛型,也可以直接沿用父类的泛型

    代码演示:

    interface Inter<T> {
        public void show(T t);
    }
    
    class Demo implements Inter<String> {       //子类在实现父接口的时候 可以明确泛型 明确成了String类型
        @Override
        public void show(String t) {
            System.out.println(t);
        }
    }
    
    class Demo<T> implements Inter<T> {     //也可以直接沿用父类的泛型 T
        @Override
        public void show(T t) {
            System.out.println(t);
        }
    }
    
    泛型-通配符:

    A:泛型通配符<?>任意类型

    List<?> list = new ArrayList<Integer>(); //当右边的泛型是不确定时,左边可以指定为?
    B:<? extends E >明确泛型的时候明确成E或者E的儿子
    代码演示:

    public static void main(String[] args) {
        ArrayList<Person> list1 = new ArrayList<>();
        list1.add(new Person("张三", 23));
        list1.add(new Person("李四", 24));
        list1.add(new Person("王五", 25));
    
        ArrayList<Student> list2 = new ArrayList<>();
        list2.add(new Student("赵六", 26));
        list2.add(new Student("周七", 27));
    
        //boolean addAll(Collection<? extends E> c)
        list1.addAll(list2);        //Student 是Person的儿子 所以 可以添加成功
        System.out.println(list1);
    }
    

    C:<? super E >明确泛型的时候明确成 E或者E的父类

    增强for循环

    为了简化数组或者集合的遍历而出现的(JDK1.5出现的)

    for(集合或者数组里面元素的数据类型 变量名 : 数组或者集合){
        直接使用变量名就ok;
    }
    

    代码演示:

    public static void demo1() {
        int[] arr = {11,22,33,44,55};
        for (int i : arr) {     //增强for循环可以遍历数组
            //增强for循环在遍历数组或者集合的时候,优点:代码的书写确实简单了,但缺点是遍历时候没有索引,如果想用索引的时候,就请用普通for循环
            System.out.println(i);
        }
    
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
    
        for (String string : list) {    //增强for循环可以遍历集合
            System.out.println(string);
        }
    }
    

    遍历过程中能否删除元素总结:
    1)普通for循环在遍历的时候(只能遍历List体系的集合),可以删除,但是在删除过程中索引会改变, size也会发生改变,所以容易出现漏删的情况。

    解决:索引--,代码片段如下:

    ArrayList<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("b");
    list.add("c");
    list.add("d");
    for(int i = 0; i < list.size(); i++) {
        if("b".equals(list.get(i))) {
            list.remove(i--);   //通过索引删除元素
        }
    }
    

    2)迭代器在遍历集合的时候 Iterator(可以遍历任何单列集合),不可以通过集合操作元素,否则会报并发修改异常。只能通过迭代器自身来对元素进行操作,如果是删除:可以用Iterator 也可以用ListIterator 因为他们里面都有remove();如果是添加:只能使用ListIterator,因为只有ListIterator里面有add()
    代码片段如下:

    ArrayList<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("b");
    list.add("c");
    list.add("d");
    Iterator<String> it = list.iterator();
    while(it.hasNext()) {
        if("b".equals(it.next())) {
            //list.remove("b"); //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
            it.remove();        //让迭代器自己来删除元素
        }
    }
    

    3)增强for循环遍历集合的时候(可以遍历任何单列集合),由于底层就是调用的迭代器,所以不能删除,只能遍历。代码片段如下:

    ArrayList<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("b");
    list.add("c");
    list.add("d");
    for (String string : list) {
        if("b".equals(string)) {
            list.remove("b");   //运行报错,并发修改异常,增强for循环底层用的是迭代器 所以不能在迭代器过程中让集合来删除元素,如果用迭代器自己来删除 ,哪有迭代器来让你使用呢?,在底层呢 你又看不到
        }
    }
    System.out.println(list);
    

    可变参数
    格式:修饰符 返回值类型 方法名(数据类型 ... 变量名){}
    注意:

    1. 可变参数是JDK1.5后出现的新特性
    2. 可变参数其实是一个数组,所以调用带有可变参数的方法的时候,可以传入一个相同类型的数组
    3. 有多个参数的时候,可变参数放到最后

    代码演示:

    public class Demo3_ChangeableArgs {
        public static void main(String[] args) {
            int[] arr = {11,22,33,44,55};
            print();            //调用的时候 可以不传入参数
            print(arr);         //调用的时候 可以传入一个数组,因为可变参数的底层就是使用的数组
            print(11,22,55);        //调用的时候 可以传入多个参数        
        }
    
        public static void print(int ... arr) { //可变参数其实是一个数组
            for (int i = 0; i < arr.length; i++) {
                System.out.println(arr[i]);
            }
        }
        public static void show(String s , int ... arr) {   //有多个参数的时候,可变参数放到最后
    
        }
        /*
            public static void method(int ... arr , String s) { //编译报错 有多个参数的时候,可变参数放到最后
    
            }*/
    }
    
    //可变参数的应用
    public class Demo4_ChangeableArgs {
        public static void main(String[] args) {    
            //求两个数的最大值,我需要定义一个,含两个参数的方法max(int a , int b)
            int big = max(5,6);
            //假如现在需求变了,我想求三个数的最大值,那么我需要定义一个含三个参数的方法 max(int a , int b , int c)
            int big1 = max(5,6,10);
    
            //假如现在需求又变了,我想求四个数的最大值,难道我就再继续定义一个含有四个参数的方法 max(int a , int b , int c , int d)吗? 这样太麻烦了, 解决方案就是 用可变参数
            int big2 = max(11,432,7,87,23);
        }
    
        //求两个数的最大值
        public static int max(int a , int b) {
            return a>b?a:b;
        }
    
        //求三个数的最大值
        public static int max(int a , int b , int c) {
            return a>b ? (a>c?a:c) : (b>c?b:c);
        }
    
        //求任意个数的最大值
        public static void max(int ... arr) {   //可变参数其实是一个数组
            int a = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if(arr[i]> a){
                    a = arr[i]
                }
            }
            return a;
        }
    }
    

    集合和数组之间的转换

    Arrays工具类的asList(T ... t):将数组转成集合(该方法用的可变参数)
    注意:

    1)返回一个长度固定的集合,可以改和查,不能增和删,也就是改变其长度的操作都不可以做。

    2)将数组转换成集合,数组必须是引用数据类型。

    Collection中toArray(T[] a)泛型版的集合转数组:

    T[] 明确成什么样的数组 toArray(T[] a)方法就返回什么类型的数组

    注意:当集合转换数组时,数组长度如果是小于等于集合的size时,转换后的数组长度等于集合的size;如果数组的长度大于了size,分配的数组长度就和你指定的长度一样。

    好了今天就先说到这了,想了解更多学习知识,请关注微信公众号“阿Q说”,获取更多学习资料吧!你也可以后台留言说出你的疑惑,阿Q将会在后期的文章中为你解答。每天学习一点点,每天进步一点点。

    相关文章

      网友评论

        本文标题:Java基础——jdk1.5新特性及集合与数组的转换

        本文链接:https://www.haomeiwen.com/subject/pyzhyqtx.html