笔者目前在菲律宾工作,入行不过一年时间,对于泛型,在公司工作的时候基本都是封装好的,不需要自己手动去写,也没有认真的去了解一下,最近看了一篇文章,受益匪浅。
文章链接:https://blog.csdn.net/s10461/article/details/53941091
一对男女甲和乙在网吧上网,这时甲由于吃了地沟油做的饭菜,肠胃内进行了一系列物理作用,需要将产物排出体外,他来到男厕所,发现门口站着丙丁戊己等人已经在排队,而旁边的女厕所并没有人,由于网吧内多为男性,故此为了改变这种供不应求的状况,网吧决定取消男女厕所的区分,今天要说的就是泛型
泛型类的普通写法
1 public class 类名<T>{//这里不一定要用T表示泛型类型,常见的还有K,E,V 2 private T t;//定义成员变量 3 }
下面我用一个例子来说明
public class Animal { //名字 private String name; //动作 private String action; //行为 private String behavior; public String toString() { return action+name+behavior; } }
创建一个Animal类,该类有三个属性分别表示名字,会做的动作,以及会做的行为,构造方法就省略没贴了
package People; public class People { private String name; private String experience; public People(String name, String experience) { super(); this.name = name; this.experience = experience; } public String toString() { return experience+name; } }
其次创建一个People类,该类有两个属性分别表示名字和经历
1 //这里我定义了两个泛型类 2 public class Behavior<T,E>{ 3 private T t; 4 private E e; 5 //以及构造方法 6 public Behavior(T t, E e) { 7 super(); 8 this.t = t; 9 this.e = e; 10 } 11 //内部方法 12 public void go() { 13 System.err.println(t+""+e); 14 } 15 }
最后我定义了一个Behavior类,用了两个泛型类参数T和E
Animal animal = new Animal("旺财", "跟", "相依为命"); People people = new People("唐伯虎", "迷恋秋香的"); Animal animal2 = new Animal("祝枝山", "与好色如命的", "上演美女与野兽"); People people2 = new People("石榴姐", "不要因为我是娇花就怜惜我的"); //需要注意的是,泛型的类型参数只能是类类型(包括自定义 //类),不能是简单类型,同时传入的实参类型需与泛型的类型参 //数类型相同,例如people 对应People Behavior<People, Animal> behavior = new Behavior<People, Animal>(people,animal); Behavior<People, Animal> behavior2 = new Behavior<People, Animal>(people2,animal2); behavior.go(); System.err.println("-------------"); behavior2.go();
迷恋秋香的唐伯虎跟旺财相依为命 ------------- 不要因为我是娇花就怜惜我的石榴姐与好色如命的祝枝山上演美女与野兽
看到这里,结果已经很明显了,但是定义的泛型类,就一定要传入泛型类型实参么?并不是这样,在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。
看下面的例子
//使用String和Interger类 Behavior<String, Integer> behavior3 = new Behavior<String, Integer>("12345", 5); //未定义泛型类型实参 Behavior behavior4 = new Behavior("随便上传",1); behavior3.go(); System.err.println("--------"); behavior4.go();
执行结果
123455
--------
随便上传1
可以发现当未定义泛型类型实参的时候,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。同时不限于People和Animal这些自定义类
下面介绍一下泛型数组
在SUN的说明文档中提到过在java中是”不能创建一个确切的泛型类型的数组”的。
//eclipse会提示报错 //Cannot create a generic array of ArrayList<String> List<String>[] lsa = new List<String>[10]; Object o = lsa; Object[] oa = (Object[]) o; List<Integer> li = new ArrayList<Integer>(); li.add(new Integer(3)); oa[1] = li; // Unsound, but passes run time store check String s = lsa[1].get(0); // Run-time error: ClassCastException.
由于JVM泛型的擦除机制,在运行时JVM是不知道泛型信息的,所以可以给oa[1]赋上一个ArrayList而不会出现异常,但是在取出数据的时候却要做一次类型转换,所以就会出现ClassCastException,如果可以进行泛型数组的声明,上面说的这种情况在编译期将不会出现任何的警告和错误,只有在运行时才会出错。
下面看一个例子,我们使用泛型通配符?创建一个数组
List<?>[] arr = new ArrayList<?>[10]; List<String> list1 = new ArrayList<>(); List<Integer> list2 = new ArrayList<>(); list1.add("我是一个字符串"); list2.add(2); arr[0] = list1; arr[1] = list2; System.err.println(arr[0]); System.err.println(arr[1]);
[我是一个字符串]
[2]
可以发现在未指定具体类型的情况下,使用泛型通配符创建数组,我们可以存放任何类型的元素
就先说到这里,新人小白还有很多东西要学,最后吐槽一下菲律宾的厕所没有蹲坑,真是不习惯啊