【Java基础面试题033】Java泛型的作用是什么?

Java的基础语法可以看尚硅谷的这个PDF:尚硅谷JavaSE基础/《Java从入门到精通(JDK17版)》_尚硅谷电子书.pdf · Autism_Btkrsr/Blog_md_to_pdf - 码云 - 开源中国 (gitee.com)

回答重点

Java泛型的作用是通过在编译时检查类型安全,允许程序员编写更通用和灵活的代码,避免在运行时发生类型转换错误。

总结作用

  • **类型安全:**泛型允许在编译时进行类型检查,确保在使用集合或其他泛型类时,不会出现类型不匹配的问题,减少了运行时的ClassCastException错误
  • **代码重用:**泛型使代码可以适用于多种不同的类型,减少代码重复,提升可读性和可维护性
  • **消除显式类型转换:**泛型允许在编译时指定类型参数,从而消除了运行时需要显式类型转换的麻烦
java 复制代码
List<String> list = new ArrayList<>();
list.add("Hello");
String str = list.get(0); // 不需要类型转换

扩展知识

泛型的实际应用

  • **集合框架:**Java的集合框架广泛使用了泛型。List<T>、Set<T>和Map<K, V>等接口可以针对不同的数据类型实现统一的操作

  • **泛型方法:**不仅可以定义泛型类,还可以定义泛型方法,使得方法能够处理多种不同的数据类型

  • 泛型方法

可以显式指定类型,不指定的话,Java编译器会自动推断类型

java 复制代码
public class GenericMethodTest {
    public static void main(String[] args) {
        Integer[] intArr = {1, 2, 3, 4, 5};
        Double[] doubleArr = {1.1, 2.2, 3.3, 4.4, 5.5};
        String[] stringArr = {"Hello", "World"};
        printArray(intArr);
        // 显式指定类型
        GenericMethodTest.<Integer>printArray(intArr);
        printArray(doubleArr);
        printArray(stringArr);
        // 多类型参数
        new GenericMethodTest().printMultiArgsArray(intArr, stringArr);
    }
    public static <T> void printArray(T[] arr){
        for (T element: arr){
            System.out.print(element);
        }
        System.out.println();
    }
    // 多类型参数
    public <T, V> void printMultiArgsArray(T[] keys, V[] values){
        for (int i = 0; i < Math.min(keys.length, values.length); i++){
            System.out.printf("{Key:%s,Value:%s}\n", keys[i], values[i]);
        }
    }
}

为什么需要泛型?

在Java5之前是没有泛型的,没泛型都能用的好好的,为什么非要加个泛型呢?能解决什么问题呢?

看这段代码

java 复制代码
  List list = new ArrayList();
  list.add("yes"); // 加入string
  list.add(233); // 加入int

在没有泛型的时候,加入的集合的数据并不会做任何约束,都会被当做成Object类型。

可能有人说:这很好呀,多自由!确实,自由是挺自由,但是代码的约束力越低,越容易从出错,使用上也有诸多不便。比如获取的时候老是要强转

就算强转过了编译器这一关,运行的时候还是会报错

综上,Java就引入了泛型。

所以泛型的作用就是加了一层约束,约束了类型。

有了这一层约束就好办事了,由于声明了类型,可以在编译时就识别不出准确的类型元素。使得错误提早抛出,避免运行时才发现。

小结一下泛型的好处:

  • 提高了代码的可读性,一眼就能看出集合的类型
  • 可在编译期检查类型的安全,增加程序的健壮性
  • 省心不需要强转(其实内部帮做了强转,下面会说)
  • 提高代码的复用率,定义好泛型,一个方法(类)就能适配所有类型(其实以前Object也行,就是比较麻烦)

为什么Java的泛型是伪泛型?

java 复制代码
public class GenericReflectionTest {
    public static void main(String[] args) throws Exception{
        List<String> list = new ArrayList<>();
        list.add("Hello");
        list.getClass().getMethod("add", Object.class).invoke(list, 123);
        System.out.println(list);
    }
}

可以看到,我声明的是一个String类型的集合,但是通过反射往集合中插入了int类型的数据,居然成功了?

这说明在运行的时候泛型根本没起作用 !也就是说在运行的时候JVM获取不到泛型的信息,也不会对其做任何约束

可以认为Java的泛型就是编译时失效,运行的时候就是没有泛型,所以大家才说Java是伪泛型!

因此,实际上在运行的时候泛型的类型是被擦除

总结:Java的泛型只在编译时生效,JVM运行时没有泛型

关于反射的博客,看我这一篇:【Java】反射_反射 博客园-CSDN博客

相关推荐
不懂哥2 分钟前
DefaultListableBeanFactory
java·spring
云之兕12 分钟前
Java内存模型详解:堆、栈、方法区
java·开发语言·jvm
flzjkl13 分钟前
【源码】【Java并发】【AQS】从ReentrantLock、Semaphore、CutDownLunch、CyclicBarrier看AQS源码
java·后端
@蓝莓果粒茶16 分钟前
LeetCode第131题_分割回文串
开发语言·前端·算法·leetcode·职场和发展·c#·.net
ChinaRainbowSea28 分钟前
7. RabbitMQ 消息队列——延时队列(Spring Boot + 安装message_exchange“延迟插件“ 的详细配置说明)的详细讲解
java·spring boot·docker·rabbitmq·java-rabbitmq
小吕学编程34 分钟前
Spring Boot + Kafka 消息队列从零到落地
java·spring boot·kafka
nlog3n40 分钟前
Java 代理模式 详解
java·开发语言·代理模式
lly2024061 小时前
抽象工厂模式
开发语言
一只小松许️1 小时前
Rust切片、结构体、枚举
开发语言·rust
Seven971 小时前
电商平台中订单未支付过期如何实现自动关单?
java