• 【Java的集合框架工具类 泛型 30】


    一、泛型:jdk1.5(或者5.0)出现的安全机制。

    好处:
    1)、将运行时期出现的问题ClassCastException转到编译时期,泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全
    2)、避免了强制类型转换的麻烦

    1、<>什么时候用?
    当操作的引用数据类型确定的时候。就是用<>。将要操作的引用数据类型传入即可。其实<>就是一个用于接收具体引用数据类型的参数范围。
    在程序中,只要用到了带有<>的类或者接口,就要明确传入具体的引用数据类型。
    2、泛型的补偿擦除:运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除,为什么擦除呢?因为为了兼容运行的类加载器。
    3、泛型的补偿:在运行时,通过获取元素的类型进行转换动作,不用使用者在强制转换了

    --->在程序中,只要用到了带有<>的类或者接口,就要明确传入具体的引用数据类型。
    --->泛型不可以往里面写基本数据类型:如:<int>  但是可以写成<Integer>
    举例1:

    package com.JavaStudy01.Generic;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    /**
     * @Author wufq
     * @Date 2020/8/10 09:57
     */
    public class GenericDemo01 {
        public static void main(String[] args){
    
            //确定引用类型是String类型,那么在集合内只能存储String类型的数据,
            // 即:泛指是确定了引用类型(如:String),然后存储的也是特定的类型(如:String)
            ArrayList<String> al = new ArrayList<>();
            al.add("123");
            al.add("456");
    //        al.add(123);只能存储String类型,不能存其他的类型,因为对ArrayList做了泛指
    
            Iterator<String> it = al.iterator();
            while (it.hasNext()){
                String str = it.next();
                System.out.println(str);
            }
        }
    }

    举例2:自定义类型的比较(通过年龄和姓名)

    ----->通过年龄排序:Personew类<-----------

    package com.JavaStudy01.Bean;
    
    /**
     * @Author wufq
     * @Date 2020/8/10 11:03
     */
    //Comparable<T>接口用于实现对象的比较,比较时指定了对象则可实现指定对象的比较,如果不指定实现的是Object对象的比较
    public class Personew implements Comparable<Personew>{
        private String name;
        private int age;
    
        public Personew() {
            super();
        }
    
        public Personew(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public int compareTo(Personew per) {
    
            int temp = this.age-per.age;
    
            return temp==0?this.name.compareTo(per.name):temp;
        }
        /*
        public boolean equals(Object obj){}
        这个才是方法覆盖,如果是
        public boolean equals(Person p){}
        不是方法覆盖,因为equals是Object的方法,所以方法覆盖时参数”Object obj“不能修改。
         */
    
        //Comparable<Personew>泛指以后,IDEA直接用快捷方式:command+N来重写equals和hashCode
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            Personew personew = (Personew) o;
    
            if (age != personew.age) return false;
            return name != null ? name.equals(personew.name) : personew.name == null;
        }
    
        @Override
        public int hashCode() {
            int result = name != null ? name.hashCode() : 0;
            result = 31 * result + age;
            return result;
        }
    }

    ----->通过姓名排序:原始Personew类<-----------

    package com.JavaStudy01.Bean;
    
    /**
     * @Author wufq
     * @Date 2020/8/10 11:03
     */
    //Comparable<T>接口用于实现对象的比较,比较时指定了对象则可实现指定对象的比较,如果不指定实现的是Object对象的比较
    public class Personew {
        private String name;
        private int age;
    
        public Personew() {
            super();
        }
    
        public Personew(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }

    ----->通过姓名排序:ComparatorByNamePers类实现姓名排序<-----------

    package com.JavaStudy01.Bean;
    
    import java.util.Comparator;
    
    /**
     * @Author wufq
     * @Date 2020/8/10 14:51
     */
    public class ComparatorByNamePers implements Comparator<Personew>{
        @Override
        public int compare(Personew o1, Personew o2) {
    
            int temp = o1.getName().compareTo(o2.getName());
            return temp==0?o1.getAge()-o2.getAge():temp;
        }
    }

    ----->测试类:GenericDemo02类<-----------

    package com.JavaStudy01.Generic;
    
    import com.JavaStudy01.Bean.ComparatorByNamePers;
    import com.JavaStudy01.Bean.Personew;
    
    import java.util.Iterator;
    import java.util.TreeSet;
    
    /**
     * @Author wufq
     * @Date 2020/8/10 11:05
     */
    public class GenericDemo02 {
        public static void main(String[] args){
            //通过age进行比较
            TreeSet<Personew> ts = new TreeSet<>();
            ts.add(new Personew("lisi1",21));
            ts.add(new Personew("lisi2",22));
            ts.add(new Personew("lisi10",28));
            ts.add(new Personew("lisi8",10));
    
            Iterator<Personew> it = ts.iterator();
            while (it.hasNext()){
                Personew p = it.next();
                System.out.println(p.getName()+"::"+p.getAge());
            }
    
            System.out.println("----------------");
            //通过name进行比较
            TreeSet<Personew> tsp = new TreeSet<>(new ComparatorByNamePers());
            tsp.add(new Personew("lisi1",21));
            tsp.add(new Personew("lisi2",22));
            tsp.add(new Personew("lisi10",28));
            tsp.add(new Personew("lisi8",10));
    
            Iterator<Personew> itp = tsp.iterator();
            while (itp.hasNext()){
                Personew p = itp.next();
                System.out.println(p.getName()+"::"+p.getAge());
            }
    
        }
    }

    二、泛型类、方法、接口

    泛型类:

     1、如果一个工具类想对所有类进行操作,那么就可以定义一个Object

    package com.JavaStudy01.GenericDefault;
    
    /**
     * @Author wufq
     * @Date 2020/8/10 16:05
     */
    public class Tool {
        private Object object;
    
        public Object getObject() {
            return object;
        }
    
        public void setObject(Object object) {
            this.object = object;
        }
    }

    2、用工具类调用学生类,需要往里面存一个学生和取一个学生

    package com.JavaStudy01.Generic;
    
    import com.JavaStudy01.GenericDefault.Tool;
    import com.JavaStudy01.GenericUtil.Student;
    import com.JavaStudy01.GenericUtil.Work;
    
    /**
     * @Author wufq
     * @Date 2020/8/10 15:24
     */
    public class GenericDemo03 {
        public static void main(String[] args){
            Tool tool = new Tool();
    
            //往里面存了一个学生
            tool.setObject(new Student());
            tool.setObject(new Work()); //什么对象都能往里面存,好处是扩展性强了,但是也有弊端那就是取对象时都必须的强转。所以需要改进Tool类
    
            //取出来一个学生,学生存进去以后就意味着向上转型了(即:Student向上转为Object),所以需要强制转换
            Student stu= (Student) tool.getObject();
        }
    }

    发现:由于工具类里面采用了Object,所以任何对象都可以往里面存,但是的需要强转

    3、为了解决这个强转问题,也为了更安全,所以在工具类内引入了泛指类

    package com.JavaStudy01.GenericDefault;
    
    //使用泛型来接受类中要操作的引用数据类型
    // 泛型类。什么时候用?当操作类中的引用类型不确定时,就采用泛型类
    public class Tool<QQ>{
        private QQ q;
    
        public QQ getObject() {
            return q;
        }
    
        public void setObject(QQ q) {
            this.q = q;
        }
    }

    4、使用泛型后的引用

    package com.JavaStudy01.Generic;
    
    import com.JavaStudy01.GenericDefault.Tool;
    import com.JavaStudy01.GenericUtil.Student;
    
    /**
     * @Author wufq
     * @Date 2020/8/10 15:24
     */
    public class GenericDemo03 {
        public static void main(String[] args){
    
          // 使用泛型类后的引用
    
            Tool<Student> tool = new Tool<>();
            tool.setObject(new Student());
            Student stu = tool.getObject();// ---->不需要在进行强转了,
        }
    }

    泛型方法

     将泛型定义在方法上,目的是为了对任何类型进行传入或操作

    package com.JavaStudy01.GenericDefault;
    
    //使用泛型来接受类中要操作的引用数据类型
    // 泛型类。什么时候用?当操作类中的引用类型不确定时,就采用泛型类
    public class Tool<QQ>{
        private QQ q;
    
        public QQ getObject() {
            return q;
        }
    
        public void setObject(QQ q) {
            this.q = q;
        }
    
        /*将泛型定义在方法上:目的是可以对任何类型进行传入或操作*/
    
        public <W> void show(W str){
            System.out.println(str);
        }
    
        public void print(QQ str){
            System.out.println(str);
        }
    
        /*
        * 当方法静态时,不能访问类上定义的泛型。
        * 如果静态方法使用泛型,只需要将泛型定义在方法上
        * */
    
        public static <W> void method(W w){
            System.out.println(w);
        }
    }
    package com.JavaStudy01.Generic;
    
    import com.JavaStudy01.GenericDefault.Tool;
    
    /**
     * @Author wufq
     * @Date 2020/8/14 09:41
     */
    public class GenericDemo04 {
        public static void main(String[] args){
            Tool<String> tool = new Tool<>();
    
            //可以传入任意类型的值
            tool.show("123");
            tool.show(new Integer(888));
            tool.show(1.2);
    
            //print方法的参数是泛型类型,同样不能传入任何类型的值
            tool.print("567");
    //        tool.print(new Integer(999)); //
    
            //静态方法使用泛型
            Tool.method(new Integer(123));
            Tool.method("456");
    
    
        }
    }

     泛型接口

    package com.JavaStudy01.Generic;
    
    import com.sun.org.apache.xpath.internal.operations.String;
    
    /**
     * @Author wufq
     * @Date 2020/8/18 16:55
     */
    public class GenericDemo05 {
        public static void main(String[] args){
    
            Interclass1<Integer> ic2 = new Interclass1<>();
            ic2.method(123);
    
        }
    }
    
    interface  Inter<T>{
        public void method(T t);
    }
    
    //在定义类时不明确类型,但是在方法上是明确的
     class Interclass1 <K> implements Inter<K> {
    
        @Override
        public void method(K k) {
            System.out.println(k);
        }
    }

     三、泛型限定(上下限定)

    可以对类型进行限定:
     上限:? extend E:接收E类型或者E的子类型对象。

     下限: ? super E:接收E类型或者E的父类型。

    1、举例:多个基本类型的集合迭代(上限)

    package com.JavaStudy01.Generic;
    
    import java.util.*;
    
    /**
     * @Author wufq
     * @Date 2020/8/19 10:39
     * 泛型限定(上限)
     * 基本类型:多个集合的迭代
     */
    public class GenericAdvanceDemo01 {
        public static void main(String[] args){
            ArrayList<String> al = new ArrayList<>();
            al.add("abc");
            al.add("bbb");
    
    
            LinkedList<String> al2 = new LinkedList<>();
            al2.add("abc");
            al2.add("bbb");
    
            HashSet<String> al3 = new HashSet<>();
            al3.add("abc");
            al3.add("bbb");
    
            printCollection(al);
            printCollection(al2);
            printCollection(al3);
    
            System.out.println("-----------");
            printCollection1(al);
    
            System.out.println("-----------");
            printCollection2(al);
    
    
    
        }
    
        //多个集合,并且每个集合的类型是不一样的,这时候就需要他们的一个父类的集合Collection
        public static void printCollection(Collection<String> al) {
    
            Iterator<String> it = al.iterator();
            while (it.hasNext()){
                String msg = it.next();
                System.out.println(msg);
            }
        }
    
        //不光集合是不同的,同样集合内的类型也是不同的并且是未知的-->可以用到通配符:?
        public static void printCollection1(Collection<?> al) {
            Iterator<?> it = al.iterator();
            while (it.hasNext()){
    //            String msg = it.next();   -->通配符因为不知道是什么类型,所以不能赋值给特定的类型
                System.out.println(it.next());
    
            }
    
        }
    
        //指定了一个具体的类型,那么这个类型就可以被操作。所以和通配符的区别在于:通配符不能进行操作,而指定类型确可以操作
        public static <T> void printCollection2(Collection<T> al) {
            Iterator<T> it = al.iterator();
            while (it.hasNext()){
                T msg = it.next();
                System.out.println(msg);
    
            }
    
        }
    
    }

    2、举例:多个自定义类型的集合迭代(上限)

    package com.JavaStudy01.Generic;
    
    import com.JavaStudy01.Bean.Person;
    import com.JavaStudy01.GenericUtil.Student;
    import com.JavaStudy01.GenericUtil.Work;
    
    import java.util.*;
    
    /**
     * @Author wufq
     * @Date 2020/8/19 10:47
     * 自定义类型:多个集合的迭代
     */
    public class GenericAdvanceDemo02 {
        public static void main(String[] args){
            ArrayList<Work> al = new ArrayList<>();
            al.add(new Work("张三",21));
            al.add(new Work("李四",22));
    
            LinkedList<Student> lk = new LinkedList<>();
            lk.add(new Student("张三",21));
            lk.add(new Student("李四",22));
    
    
            //打印容器中的元素 -->但是这个容器有个条件?只打印person的子类
            printCollectionAction(al);
            printCollectionAction(lk);
        }
    
    
        /*public static void printCollectionAction(Collection< Person> al)
             (Collection<Person> al = new ArrayList<Work>())  -->其实参数是这样的,引用和实体其实是泛型不匹配
        {
            Iterator<String> it = al.iterator();
            while (it.hasNext()){
                String msg = it.next();
                System.out.println(msg);
            }
    
        }*/
    
        //针对以上的错(仍然无法打印Person的子类),改进:只需要把通配符继承一下Person类
        public static void printCollectionAction(Collection<? extends Person> al) {
    
            Iterator<? extends Person> it = al.iterator();
            while (it.hasNext()){
    
                //用Person类接受,迭代器就可以对Person类里面的数据进行操作
                Person p = it.next();
                System.out.println(p.getName()+"::"+p.getAge());
            }
        }
    
    
    }

    2、举例:多个自定义类型的集合迭代(下限)

    package com.JavaStudy01.Generic;
    
    import com.JavaStudy01.Bean.Person;
    import com.JavaStudy01.GenericUtil.Student;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    import java.util.LinkedList;
    
    /**
     * @Author wufq
     * @Date 2020/8/19 11:43
     * 泛型限定(下限)
     */
    public class GenericAdvanceDemo03 {
    
        public static void main(String[] args){
            ArrayList<Person> al = new ArrayList<>();
    
            al.add(new Person("张三",21));
            al.add(new Person("李四",22));
    
            LinkedList<Student> lk = new LinkedList<>();
            lk.add(new Student("张三",21));
            lk.add(new Student("李四",22));
    
            //打印容器中的元素 -->但是这个容器有个条件?只打印person的子类
            printCollectionAction(al);
            printCollectionAction(lk);
        }
    
    
        public static void printCollectionAction(Collection<? super Student> al) {
    
            Iterator<? super Student> it = al.iterator();
            while (it.hasNext()){
    
                System.out.println(it.next());
            }
        }
    }

     四、泛指上限、下限、通配符体现。

    1、泛指上限:一般在存储元素的时候使用上限,因为这样去除都是按照上限类型来运算的。不会出现类型安全隐患

    ------->addAll(Collection<? extends E> c)<-------

    addAll(Collection<? extends E> c)    将指定Collection中的所有元素都添加到此Collection种

    package com.JavaStudy01.Generic;
    
    import com.JavaStudy01.Bean.Person;
    import com.JavaStudy01.GenericUtil.Student;
    import com.JavaStudy01.GenericUtil.Work;
    
    import java.util.ArrayList;
    import java.util.LinkedList;
    
    /**
     * @Author wufq
     * @Date 2020/8/24 10:49
     * 泛指上限高级应用
     * 一般在存储元素的时候使用上限,因为这样去除都是按照上限类型来运算的。不会出现类型安全隐患。
     * addAll(Collection<? extends E> c)  将指定Collection中的所有元素都添加到此Collection中
     */
    public class GenericAdvanceDemo04 {
        public static void main(String[] args){
    
            ArrayList<Person> al = new ArrayList<>();
            al.add(new Person("张三",21));
            al.add(new Person("李四",22));
    
            LinkedList<Student> lk = new LinkedList<>();
            lk.add(new Student("张三1",21));
            lk.add(new Student("李四1",22));
    
            ArrayList<Work> al1 = new ArrayList<>();
            al1.add(new Work("张三2",21));
            al1.add(new Work("李四2",22));
    
            ArrayList al2 = new ArrayList();
            al2.add("uuu");
    
    
            al.addAll(al2);
            System.out.println(al.toString());
    
        }
    }
    
    class MyCollection<E>{
        public void add(E e){
    
        }
    
        public void addAll(MyCollection<? extends E> e){
    
        }
    }
    ====执行结果====
    [张三::21, 李四::22, uuu]
  • 相关阅读:
    salt+jenkins+gitlab+ecs构建公司部署平台
    解决openstack实例主机名后缀问题
    测试CentOS-7-x86_64-Minimal-1708.iso这种光盘安装效果
    dbca建库--linux上使用vnc图形化安装oracle10g版本
    使用mediainfo工具统计每个视频文件(媒体文件)播放时长
    rsync命令简单用法介绍
    winscp工具和xshell连接linux机器时切换到root账户
    zabbix和iptables的nat表结合使用
    adb和机顶盒一些常识
    VirtualBox虚拟机禁止时间同步
  • 原文地址:https://www.cnblogs.com/frankruby/p/13494879.html
Copyright © 2020-2023  润新知