听说Java泛型很难?我不信!

作为一个曾被泛型弄得死去活来的小辣鸡,这篇文章将致力于给大家以最清新舒服的方式来把泛型讲的清清爽爽~

首先我想以集合来为泛型开个头,现在咱们这里有一个需求:集合里面有字符串类的数据,我们要把它打印出来,代码很简单

public class TestDemo {
    public static void main(String[] args) {
        
        
        ArrayList a=new ArrayList();
        a.add("java01");//添加
        a.add("java02");
        a.add("java03");//a:java01,java02,java03
                //a.add(4);//加入一个整形
        Iterator it=a.iterator();
        while(it.hasNext())
        {
            String s=(String)it.next();
            sop(s);
            
        }
    }
    static void sop(Object e) {
        System.out.println(e);
    }
}

一天有一个好事者一不小心加入了一个整形变量,编译没有问题,但是在运行时会打印错误(把上文代码中的注释去掉,编译

java01
java02
java03
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at TestDemo.main(TestDemo.java:21)

代码抛了一个异常,问题在于Integer类型不能强转为String类型

问题来了,集合作为一个容器对于所有的对象都统统接收,那么我们能不能对容器加以限制,比如说,我们就要String类型的,其他的都统统的不接受?
答案是肯定可以的,主jio登场~(BGM ing.....

泛型

泛型能够限制传进来的类型
可能说起来有些抽象,我们还是用上面那个例子来说明,见代码

ArrayList a=new ArrayList();

修改一下

ArrayList<String> a=new ArrayList<String>();

这个时候,我们再试着添加整型4,编译报错

Multiple markers at this line
    - The method add(int, String) in the type ArrayList<String> is not applicable for the arguments 
     (int)
    - Type safety: The method add(Object) belong

意思大概是int类型的不能应用类型是String的添加方法

我们已经成功的用泛型来限定了传进去的类型了,在创建对象时<>中传入合适的类型

问题来了,使用泛型需要什么条件呢?

我们来看看ArrayList的JDK文档

Class ArrayList<E>

在ArrayList后面添加了<E>
我们在看看类中的方法

ArrayList中的方法.jpg

比如说add(E e)中参数的类型和Class ArrayList<E>中的E是一致的

也就是说我们在限定我们创建ArrayList时候的类型参数和后面方法中的参数是一致的,这里的E其实也就是Element的含义
需要注意的是JDK中的Iterator也允许泛型

这里再给出完整的代码

public class TestDemo {
    public static void main(String[] args) {
        
        
        ArrayList<String> a=new ArrayList<String>();
        a.add("java01");//添加
        a.add("java02");
        a.add("java03");//a:java01,java02,java03
        
        Iterator<String> it=a.iterator();
        while(it.hasNext())
        {
                        //String s-(String)it.next();
            String s=it.next();
            sop(s);
            
        }
    }
    static void sop(Object e) {
        System.out.println(e);
    }
}

这里可以给出两个添加泛型后的小结论

1、限定容器中的元素的内容
2、避免获得容器中内容的元素时需要强转
这里提出一个问题,是否我们自己能够使用泛型?
答案是肯定的,接下来给大家介绍常见的情况下使用泛型

类中加泛型

类中所有用到类定义时使用的类型的方法
也就是说,方法中传入的参数只要和定义类时参数一致,那么创建对象时就确定了


public class Person<E> {
    void show(E e)
    {
        System.out.println("show-----"+e);
    }
    
}
import javax.print.attribute.standard.MediaSize.Other;

public class TestDemo {
    public static void main(String[] args) {
        Person<String> p=new Person<String>();
        String s="abc";
        p.show(s);
    }
    static void sop(Object e) {
        System.out.println(e);
    }
}

打印一下

show-----abc

Person<E>和show(E e)中的E是同一个E,传入的类型就被确定了

我想让方法中使用自己的泛型行不行?也就是方法中的泛型与类无关
聪明的JAVA会告诉你,答案肯定也是可以的

方法中添加泛型

格式:修饰符+<E>+返回类型+方法名+参数
见代码

//方法中单独设置泛型
public class Person<E> {
    void show(E e)
    {
        System.out.println("show-----"+e);
    }
    public <T> void method(T t)
    {
        System.out.println("method----"+t);
    }
    public static <R> void function(R r)
    {
        System.out.println("function----"+r);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Person<String> p=new Person<String>();
        String s="abc";
        p.show(s);
        int num=201314;
        p.method(num);
        Person.function(520);
    }
    static void sop(Object e) {
        System.out.println(e);
    }
}

打印一下

show-----abc
method----201314
function----520
又有同学举手手说:好像泛型在很多地方都能够加
答案是肯定的,接下来我们一起来看还有那些地方能够加

接口中设置泛型

格式:interface+接口名+<E>

interface Inter<M>{
    void show(M m);
    <M> void method(M m);
    
}
public class InterTest implements Inter<String>{

    @Override
    public void show(String m) {
        // TODO Auto-generated method stub
        System.out.println("show---"+m);
    }

    @Override
    public <M> void method(M m) {
        // TODO Auto-generated method stub
        System.out.println("method----"+m);
    }

}

到这里了,我们来做一个小总结

泛型的使用非常广泛,类、方法、接口都可以使用泛型作为限定类型,其实它的本质就是打破了Object的使用,并且很好的维持了多态(因为避免了强转)

好事者又不服,认为我们既然利用泛型在创建时限定了类型,那么我现在有一个需求:我有一个Person类,还有一个Person的子类Student,我想把这两个类都打印出他们的属性,我想用一个通用的办法来打印

这个需求提的很好

泛型限定符

泛型不光支持任何单一类型,还支持具有继承关系的类型
格式:<? extends 类型>允许某一种类型极其子类
那么这里的需求很好的可以满足

//创建吗一个基本Person类
public class Person {
    private String name;
    private int age;
    Person(String name,int age)
    {
        this.age=age;
        this.name=name;
    }
    void show()
    {
        System.out.println("person-----"+name+age);
    }
}
//Person类的子类
public class student extends Person {
    private String name;
    private int age;
    private String xuehao;
    student(String name, int age,String xuehao) {
        super(name, age);
        this.xuehao=xuehao;
        // TODO Auto-generated constructor stub
    }
    void show() {
        System.out.println("stu----"+name+age+xuehao);
    }
    
}
//需求:用一种通用的方法打印Person和student类的基本属性
public class TestDemo {
    public static void main(String[] args) {
        ArrayList<Person> per_al=new ArrayList<Person>();
        per_al.add(new Person("xiaoming01",14));
        per_al.add(new Person("xiaoming02",12));
        per_al.add(new Person("xiaoming03",13));
        per_al.add(new Person("xiaoming04",42));
        per_al.add(new Person("xiaoming05",16));
        ArrayList<student> stu_al=new ArrayList<student>();
        stu_al.add(new student("xiaoming01",14,"201514160101"));
        stu_al.add(new student("xiaoming02",14,"201514160102"));
        stu_al.add(new student("xiaoming03",14,"201514160103"));
        stu_al.add(new student("xiaoming04",14,"201514160104"));
        printColl(per_al);
        printColl(stu_al);
    }
    public static void printColl(ArrayList<? extends Person> al)
    {
        Iterator<? extends Person> it=al.iterator();
        while(it.hasNext())
            it.next().show();
    }
    static void sop(Object e) {
        System.out.println(e);
    }
}

打印一下

person-----xiaoming0114
person-----xiaoming0212
person-----xiaoming0313
person-----xiaoming0442
person-----xiaoming0516
stu----null0201514160101
stu----null0201514160102
stu----null0201514160103
stu----null0201514160104

这样子,Iterator中的泛型的类型就允许接收Person和Person的子类

我们不光可以接收类及其子类,我们还可以接收类及其父类

格式:<? super student>

总结

在创建类、方法、接口的时候利用了泛型限定符,我们可以定义单类型,类以及其父类,类以及子类三种形式

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