Loading... > 集合中可以存放任意对象,只要把对象存储集合后,那么他们都会被提升为Object类型。当取出每一个对象,并且进行相应的操作,则必须进行类型转换。程序在运行时可能会发生java.lang.ClassCastException异常。 > Collection虽然可以存储各种对象,但实际上通常Collection只存储同一类型对象。例如都是存储字符串对象。因此在JDK5之后,新增了泛型(Generic)语法,在设计API时可以指定类或方法支持泛型,这样使用API的时候也变得更为简洁,并得到了编译时期的语法检查。 # 1、概念 泛型是一种未知的数据类型。泛型也可以看作是一个变量,用来接收数据类型。创建集合对象是,会确定泛型的数据类型。如果集合不使用泛型,则默认是Object类型。 # 2、好处 1. 将运行时期的ClassCastException,转移到了编译时期,变成了编译失败。 2. 避免了类型强转的麻烦。 【弊端】泛型是什么类型,则集合就只能存储什么类型的数据。 # 3、泛型的定义与使用 ## 3.1、含有泛型的类 * 格式 ```java has-numbering 修饰符 class 类名<代表泛型的变量> { // } ``` * 创建对象时确定泛型 * 示例 ```java has-numbering // 自定义泛型类 public class Test23<E> { private E e; public E getE() { return e; } public void setE(E e) { this.e = e; } } ``` ```java has-numbering // 调用 public class Test24 { public static void main(String[] args) { // 创建泛型为String的对象 Test23<String> myObj = new Test23<>(); // 调用setE myObj.setE("小学妹"); // 调用getE String e = myObj.getE(); System.out.println(e); // 创建泛型为Integer的对象 Test23<Integer> myObj1 = new Test23<>(); // 调用setE myObj1.setE(123); // 调用getE Integer e1 = myObj1.getE(); System.out.println(e1); } } ``` ## 3.2、含有泛型的方法 * 格式 ```java has-numbering 修饰符 <代表泛型的变量> 返回值类型 方法名(参数列表) { // } ``` * 调用方法时确定泛型,传递什么类型的参数,泛型就是什么类型 * 示例 ```java has-numbering // 自定义泛型方法 public class Test25 { public <E> void show(E e) { System.out.println(e.getClass()); } public <E> E show2(E e) { return e; } } ``` ```java has-numbering // 调用 public class Test26 { public static void main(String[] args) { Test25 myObj = new Test25(); myObj.show("hello"); myObj.show(123); myObj.show(12.34); System.out.println(myObj.show2("hello")); System.out.println(myObj.show2(123)); System.out.println(myObj.show2(12.34)); } } ``` ## 3.3、含有泛型的接口 * 格式 ```java has-numbering 修饰符 interface 接口名<代表泛型的变量> { // } ``` * 定义类时确定泛型 * 始终不确定泛型,创建对象时确定泛型 * 示例 ```java has-numbering // 定义泛型接口 public interface Test27<E> { public abstract void add(E e); public abstract E get(); } ``` ```java has-numbering // 创建类时确定泛型 public class Test28 implements Test27<String> { @Override public void add(String s) { System.out.println(s); } @Override public String get() { return null; } } ``` ```java has-numbering // 始终不确定泛型,创建对象时确定泛型 public class Test29<E> implements Test27<E> { @Override public void add(E e) { System.out.println(e.getClass()); } @Override public E get() { return null; } } // 创建对象时确定泛型 public class Test30 { public static void main(String[] args) { Test29<String> myObj = new Test29<String>(); myObj.add("hello"); Test29<Integer> myObj1 = new Test29<Integer>(); myObj1.add(123); } } ``` # 4、泛型通配符 当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符表示。但是一旦使用泛型的通配 符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。 【注意】 1. 使用泛型通配符时,不能创建对象 2. 使用泛型通配符时,只能作为方法的参数使用 3. 泛型不存在继承关系 * 示例 ```java has-numbering public static void main(String[] args) { Collection<Integer> list = new ArrayList<>(); list.add(123); list.add(456); list.add(789); getEle(list); Collection<String> list1 = new ArrayList<>(); list1.add("张三"); list1.add("李四"); list1.add("王五"); getEle(list1); } private static void getEle(Collection<?> coll) { for (Object o : coll) { System.out.println(o); } } ``` # 5、通配符高级使用–受限泛型 ## 5.1、泛型的上限 * 格式: `<? extends E>` * 含义:只能接受该类型及其子类 ## 5.2、泛型的下限 * 格式: `<? super E>` * 含义:只能接受该类型及其父类 ```java has-numbering public static void main(String[] args) { Collection<Integer> list1 = new ArrayList<>(); Collection<String> list2 = new ArrayList<>(); Collection<Number> list3 = new ArrayList<>(); Collection<Object> list4 = new ArrayList<>(); getEle1(list1); getEle1(list2); // 编译报错 getEle1(list3); getEle1(list4); // 编译报错 getEle2(list1); // 编译报错 getEle2(list2); // 编译报错 getEle2(list3); getEle2(list4); } // 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类 private static void getEle1(Collection<? extends Number> list1) { } // 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类 private static void getEle2(Collection<? super Number> list1) { } ``` > 感谢小伙伴们的关注! > 你的点赞、评论、关注、收藏是对博主的最大鼓励! > 持续更新JavaSE学习笔记!欢迎订阅专栏! 最后修改:2021 年 10 月 06 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