600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 泛型 泛型的表现 泛型类 泛型方法 泛型接口 通配符 限定

泛型 泛型的表现 泛型类 泛型方法 泛型接口 通配符 限定

时间:2020-11-30 08:18:22

相关推荐

泛型 泛型的表现 泛型类 泛型方法 泛型接口 通配符 限定

泛型

泛型技术泛型的表现泛型代码示例泛型练习(强转)泛型类泛型方法泛型接口通配符限定

泛型技术

在jdk1.4版本之前,容器什么类型的对象都可以存储,但在取出时,需要用到对象的特有内容时,需要做向下转型。但有时存入的对象类型不一致,会导致向下转型过程中出现ClassCastException。为了避免出现这个问题,只能在主观上控制,往集合中存储的对象类型保持一致。jdk1.5后解决了这个问题,在定义集合时,就直接明确集合内存储元素的具体类型。这样,编译器在编译时,可以对集合中存储的对象类型进行检查,一旦发现类型不匹配,就编译失败。

好处

将运行时期的问题转移到编译时期,可以更好的让程序员发现并解决问题。避免了向下转型的麻烦。

总结

泛型是应用在编译时期的一项安全机制

泛型的擦除

编译器通过对元素类型进行检查,只要检查通过,就会生成class文件,但在class文件中,就将泛型标识去掉了。

泛型的表现

泛型在集合框架中应用的范围很大。什么时候需要写泛型呢? 只要看到类,或者接口在描述时右边定义了<>,就需要泛型。其实是容器在不明确操作元素类型的情况下,对外提供一个参数<>使用容器时,只要将具体的类型实参传递给该参数即可简单的说,泛型就是传递类型参数

泛型代码示例

当我们使用增强for循环或者迭代器取出list的元素时,可以正常取出,即使是往这个集合中存不同数据类型的元素,比如字符串类型和int。但其实在编译运行的过程中,JVM会对存入的元素进行自动装箱和拆箱,

//list.add(4)等于list.add(Integer.valueOf(4))

而在使用迭代器时,使用的是Object类型接收,所以元素也可以正常取出。

而当我们将取出的类型定义为String时,无论是想要获取长度还是内容,运行时都会报错,抛出ClassCastException异常。而代码在编译时是没有报错的。

