Java-API-集合框架(三)-泛型

泛型的由来和基本使用

            1,因为集合可以存储的对象类型是任意的,在取出进行向下转型时,容易发生ClassCastException。
            所以JDK1.5以后就有了解决这个问题的技术:泛型。
            2,泛型的原理:其实就是在操作的元素类型不确定时,通过传递参数的形式来明确类型。
            3,泛型的体现就是 <参数类型变量>用于接收具体的实际元素类型。
            4,泛型技术在集合框架中应用非常广泛,只要记住:在使用类或者接口时,如果接口上有明确<>泛型。
            在使用时,就传递所需的数据类型即可。不传递会出现警告类型不安全提示。
            5,了解:泛型技术是用在编译器部分的技术,一旦类型检查正确,
                生成的class文件中就没有泛型标记了:这是的泛型的擦除。
            6,泛型的好处:
                6.1 将运行时期的ClassCastException异常转移到编译时期通过编译失败体现。
                6.2 避免了强制转换的麻烦。
            7,其实泛型的使用就是往定义了泛型的类或者接口的<>中传递类型参数。
    public static void main(String[] args) {
        
        
        /*
         * 为了让集合使用更安全,
         * 问题:什么类型的元素都可以存储。导致取出时,如果出现强转就会引发运行时 ClassCastException。
         * 能不能在创建集合时,就明确容器中的元素的类型,如同数组一样。
         * 目的是为了更安全。
         * JDK1.5以后,出现了解决方案,使用容器时,必须明确容器中元素的类型。
         * 这种机制:称之为 :泛型。
         * 体现 <数据类型>,不是很难理解,<>也是括号,往括号里面写东西其实就是在传递参数。
         * 泛型:
         * 1,安全机制。
         * 2,将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
         * 3,泛型技术,是给编译器使用的技术。
         * 4,避免了强转的麻烦。
         */
        //int[] arr = new int[];
        //创建集合时,直接在集合上明确要存储的元素的类型。
        List<String> list = new ArrayList<String>();
        
        list.add("abc");
        list.add("zzzz");
//      list.add(6);//只要不是指定的类型对象,编译器检查会 报错。这样将运行时的问题转移到编译时期。
        
        for (Iterator<String> it = list.iterator(); it.hasNext();) {
//          Object object = (Object) it.next();
//          System.out.println(object.toString());
            //想要打印字符串的长度。
            String str = it.next();
            System.out.println(str.length());
            
        }
    }

泛型的擦除

泛型的擦除

泛型类的使用

import java.util.LinkedList;

public class GenericDemo2 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        
//      Tool t = new Tool();
//      t.setObject(6);
//      String s = (String)t.getObject();
//      System.out.println(s);
        
        Tool<String> t = new Tool<String>();
//      t.setObject(6);//只要类型错误,编译失败。避免了运行时的类型转换异常。
        String s = t.getObject();//省去了强转的麻烦。
        System.out.println(s);
        

        
        Queue<String> queue = new Queue<String>();
        queue.myAdd("abcd1");
        queue.myAdd("abcd2");
        queue.myAdd("abcd3");
        while(!queue.isNull()){
            String string = queue.myGet();
            System.out.println(string);
        }
    }

}
//jdk1.5有了新技术,泛型,改成如下这样。
//类中操作的对象确定不?不确定,用Object,需要转型,运行容易出异常。不爽。
//在定义时,就将不确定的对象的类型,定义成参数。由使用该类的调用者来传递对象类型。
class Tool<Q>{//将泛型定义在类上,泛型类。
    private Q object;

    public Q getObject() {
        return object;
    }

    public void setObject(Q object) {
        this.object = object;
    }
    
}

class Queue<E>{
    //封装了一个链表数据结构。
    private LinkedList<E> link;
    /*
     * 队列初始化时,对链表对象初始化。
     */
    Queue(){
        link = new LinkedList<E>();
    }
    
    /**
     * 队列的添加元素功能。
     */
    public void myAdd(E obj){
        //内部使用的就是链表的方法。
        link.addFirst(obj);
    }
    
    /**
     * 队列的获取方法。
     */
    public E myGet(){
        return link.removeLast();
    }
    
    /**
     * 判断队列中元素是否空,没有元素就为true。
     */
    public boolean isNull(){
        return link.isEmpty();
    }
}

