• Java - 泛型


    前言

              学习 Java 泛型 内容!

    一、为什么

    Java 泛型是 JDK 5 中引入的一个新特性,目的是用来弥补集合可以容纳各种类型数据导致的类型异常。
    集合中可以存放字符串、整型数据等各种数据,对于集合而言,都将其统一当作是 object 类型(Java 中所有类的父类是 Object)。类比,集合是一个大房子,各种数据类比为人、狗、猫等具体的,对于房子而言都将其统一看作是活物。
    存在问题:将所有类型数据都当作 object 类型存放,后续使用具体数据类型时需要强制类型转换,造成类型转换错误。

    List list = new ArrayList ();
    list.add("hello");
    list.add(6);
    
    for (object o : list) {
    	System.out.println((String) o);  // 发生错误:Integer 不能转换成 String 类型
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    二、泛型

    泛型是什么?

    定义泛型时可以类比成增加了一个安检功能,使用时如果使用泛型(安检功能),则会对不符合限制(特定数据类型)的进行过滤,也可以不适用泛型(安检功能),不使用就没有过滤功能(默认就是 Object 类型)。
    所谓的泛型就是参数化类型,即将要操作的类型作为一个参数。
    参数化类型是什么?字面拆解。参数化变成参数类型数据类型,例如,StringInterger参数化类型将类型当作参数。例如,将 String 直接变成参数。

    public class Main {
    	public static void main(String[] args) {
    		List list = new ArrayList();  // 不使用泛型
    		// <String>  泛型表达:将 String 类型变成集合 List 的参数
    		List<String> list1 = new ArrayList<>();  
    	}
    	// 该方法规定需要传入一个 String 类型的参数(具体的字符串)
    	public void Do(String s) {
    		System.out.println(s);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    泛型的作用:给集合加上特定的限制,只能存储特定的类型数据。

    类型参数

    对于方法,方法参数有形参和实参。对于泛型,参数化类型,就是将类型当作参数,类型参数就是 <> 内的东西。类型参数也分为类型实参和类型形参。

    1. 类型实参

      List<String> list1 = new ArrayList<>();
      
      • 1

      <> 内的 String 就是类型实参,即实际的类型参数,这里的类型参数就是各个数据类型。

    2. 类型形参

      public interface List<E> extends Collection<E> {
      	...
      }
      
      • 1
      • 2
      • 3

      对于泛型就是使用一些大写的英文字母来作为类型形参,这列的 E 就是类型形参,代表通用型。例如,E:在集合框架中使用,K V:含有映射关系使用(Map),N:用于数字,T S U V:通用类型。

    泛型使用

    对于泛型,如果是使用泛型用类型实参,如果是定义泛型接口或泛型类用类型形参。

    1. 定义泛型接口

    interface MyList<E> {  // E 作为类型形参
    	// 打印泛型实际类型实参的类型名称
    	void showTypeName(E e)
    }
    
    • 1
    • 2
    • 3
    • 4
    // 通过 MyListImp 类实现一个泛型接口
    public class MyListImp<E> implents MyList<E>{
    	public void showTypeName(E e) {
    		System.out.println(e.getClass().getName());
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    // 测试类
    public class Main {
    	public static void main(String[] args) {
    		MyList<String> myList = new MyListImp<>();
    		myList.showTypeName("hello");
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2. 定义泛型类

    // 定义
    // 给类增加泛型,相当于给类增加了过滤
    public class FxClass<G> {  // G 类型形参,定义时不能确定具体的类型,后面使用时传入类型实参确定 G 类型
    	private G g;
    	public G getG() {
    		return g;
    	}
    	public void setG(G g) {
    		this.g = g;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    // 使用泛型类:使用时会根据泛型定义对操作进行可一些过滤
    public class Main {
    	public static void main(String[] args) {
    		FxClass<String> fxClass = new FxClass<>();
    		fxClass.setG("自定义泛型类");
    		System.out.println(fxClass.getG());
    		Test test = new Test();
    	}
    
    // 泛型类的继承
    class Test extends FxClass<String> {  // 继承泛型类的时候要指定具体的类型实参
    	
    }
    
    // 原始类型
    class Test extends FxClass {  // 不写类型实参被称为原始类型等价于 class Test extends FxClass<object>
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    泛型类是不存在的,泛型类并不是一个新的种类

    List list = new ArrayList();  // 没有使用泛型
    List<String> stringlist = new ArrayList<>();  // 使用了泛型:没有生成新的 List 本质上还是上一个 List,只不过泛型做了规定只能装载特定的数据
    
    • 1
    • 2

    使用通配符

    public void doS(List<?> list) {
    }
    
    • 1
    • 2

    3. 泛型方法

    修饰符 <T,E, … 形参> 返回值类型 方法名称 (形参列表) {
                  方法体,具体的逻辑实现
    }

    public class Test {
    	public static void main(String[] args) {
    	// 普通方法
    	public void doS(String s) {
    		System.out.println(s.getClass().getName());
    	}
    
    	// 泛型方法
    	public <T> void doSS(T t) {  // <T> T 形参
    		System.out.println(T.getClass().getName());
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    泛型擦除

  • 相关阅读:
    每天一个注解之@Async
    C++——类和对象(上)
    Linux系统访问卡顿 慢
    webpack与vue-cli的关系
    希尔排序超详细讲解C语言
    PandoraBox版本及已安装软件包
    requests模块get方法使用
    强大而灵活的python装饰器
    java-net-php-python-jspm餐饮管理系统演示录像2019计算机毕业设计程序
    Docker 基本使用
  • 原文地址:https://blog.csdn.net/weixin_39903708/article/details/125616316