Android面试题之Java 泛型和Kotlin泛型

简介: **Java泛型是JDK5引入的特性,用于编译时类型检查和安全。泛型擦除会在运行时移除类型参数,用Object或边界类型替换。这导致几个限制:不能直接创建泛型实例,不能使用instanceof,泛型数组与协变冲突,以及在静态上下文中的限制。通配符如<?>用于增强灵活性,<? extends T>只读,<? super T>只写。面试题涉及泛型原理和擦除机制。

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点

定义:JDK5引入的一种参数化类型特性

继承和实现接口可以多个
static class A{
   }
static interface B{
   }
static interface C{
   }

//类必须在接口的前面
static class D<T extends A & B & C>{
   }
泛型原理

泛型擦除:

  • 做类型检查,T如果有做类型限制,会转化为第1种限制,否则会擦除为object
  • 生成桥方法,里面调用对应的接口方法,调用的时候会进行类型的强转,转为T的限制类型
  • 泛型擦除后,字节码中没有泛型信息了,但是类的常量池里保留了泛型信息。反射的时候提供了一套API可以拿到,比如getGenericType()
泛型带来的问题
  1. 泛型类型变量不能使用基本类型
比如没有ArrayList<int>,只有ArrayList<Integer>,
当泛型擦除后,ArrayList的原始类中的类型变量T替换成了Object,但Object不能存放基本数据类型
  1. 不能使用instanceof运算符
因为泛型擦除后,ArrayList<String>只剩下原始类型,泛型信息String不存在了
  1. 泛型在静态方法和静态类中的问题

    因为泛型类中的泛型参数的实例化是在定义泛型类型对象时候指定的,而静态成员是不需要使用对象来调用的,所有对象都没创建,无法确定泛型参数;

    静态方法中是可以的,因为调用的时候可以确定参数中的泛型类型

  2. 泛型类型中的方法冲突

    因为擦除后2个equales方法变成一样的了,参数都会变成object

@Override
public boolean equals(Object o) {
   
    super.equals(o);
}
@Override
public boolean equals(T o) {
   
    super.equals(o);
}
  1. 没法创建泛型实例,因为类型不确定
public static <E> void append(List<E> list){
   
    //编译会报错
    E element = new E();
    list.add(element);
}
不过可以通过反射来创建
 public static <E> void append(List<E> list, Class<E> cls) throws Exception {
   
    E element = cls.newInstance();
    list.add(element);
}
  1. 没有泛型数组,因为数组遵循协变原则
协变:Apple extend Fruit,Apple[] 的父类是Fruit[]
泛型,继承和子类
  • 给定两种具体的类型 A和B,无论A和B是否相关,MyClass和MyClass都没有半毛钱关系;
比如Apple继承自Fruit,那Plate<Fruit>和Plate<Apple>也没有任何关系;
也就是说苹果是水果,但装苹果的盘子不是装水果的盘子
  • 继承关系中,泛型可以有多个,但如果有一个泛型参数是一样的,继承关系就存在的,不会因为有的类多个个泛型参数,继承关系就不在了
比如Plate<Apple> <--AIPlate<Apple> <--BIgPlate<Apple> <-- ColorPlate<String, Apple>
泛型和通配符

通配符让泛型转型更灵活

  • Plate<?> 非限定通配符,是一个泛型类型 ?表示未知,等价于 Plate<? extends Object>;副作用是既不能读也不能写;可以促使进行安全检查

  • List和List<?>,前者不会进行安全检查,后者会进行类型的安全检查

限定通配符

  • Plate<? extends T> 限定上届,能读不能写,类似于生产者
  • Plate<? super T> 限定下届,能写不能读,类似于消费者
通配符总结
  • 如果只需要从集合中获得类型T,使用<? extends T>;

  • 如果只需要将类型T放到集合中,使用<? super T>;

  • 既要获取又要放置元素,则不使用通配符

用<? extends Fruit>的后遗症

<? extends Fruit>是上届通配符,相当于“只读”

Plate<? extends Fruit> fruitPlate = plate(Plate<Apple> 类型)
//下面会报错,因为具体类型丢失了,只能是Fruit
fruitPlate.set(new Apple())

解决方案:可以用反射来set,但是安全性降低

Method set = friutPlate.getClass().getMethod("set", Object.class);
set.invoke(fruitPlate, new Banana())
//什么都能set,安全性降低
set.invoke(fruitPlate, new Beef())