package com.rqy.day19;import java.util.ArrayList;import java.util.Iterator;import java.util.List;/*** 泛型*/public class GenericDemo {public static void main(String[] args) {List list = new ArrayList();list.add("abc");list.add(4);//list.add(Integer.valueOf(4))// for(Object obj : list){// System.out.println(obj);// }for(Iterator it = list.iterator();it.hasNext();){//Object obj = it.next();//System.out.println(obj.toString());String str = (String) it.next();System.out.println(str.length());System.out.println(str);}}}

为了运行时期不出现类型异常,可以在定义容器时,就明确容器中元素的类型,这样在编译期间,类型不符的元素就无法存入,会更安全。且当明确了类型后,就不需要使用强转。

泛型练习(强转)

加入泛型,对自定义的对象进行存入取出按照自然排序(年龄),和自定义排序(姓名)

自然排序

package com.rqy.day18;public class Person implements Comparable<Person> {private String name;private int 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;}public Person() {super();}public Person(String name, int age) {super();this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Person o) {int temp = this.getAge() - o.getAge();return temp == 0?this.getName().compareTo(o.getName()):temp;}}

Set<Person> set = new TreeSet<Person>();

自定义排序

package com.rqy.day18;import parator;public class CompaByName implements Comparator<Person> {//当指定泛型后,不需要使用强转@Overridepublic int compare(Person o1, Person o2) {int temp = o1.getName().compareTo(o2.getName());return temp==0?o1.getAge() - o2.getAge():temp;}//@Override// public int compare(Object o1, Object o2) {// Students s1 = (Students)o1;// Students s2 = (Students)o2;// int temp = s1.getName().compareTo(s2.getName());// return temp == 0?s1.getAge()-s2.getAge():temp;// return 0;// }}

package com.rqy.day19;import com.paByName;import com.rqy.day18.Person;import java.util.Iterator;import java.util.Set;import java.util.TreeSet;/*** 加入泛型,对自定义的对象进行存入取出* 按照自然排序(年龄),和自定义排序(姓名)* 自定义排序*/class GenericExample_1 {public static void main(String[] args) {//自定义排序,按照姓名Set<Person> set = new TreeSet<Person>(new CompaByName());set.add(new Person("lily",20));set.add(new Person("angle",20));set.add(new Person("vincy",29));set.add(new Person("lucy",25));set.add(new Person("zero",25));set.add(new Person("mary",24));for(Iterator<Person> it = set.iterator(); it.hasNext();){System.out.println(it.next());}}}

注意:若使用HashSet,需要覆盖HashCode和equals方法,但在equals方法中,参数就是Object,如果改成自定义的对象,就不是覆盖了

package com.rqy.day19;import java.util.HashSet;import java.util.Iterator;import java.util.Set;/*** HashSet演示 */public class HashDemo {public static void main(String[] args) {Set<Person1> set = new HashSet<Person1>();set.add(new Person1("lucy",23));set.add(new Person1("lucy",22));set.add(new Person1("lucy",23));set.add(new Person1("zero",20));set.add(new Person1("lucy",29));for(Iterator<Person1> it = set.iterator();it.hasNext();){System.out.println(it.next());}}}

package com.rqy.day19;import java.util.Objects;public class Person1 {private String name;private int 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;}public Person1() {super();}public Person1(String name, int age) {super();this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Override//该处的Object不可修改public boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person1 person1 = (Person1) o;return age == person1.age &&Objects.equals(name, person1.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}}

泛型类

package com.rqy.day19;class Tool{private Object obj ;public Object getObj() {return obj;}public void setObj(Object obj) {this.obj = obj;}}/*** 定义一个可以操作所有对象的工具类,可以降低对对象设置和获取的局限性* 但需要类型向上抽取*/public class GenericDemo_1 {public static void main(String[] args) {Tool tool = new Tool();tool.setObj(new Women());Women wo = (Women) tool.getObj();//需要强制类型转换System.out.println(wo);}}

但正是因为使用了强制类型转换,代码在编写时可能会产生一些错误,而这些错误在编译时期是不会被检查出的,但到了运行时期,就会抛出ClassCastException异常

jdk1.5之后,提供了新的解决方案。当类型不确定时,对外提供参数,使用者通过传递参数的形式来完成类型的确定。

//在类定义时就明确参数,由使用该类的调用者,来传递具体的类型class Util<W>{private W obj;public W getObj() {return obj;}public void setObj(W obj) {this.obj = obj;}}

Util<Women> ut = new Util<Women>();ut.setObj(new Women());//若类型不匹配,会直接编译失败Women wo = ut.getObj();//避免了向下转型System.out.println(wo);

当类型不匹配时,会直接编译失败

泛型方法

package com.rqy.day19;class Test<W >{void show(W w){System.out.println("show:"+w);}void prin(W w){System.out.println("print:"+w);}}public class GenericExample_2 {public static void main(String[] args) {//new一个Test对象,指定类型为StringTest<String> test = new Test<String>();test.show("ert");test.prin(123);//当往Test类中传非String类型的元素时,编译会报错}}

但现在的需求时,在不重新实例化一个对象的前提下,使用Test类下的prin方法打印int类型的元素。

这就需要使用到------泛型方法

package com.rqy.day19;class Test<W >{void show(W w){System.out.println("show:"+w);}//调用该方法的类型不明确,使用泛型public <Q> void prin(Q q){System.out.println("print:"+q);}}/*** 在不new新的Test对象下,输出int类型的元素* 思路:* 在方法上定义泛型*/public class GenericExample_2 {public static void main(String[] args) {//new一个Test对象,指定类型为StringTest<String> test = new Test<String>();test.show("rqy");//test.prin("boss");//当往Test类中传非String类型的元素时,编译会报错test.prin(6);//}}

注意:静态方法是无法访问类上定义的泛型的,如果静态方法需要定义泛型,只能定义在方法上。

//静态方法上定义泛型static <A> void staticShow(A a){System.out.println("static:"+a);}

泛型接口

package com.rqy.day19;import javax.crypto.spec.PSource;//泛型接口interface Inter<T>{public void show(T t);}//实现接口时明确类型//class Test1<String> implements Inter<String>{// @Override// public void show(String s) {// }//}//实现接口时不明确类型class Test1<W> implements Inter<W>{@Overridepublic void show(W w) {}}//继承Test1类时明确参数类型class Son extends Test1<String>{}public class GenericExample_3 {public static void main(String[] args) {Son son = new Son();son.show("rqyboss");}}

通配符

package com.rqy.day19;import java.util.*;/*** 通配符*/public class GenericExample_4 {public static void main(String[] args) {Set<String> set = new TreeSet<>();set.add("abc");set.add("rqy");set.add("zzz");set.add("uuu");List<String> list = new ArrayList<String>();list.add("rqy");list.add("ttt");list.add("bbb");printCollection(set);System.out.println("------------------");printCollection(list);}//使用迭代器取出,为了提高代码复用性,可以将其封装为方法//为了使得不论存入set或list都可以使用该方法,将参数换为Collection// private static void printCollection(Collection<String> set) {// for (Iterator<String> it = set.iterator(); it.hasNext();){// String str = it.next();// System.out.println(str);// }// }//但在不明确具体类型的情况下,可以将参数使用通配符?表示private static void printCollection(Collection<?> coll) {for (Iterator<?> it = coll.iterator(); it.hasNext();){Object obj = it.next();System.out.println(obj);}}}

限定

泛型的限定

确定了泛型上线? extend E:接受E类型或E的子类型

package com.rqy.day19;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import java.util.List;/*** 泛型的限定* 当同时需要对person1子类women或者man进行操作* 对于迭代器方法的参数选择,无论是选择woman还是man,代码的复用性都不高* 可以使用泛型中的限定* 既然woman和man都是person1的子类,那么参数直接使用? extends Person1即可*/public class GenericDemo_5 {public static void main(String[] args) {List<Women> list = new ArrayList<Women>();list.add(new Women("lily",23));list.add(new Women("zero",20));list.add(new Women("stacy",29));printCollection(list);}private static void printCollection(Collection<? extends Person1> coll) {for (Iterator<? extends Person1> it = coll.iterator(); it.hasNext();){Person1 obj = it.next();System.out.println(obj);}}}

确定了泛型下限? super E:接受E类型或E的父类型

package com.rqy.day19;import java.util.*;/*** 泛型的限定 */public class GenericDemo_5 {public static void main(String[] args) {List<Person1> list = new ArrayList<Person1>();list.add(new Person1("lily",22));list.add(new Person1("mary",20));list.add(new Person1("queen",29));printCollection(list);}private static void printCollection(Collection<? super Women> coll) {for (Iterator<? super Women> it = coll.iterator(); it.hasNext();){Object obj = it.next();System.out.println(obj);}}}

文章为学习笔记,如有不足之处还请指正

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。