泛型就是参数化类型
泛型的作用
减少重复代码
像 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();
- }
- }
什么是泛型
来源: http://www.bubuko.com/infodetail-3089473.html