泛型的介绍与原理

泛型的介绍与原理

一、什么是泛型

泛型的本质是参数化类型,意思就是所要使用的参数的类型也是个参数,是未确定的,可以是任意的类型(不能是基本数据类型

二、泛型的意义

  1. 安全性:在编译期间就能确定类型,不用担心ClassCastException异常
  2. 复用性:合并了同类型的处理代码的重用率
  3. 效率提高:不用再因为Object强转的装箱和开箱
  4. 提升可读性:从编码阶段就显式地知道泛型集合、泛型方法处理的类型是什么

三、使用泛型的三种方式

3.1、泛型类

格式:修饰符 + class + 类名 + <?>()

例如:public class Student ()

参数类型有规范,通常用大写字母表示

  • E - Element(在集合中使用)
  • T - Type(java类)
  • K - Key(键)
  • V - Value(值)
  • N - Number(数值类型)
  • ?- 表示不确定的java类型
package com.cjian.generic;
 
/**
 * @Author: cjian
 * @Date: 2023/5/30 10:33
 * @Des:
 */
public class GenericClass <T> {
    private T type;
 
    public T getType() {
        return type;
    }
 
    public void setType(T type) {
        this.type = type;
    }
 
    public GenericClass(T type) {
        this.type = type;
    }
 
    public static void main(String[] args) {
        GenericClass<String> g1 = new GenericClass<>("string");
        System.out.println(g1.getType());
        GenericClass<Integer> g2 = new GenericClass<>(1);
        System.out.println(g2.getType());
    }
}

3.2、泛型接口

与泛型类类似

package com.cjian.generic;
 
/**
 * @Author: cjian
 * @Date: 2023/5/30 10:39
 * @Des:
 */
public interface GenericInterface<T> {
    void run(T value);
}
 
class StringImpl implements GenericInterface<String> {
 
    @Override
    public void run(String value) {
        System.out.println(value);
    }
}
 
class IntegerImpl implements GenericInterface<Integer> {
 
    @Override
    public void run(Integer value) {
        System.out.println(value);
    }
}


3.3、泛型方法

格式:修饰符 + <?> + 返回值类型 + 方法名()

例子:public void show (T t)

方案一:使用类名后面定义的泛型(所有方法都能用)

方案二:在方法申明上定义自己的泛型(只有本方法能用)

package com.cjian.generic;
 
import java.util.ArrayList;
 
/**
 * @Author: cjian
 * @Date: 2023/5/30 9:51
 * @Des: 使用泛型打印不同类型的数组
 */
public class Demo {
    public static void main(String[] args) {
        String[] strings = {"a", "b", "c"};
        Integer[] integers = {1, 2, 3};
        Double[] doubles = {1.1, 2.2, 3.3};
 
        printArr(strings);
        printArr(integers);
        printArr(doubles);
        test1();
    }
 
    public static <E> void printArr(E[] arr) {
        for (E e : arr) {
            System.out.printf("%s ", e);
        }
        System.out.println();
    }
 
    public static void test1() {
        ArrayList<Integer> arr = new ArrayList<>();
        arr.add(1);
        int o1 = arr.get(0);
    }
}

小细节:E…e代表可变参数,可传任意个数参数

四、泛型通配符

//表示类型参数可以是任何类型
public class GenericClass<?>{}
 
//表示类型参数必须是A或者是A的子类
public class GenericClass<T extends A>{}
 
//表示类型参数必须是A或者是A的超类型
public class GenericClass<T supers A>{}

五、类型擦除(重点)

5.1、什么是类型擦除

大家都知道java泛型是伪泛型,这是因为在java编译期间,所有泛型信息都会被擦掉。泛型基本上都是在编译器这个层次上实现的,在生成的字节码文件中是不包含泛型的基本信息的,使用泛型的时候加上类型参数,在编译器编译的时候会去掉,这就是类型擦除

一句话概括:在编译期完成类型检查后,把某个具体的泛型引用擦除成了Object而丢失了它运行时所赋予的类型信息

5.2、为什么要类型擦除

java5才引入了泛型,在此之前都是没有的,引入的目的是为了解决遍历集合的时候总要手动强转类型

List cats = loadCats();  // 5之前没有范型哦

for (Object obj : cats) {
  Cat cat = (Cat) obj;  // 所以这里总是需要强转
  cat.meow();
}

为了让JVM向下兼容,就给出了类型擦除的下下策

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值