什么是泛型为什么要使用泛型
泛型就是参数化类型
泛型的作用
减少重复代码
像dao接口中存在样式雷同的代码: EmpDao: package com.aaa.gen.dao; import com.aaa.gen.entity.Emp; import java.util.List; /** * 员工管理dao接口 DetpDao: */ public interface EmpDao { /** * 查询所有的员工信息 * @return */ public List<Emp> listAll(); /** * 保存员工信息 * @param emp * @return */ public int save(Emp emp); /** * 删除员工信息 * @param emp * @return */ public int delete(Emp emp); /** * 修改员工信息 * @param emp * @return */ public int update(Emp emp); /** * 根据主键查询 员工的信息 * @param id * @return */ public Emp find(Long id); } package com.aaa.gen.dao; import com.aaa.gen.entity.Dept; import java.util.List; /** * 部门管理dao接口 */ public interface DeptDao { /** 有这么 多重复代码,肯定是不好的,我们应该使用一种范式提取出来。我们可以定义一个公共的BaseDao接口来 解决这种问题: * 查询所有的部门信息 * @return */ public List<Dept> listAll(); /** * 保存部门信息 * @param dept * @return */ public int save(Dept dept); /** * 删除部门信息 * @param dept * @return */ public int delete(Dept dept); /** * 修改部门信息 * @param dept * @return */ public int update(Dept dept); /** * 根据主键查询 部门的信息 * @param id * @return */ public Dept find(Long id); } package com.aaa.gen.common; import com.aaa.gen.entity.Dept; import java.util.List; public interface BaseDao<T> { /** * 查询所有的实体信息 * @return */ public List<T> listAll(); 然后针对某个特定多的接口比如EmpDao,我们可以让EmpDao继承BaseDao接口,同时指定泛型的类型: 帮助我们提前发现一些程序的错误 /** * 保存实体信息 * @param t * @return */ public int save(T t); /** * 删除实体信息 * @param t * @return */ public int delete(T t); /** * 修改实体信息 * @param t * @return */ public int update(T t); /** * 根据主键查询 实体的信息 * @param id * @return */ public T find(Long id); } package com.aaa.gen.dao; import com.aaa.gen.common.BaseDao; import com.aaa.gen.entity.Emp; import java.util.List; /** * 员工管理dao接口 */ public interface EmpDao extends BaseDao<Emp> { }
帮助我们提前发现一些程序的错误 package com.aaa.gen.test; import java.util.ArrayList; import java.util.List;定义泛型接口或者类 定义泛型接口 泛型接口在被实现的时候,如果实现类不再需要泛型,则需要指定泛型的具体类型: /** * 测试泛型 */ public class Test01 { /** * 打印list中所有的内容 */ public static void printList(List<String> list){ for(int i=0;i<list.size();i++){ String str = list.get(i); System.out.println(str); } } public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("Java"); list.add("C#"); list.add("python"); list.add(123); Test01.printList(list); } } package com.aaa.gen; /** * 定义泛型接口list * 在接口后面使用<>表示,在<>可以定义泛型的形参,一般形参都使用单独的一个大写字母来表示 * 多个发型的形参用逗号进行间隔 经常用的泛型的标识有T E * */ public interface List<T> { /** * 迭代元素 * @param t */ public void iterator(T t); }如果实现类继续使用泛型,则可以不指定泛型的具体类型: 定义泛型类 package com.aaa.gen; /** * 如果实现类中不再使用泛型,则需要指定泛型的具体类型 */ public class ArrayList implements List<String> { @Override public void iterator(String s) { } } package com.aaa.gen; /** * 实现类中如果继续使用泛型 ,则不必指定泛型的具体类型 * @param <T> */ public class LinkedList<T> implements List<T>{ @Override public void iterator(T t) { } } package com.aaa.gen; /** * 泛型类 */ public class Apple<T> { //声明泛型变量info private T info; public T getInfo() { return info; } public void setInfo(T info) { this.info = info; } }在使用的时候: 泛型通配符 需求:定义一个类,类中需要有打印一个字符串集合中的所有元素的方法,还需要有打印一个整数集合中的所有元 素的方法 package com.aaa.gen.test; import com.aaa.gen.Apple; /** * 测试泛型类 */ public class Test02 { public static void main(String[] args) { Apple<String> apple= new Apple<String>()apple.setInfo("红色"); System.out.println(apple.getInfo()); Apple<Integer> apple2= new Apple<Integer>(); apple2.setInfo(10); System.out.println(apple2.getInfo()); } } package com.aaa.gen.test; import java.util.List; public class Test03 { /** * 打印字符串集合中的所有的元素 * @param list */ public void printStr(List<String> list){ for(String str : list){ System.out.println(str); } } /** * 打印整数集合中的所有的元素 * @param list */ public void printInt(List<Integer> list){ for(Integer num :list){ System.out.println(num); } }我们发现所有打印的方法的代码结构上都是类似的,打印每种类型的变量的集合都需要再定义一个方法,这样做非 常麻烦,有没有一个通用的方法可以解决这个问题? 我们通过泛型通配符来解决这个问题,java提供一个方案,List 不是所有List<其他类型>的父类,但是List<?>可以 理解为所有List<其他类型>的父类: /** * 打印小数集合中的所有的元素 * @param list */ public void printDouble(List<Double> list){ for(Double num :list){ System.out.println(num); } } } package com.aaa.gen.test; import java.util.ArrayList; import java.util.List; /** * 使用List<Object>来代替List<String>List<Double> List<Integer> */ public class Test04 { /** * 打印所有的object对象 * @param list */ public void print(List<Object> list){ for(Object obj : list){ System.out.println(obj); } } public static void main(String[] args) { List<String> strList = new ArrayList<String>(); strList.add("java"); strList.add("c#"); //String 是Object的子类,但是List<String> 还是不是List<Object>的子类了?不是了 //我们还是希望List<Object>是List<String>或者是List<其他类型>的父类 new Test04().print(strList); } }泛型通配符上限 需求:声明一个方法,打印所有数字类型的集合中的元素 package com.aaa.gen.test; import java.util.ArrayList; import java.util.List; /** * 使用List<?>来代替List<Object> */ public class Test05 { /** * 打印所有的object对象 * @param list */ public static void print(List<?> list){ for(Object obj : list){ System.out.println(obj); } } public static void main(String[] args) { List<String> strList = new ArrayList<String>(); strList.add("java"); strList.add("c#"); //可以理解为List<?>是所有List<其他类型>的父类 new Test05().print(strList); List<Integer> intList = new ArrayList<Integer>(); intList.add(1); intList.add(2); //可以理解为List<?>是所有List<其他类型>的父类 new Test05().print(intList); } } package com.aaa.gen.test; import java.util.ArrayList; import java.util.List; /** * 泛型通配符上限 */ public class Test06 { /** * 打印所有的数字类型集合中的元泛型方法 原先在使用泛型的时候,只把泛型定义在了类上或者接口上。泛型也可以只在一个方法上来使用。 举例:声明一个泛型方法 合并两个list集合中的元素 * @param list */ public void printNum(List<? extends Number> list){ for(Number n : list){ System.out.println(n); } } public static void main(String[] args) { List<Integer> inStrs = new ArrayList<Integer>(); inStrs.add(1); inStrs.add(2); //同List<Object>不是List<其他类型>的父类一样,List<Number>也不是List<Number的子类>的父类 //如果要解决这种问题,就需要用到泛型通配符上限 new Test06().printNum(inStrs); List<Double> doStrs = new ArrayList<Double>(); doStrs.add(1D); doStrs.add(2D); new Test06().printNum(doStrs); List<String> strs = new ArrayList<String>(); strs.add("abc"); strs.add("def"); new Test06().printNum(strs); } } package com.aaa.gen.test; import java.util.ArrayList; import java.util.List; /** * 泛型方法 */ public class Test07 { /** * 合并两个list集合 * @param a * @param b */ /* public static void join(List<String> a , List<String> b){ for(String item :a){ b.add(item); } }*/问题,如果b中的泛型类型声明成Object会报错: public static <T> void join(List<T> a , List<T> b){ for(T item :a){ b.add(item); } System.out.println(b); } public static void main(String[] args) { List<String> a = new ArrayList<String>(); a.add("1"); a.add("2"); List<String> b = new ArrayList<String>(); b.add("3"); Test07.join(a,b); List<Integer> a1 = new ArrayList<Integer>(); a1.add(1); a1.add(2); List<Integer> b1 = new ArrayList<Integer>(); b1.add(3); Test07.join(a1,b1); } }怎么在不把Object改成String的前提下解决这种问题?泛型通配符下限 需求:要返回最后一个添加的元素 怎么样修改方法才能让返回值变成添加元素时的类型? package com.aaa.gen.test; import java.util.ArrayList; import java.util.List; /** * 泛型方法 发型通配符下限 */ public class Test08 { /** * 合并两个list集合 返回最后一个添加的元* @param a * @param b */ /* public static void join(List<String> a , List<String> b){ for(String item :a){ b.add(item); } }*/ public static <T> T join(List<? extends T> a , List<T> b){ T last = null; for(T item :a){ last = item; b.add(item); } System.out.println(b); return last; } public static void main(String[] args) { List<String> a = new ArrayList<String>(); a.add("1"); a.add("2"); a.add("3"); List<Object> b = new ArrayList<Object>()//返回值是什么类型,原先放置的时候类型是String类型,现在还能不能用String类型来接收返回值了? Object last = Test08.join(a,b); } } package com.aaa.gen.test;擦除 把一个具有泛型信息的变量赋值给一个没有泛型信息的变量,泛型的信息会消失,这就叫做擦除。 import java.util.ArrayList; import java.util.List; /** * 泛型方法 发型通配符下限 */ public class Test08 { /** * 合并两个list集合 返回最后一个添加的元* @param a * @param b */ /* public static void join(List<String> a , List<String> b){ for(String item :a){ b.add(item); } }*/ public static <T> T join(List<T> a , List<? super T> b){ T last = null; for(T item :a){ last = item; b.add(item); } System.out.println(b); return last; } public static void main(String[] args) { List<String> a = new ArrayList<String>(); a.add("1"); a.add("2"); a.add("3"); List<Object> b = new ArrayList<Object>()//返回值是什么类型,原先放置的时候类型是String类型,现在还能不能用String类型来接收返回值了? // Object last = Test08.join(a,b); //怎么样修改方法才能让返回值变成添加元素时的类型 String last = Test08.join(a,b); } } package com.aaa.gen; /** * 泛型类 */ public class Apple<T> {测试: //声明泛型变量info private T info; public T getInfo() { return info; } public void setInfo(T info) { this.info = info; } } package com.aaa.gen.test; import com.aaa.gen.Apple; /** * 擦除 */ public class Test09 { public static void main(String[] args) { Apple<String> a1 = new Apple<String>(); a1.setInfo("红色"); String info = a1.getInfo(); //把一个具有泛型信息的变量赋值给一个没有泛型信息的变量 Apple a2=a1; //泛型类型信息会消失 Object info1 = a2.getInfo(); } }