面试题

1、Java泛型原理?什么是泛型擦除机制?

Java泛型是JDK5新引入的特性,为了向下兼容,虚拟机其实不支持泛型,所以Java实现的是伪泛型机制,也就是说Java在编译期擦除了所有的泛型信息,这样Java就不需要产生新的类型到字节码,所有的泛型类型最终都是一种原始类型,在Java运行时根本就不存在泛型信息

2、Java编译器具体是如何擦除泛型的

  • 检查泛型类型,获取目标类型

  • 擦除类型变量,并替换为限定类型。如果泛型类型的类型变量没有限定(\),则Object为原始类型;

 如果有限定(\<T extends XClass>),则用XClass作为限定类型;
 如果有多个限定(T extends XClass1 & XClass2),则使用第一个边界XClass1作为原始类。
  • 在必要时插入类型转换以保持类型安全

  • 生成桥方法以在扩展时保持多态性

Kotlin泛型

Kotlin的泛型可以看文章:Android面试题之Kotlin泛型和reified关键字


欢迎关注我的公众号AntDream查看更多精彩文章!

目录
相关文章
|
10月前
|
缓存 Java 关系型数据库
2025 年最新华为 Java 面试题及答案,全方位打造面试宝典
Java面试高频考点与实践指南(150字摘要) 本文系统梳理了Java面试核心考点,包括Java基础(数据类型、面向对象特性、常用类使用)、并发编程(线程机制、锁原理、并发容器)、JVM(内存模型、GC算法、类加载机制)、Spring框架(IoC/AOP、Bean生命周期、事务管理)、数据库(MySQL引擎、事务隔离、索引优化)及分布式(CAP理论、ID生成、Redis缓存)。同时提供华为级实战代码,涵盖Spring Cloud Alibaba微服务、Sentinel限流、Seata分布式事务,以及完整的D
549 3
|
10月前
|
存储 安全 Java
常见 JAVA 集合面试题整理 自用版持续更新
这是一份详尽的Java集合面试题总结,涵盖ArrayList与LinkedList、HashMap与HashTable、HashSet与TreeSet的区别,以及ConcurrentHashMap的实现原理。内容从底层数据结构、性能特点到应用场景逐一剖析,并提供代码示例便于理解。此外,还介绍了如何遍历HashMap和HashTable。无论是初学者还是进阶开发者,都能从中受益。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
414 3
|
7月前
|
算法 Java
50道java集合面试题
50道 java 集合面试题
|
9月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
624 0
|
9月前
|
Java 数据库连接 数据库
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
本文全面总结了Java核心知识点,涵盖基础语法、面向对象、集合框架、并发编程、网络编程及主流框架如Spring生态、MyBatis等,结合JVM原理与性能优化技巧,并通过一个学生信息管理系统的实战案例,帮助你快速掌握Java开发技能,适合Java学习与面试准备。
423 2
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
|
10月前
|
存储 安全 Java
2025 最新史上最全 Java 面试题独家整理带详细答案及解析
本文从Java基础、面向对象、多线程与并发等方面详细解析常见面试题及答案,并结合实际应用帮助理解。内容涵盖基本数据类型、自动装箱拆箱、String类区别,面向对象三大特性(封装、继承、多态),线程创建与安全问题解决方法,以及集合框架如ArrayList与LinkedList的对比和HashMap工作原理。适合准备面试或深入学习Java的开发者参考。附代码获取链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
5744 50
|
7月前
|
算法 Java
50道java基础面试题
50道java基础面试题
|
10月前
|
算法 架构师 Java
Java 开发岗及 java 架构师百度校招历年经典面试题汇总
以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。
280 5
|
10月前
|
Java API 微服务
2025 年 Java 校招面试全攻略:从面试心得看 Java 岗位求职技巧
《2025年Java校招最新技术要点与实操指南》 本文梳理了2025年Java校招的核心技术栈,并提供了可直接运行的代码实例。重点技术包括: Java 17+新特性(Record类、Sealed类等) Spring Boot 3+WebFlux响应式编程 微服务架构与Spring Cloud组件 Docker容器化部署 Redis缓存集成 OpenAI API调用 通过实际代码演示了如何应用这些技术,如Java 17的Record类简化POJO、WebFlux构建响应式API、Docker容器化部署。
535 5