/*
//定义一个工具对对象进行操作,比如设置和获取。可以对任意对象进行操作。对共性类型Object操作。
//定义Object就哦了。但用的时候,因为提升为了Object,想要使用特有内容,需要向下转型。容易引发ClassCastException:
class Tool{
    
    private Object object;

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}
*/

泛型方法的使用

public class GenericDemo3 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        Util<String> util = new Util<String>();
        util.show("hehe");
//      util.print(5);
        Util<Integer> util2 = new Util<Integer>();
        Util.print(5);
        util2.show("hehe");
        
    }
}

class Util<W>{
    //当方法要操作的类型不确定和类上的泛型不一定一样。这时可以将泛型定义在方法上。
    public  <Q> void show(Q q){//泛型方法
        System.out.println("show:"+q);
    }
    public static<E> void print(E e){//记住:如果方法是静态,还需要使用泛型,那么泛型必须定义在方法上。
        System.out.println("print:"+e);
    }
    public void method(W w){
        
    }
}

泛型接口

public class GenericDemo4 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new InterImpl<String>().show("hehe");
    }

}

//泛型接口。
interface Inter<E>{
    void show(E e);
}
/*
class InterImpl implements Inter<String>{
    public void show(String e){}
}
*/

class InterImpl<T> implements Inter<T>{

    @Override
    public void show(T e) {
    }
}

泛型通配符(?)

public class GenericDemo5 {

    public static void main(String[] args) {
        
        Set<Student> list = new HashSet<Student>();
        
        list.add(new Student("lisi1",21));
        list.add(new Student("lisi2",22));
        list.add(new Student("lisi3",23));
        
        printList(list);
        
        List<String> list2 = new ArrayList<String>();
        
        list2.add("lisi11");
        list2.add("lisi22");
        list2.add("lisi33");
        
        printList(list2);
    }

    /*
     *  打印集合中的元素。
     *  
     *  当使用泛型类或者接口时,传递的具体的类型不确定,可以通过通配符(?)表示。
     *  
     */
    private static void printList(Collection<?> list2) {
        for (Iterator<?> it = list2.iterator(); it.hasNext();) {
            System.out.println(it.next().toString());
        }
    }
}
  • 通配符? 在api中的体现

public class GenericDemo7 {

    public static void main(String[] args) {
        
        /*
         * 通配符? 在api中的体现。
         * 
         * Collection接口: boolean containsAll(Collection<?> c) 
         */

        Collection<String> c1 = new ArrayList<String>();
        c1.add("haha");
        c1.add("hehe");
        
        Collection<Integer> c2 = new ArrayList<Integer>();
        c2.add(4);
        c2.add(5);
        
        boolean b = c1.containsAll(c2);//了解 containAll源码内判断是否包含的依据。依据是equals方法。
                                        //public  boolean equals(Object obj) "abc".equals(5);
        System.out.println("b="+b);
    }
}

/*
 * class Collection<E>
 * {
 *      public boolean containsAll(Collection<?> c){
 *      }
 * }
 */

泛型限定

public class GenericDemo6 {

    public static void main(String[] args) {
        
        Set<Student> list = new HashSet<Student>();
        
        list.add(new Student("lisi1",21));
        list.add(new Student("lisi2",22));
        list.add(new Student("lisi3",23));
        
        printList(list);
        
        List<Worker> list2 = new ArrayList<Worker>();
        
        list2.add(new Worker("lisi11",21));
        list2.add(new Worker("lisi22",22));
        list2.add(new Worker("lisi33",23));
        
        printList(list2);

        
    }

    /*
     *  打印集合中的元素。
     *  当使用泛型类或者接口时,传递的具体的类型不确定,可以通过通配符(?)表示。
     *  如果想要对被打印的集合中的元素类型进行限制,只在指定的一些类型,进行打印。
     *  使用泛型的限定。
     *  
     *  只需要打印学生和工人的集合。找到学生和工人的共性类型Person。
     *  ? extends Person : 接收Person类型或者Person的子类型。
     *  
     *  总结:
     *  ? super E:接收E类型或者E的父类型。下限。
     *  ? extends E:接收E类型或者E的子类型。上限。
     */
    private static void printList(Collection<? extends Person> list2) {
        for (Iterator<? extends Person> it = list2.iterator(); it.hasNext();) {
            
            Person p = it.next();
            System.out.println(p.getName());
        }
    }
}
  • 泛型限定在api中的使用

