泛型
-
泛型的本质:参数类型化
-
概述:将类型由原来的具体的类型参数化,然后在 使用/调用 时传入具体的类型
-
格式:
- <类型>
- 指定一种类型的格式,这里的类型可以看成是 方法中的形参(如果不理解可去看下形参和实参)
- 并且 类型 只能是 引用类型,不能是基本数据类型
- <类型>
-
好处:
-
把运行时期的问题提前到了编译期间
import java.util.ArrayList; import java.util.Collection; public class Test{ // 遍历集合 public static void show(Collection co){ for(Object c : co){ System.out.println(c); } } public static void main(String args[]){ // 1、创建集合对象,Collection 是接口,所以创建对象只能用其子类实现类 Collection c = new ArrayList(); // 2、添加元素 c.add(1); c.add("张三"); c.add(true); // 3、遍历集合 show(c); } }
注意:我们可以看到,此时的 Collection 集合可以添加任意数据类型,但是大家思考一个问题,集合中存储不同数据类型,是否会影响我们后期对于集合中数据的操作呢?答案是肯定的,怎么解决呢,我们就可用到泛型。
这样,我们就可以将 问题 提前到了 编译期间!
-
避免了强制类型转换
-
泛型类
-
格式: 修饰符 class 类名<参数类型>{}
// 学生泛型类 class Student<T>{ private T value; // 定义私有变量 public Student(T value){ this.value = value; } public T getValue(){ return value; } public void setValue(T value){ this.value = value; } } // 测试类 public class Test1{ public static void main(String args[]){ // 这里的 <> 中 String 和 Integer 是实参,T 是形参 Student<String> s1 = new Student<String>("张三"); Student<Integer> s2 = new Student<Integer>(1); System.out.println(s1.getValue() + " " + s2.getValue()); } }
最终运行结果:张三 1
泛型方法
-
格式:修饰符 <类型> 返回值类型 方法名(类型 变量名){}
class Cat{ // 泛型方法 public <T> T show(T t){ return t; } } public class Test{ public static void main(String args[]){ // 1、创建对象 Cat t = new Cat(); // 2、调用泛型方法,传入不同的参数 String s = t.show("张三"); int i = t.show(1); System.out.println(s + " " + i); } }
最终运行结果:张三 1
泛型接口
-
格式:修饰符 interface 接口名 <类型>{}
interface Animal<T>{ // 抽象方法 public void show(T t); } // 实现 泛型接口 class Dog implements Animal<String>{ @Override public void show(String s) { System.out.println(s); } } public class Test{ public static void main(String[] args) { Dog d = new Dog(); d.show("李四"); } }
类型通配符
-
类型通配符:<?>
-
例如:List<?>:表示元素类型未知的List,他的元素可以匹配任何的类型
这种带通配符的List仅表示它是各种泛型的List的父类,并不能把元素添加到其中
范围 格式 举例 作用 任意类型 <?> List<?> 表示的类型是所有 上限 <? extends 类型> List<? extends Number> 表示的类型是Number或者其子类 下限 <? super 类型> List<? super Number> 表示的类型是Number或者其父类