public class GenericDemo8 {

    public static void main(String[] args) {
        /*
         *  泛型的限定在api中的使用。上限的体现。
         *  TreeSet(Collection<? extends E> c) 
         *  
         *  
         */
        //创建一个Collection.
        Collection<Student> c = new ArrayList<Student>();
        c.add(new Student("wangcai1",26));
        c.add(new Student("wangcai2",29));

        //TreeSet集合在创建时,就将c中的存储到Treeset集合。
        TreeSet<Person> ts = new TreeSet<Person>(c);
        
        ts.add(new Person("lisi",20));
        
        for (Iterator<Person> it = ts.iterator(); it.hasNext();) {
            Person person =  it.next();
            System.out.println(person);
            
        }
    }
}

/*
 * class TreeSet<E>{
 *      TreeSet(Collection<? extends E> c){}
 */
运行结果
  • 泛型的限定在api中的使用。下限的体现

public class GenericDemo9 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        /*
         *  泛型的限定在api中的使用。下限的体现。
         *  TreeSet(Comparator<? super E> comparator) 
         *  
         *  
         */
        //创建一个集合存储的是学生对象。想要按照姓名排序。
        TreeSet<Student> ts = new TreeSet<Student>(new ComparatorByName());
        ts.add(new Student("abc",26));
        ts.add(new Student("aaa",29));
        ts.add(new Student("lisi",20));
        
        
        for (Iterator<Student> it = ts.iterator(); it.hasNext();) {
            Student student =  it.next();
            System.out.println(student);
            
        }
        
        //让工人按照姓名排序。
        TreeSet<Worker> ts2 = new TreeSet<Worker>(new ComparatorByName());
        ts2.add(new Worker("abc",26));
        ts2.add(new Worker("aaa",29));
        ts2.add(new Worker("lisi",20));
        
        
        for (Iterator<Worker> it = ts2.iterator(); it.hasNext();) {
            Worker worker =  it.next();
            System.out.println(worker);
            
        }
    }
}


class ComparatorByName implements Comparator<Person>{

    @Override
    public int compare(Person o1, Person o2) {
        int temp = o1.getName().compareTo(o2.getName());
        
        return temp==0? o1.getAge() - o2.getAge() : temp;
    }
    
}
/*
 * 以下两个比较器,都是通过姓名排序,就是类型不同,一个是student,一个是worker
 * 既然使用的都是Person的内容,为什么不定义一个Person的比较器。
 */
/*
//定义一个比较器。
class ComparatorByName implements Comparator<Student>{

    @Override
    public int compare(Student o1, Student o2) {
        int temp = o1.getName().compareTo(o2.getName());
        
        return temp==0? o1.getAge() - o2.getAge() : temp;
    }
    
}
//定义一个工人的姓名比较器。
class ComparatorByWorkerName implements Comparator<Worker>{

    @Override
    public int compare(Worker o1, Worker o2) {
        int temp = o1.getName().compareTo(o2.getName());
        
        return temp==0? o1.getAge() - o2.getAge() : temp;
    }
    
}
*/
/*
 * class TreeSet<E>{
 *      TreeSet(Comparator<? super E>  c){}
 */

泛型的细节

//      ArrayList<Dog> al = new ArrayList<Animal>();//使用泛型,要保证左右类型一致。
//      ArrayList<String> al = new ArrayList<Object>();
    
        List<Integer> list = new ArrayList<Integer>();
//      show(list);
    }
    public static void show(List<String> list){
        
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 自定义泛型 1.1、泛型的定义介绍 在集合中,不管是接口还是类,它们在定义的时候类或接口名的后面都使用<标识符>,...
    Villain丶Cc阅读 8,706评论 0 7
  • 转载: https://blog.csdn.net/s10461/article/details/53941091...
    DaneYang阅读 486评论 1 6
  • 1. 概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用。 什么是泛型?为什么要...
    小乖心塞阅读 353评论 1 2
  • 最近,日本演员矢野浩二摊上事儿了。他在一档综艺节目中的言论被截出:“中国人没资格养狗”。 但这其实是2012年的“...
    槽值阅读 4,809评论 28 65
  • 今天安慰自己是欺骗餐吧。 中午食堂打的菜。下午吃了水煮菠菜最后 还是没忍住走进了该路过的面包店。 吃了一个蛋黄酥 ...
    一画NF阅读 79评论 0 0