首页 > 编程语言 >Android面试题之Java 泛型和Kotlin泛型

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

时间:2024-06-16 14:57:43浏览次数:32  
标签:Plate 面试题 set Java Kotlin 类型 擦除 泛型

本文首发于公众号“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编译器具体是如何擦除泛型的

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

  • 擦除类型变量,并替换为限定类型。如果泛型类型的类型变量没有限定(<T>),则Object为原始类型;如果有限定(<T extends XClass>),则用XClass作为限定类型;如果有多个限定(T extends XClass1 & XClass2),则使用第一个边界XClass1作为原始类。

  • 在必要时插入类型转换以保持类型安全

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

Kotlin泛型

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


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

AntDream

标签:Plate,面试题,set,Java,Kotlin,类型,擦除,泛型
From: https://blog.csdn.net/myth13141314/article/details/139612676

相关文章

  • 2024hw蓝队面试题-3
    Linux有哪些提权思路常用的有以下几种:1.SUID提权:在Linux中,如果一个可执行文件的SUID被设置,那么该文件将以拥有者的权限运行,而不是以执行者的权限运行。因此,如果用户找到了一个SUID为root的文件并成功地使其执行了恶意代码,那么该用户将会获得root权限。2.利用系统漏洞:这是最......
  • 数据库面试题(持续更新中)
    1.oracle与mysql的区别1.对事务的提交   MySQL默认是自动提交,而Oracle默认不自动提交,需要用户手动提交,需要在写commit;指令或者点击commit按钮2.分页查询   MySQL是直接在SQL语句中写"select...from...where...limit x,y",有limit就可以实现分页;而Oracl......
  • [面试题]Spring MVC
    考虑到SpringMVC和Rest关系比较大,所以本文一共分成两大块:SpringMVCRESTSpringMVCSpringMVC框架有什么用?SpringWebMVC框架提供”模型-视图-控制器”(Model-View-Controller)架构和随时可用的组件,用于开发灵活且松散耦合的Web应用程序。MVC模式有助......
  • 前端面试题日常练-day71 【面试题】
    题目希望这些选择题能够帮助您进行前端面试的准备,答案在文末好的,以下是另外五个与Sass相关的选择题:Sass中,以下哪个符号用于声明一个变量?a)$b)@c)#d)&在Sass中,以下哪个符号用于引入其他Sass文件?a)@importb)$c)#d)&Sass中的混合器(Mixin)用于什么目的?a......
  • 前端面试题日常练-day69 【面试题】
    题目希望这些选择题能够帮助您进行前端面试的准备,答案在文末TypeScript中,以下哪个关键字用于声明一个变量的类型为联合类型?a)unionb)anyc)alld)|在TypeScript中,以下哪个符号用于声明一个变量的类型为对象类型?a){}b)[]c)()d)<>TypeScript中的枚举(Enum......
  • 最全Java面试题及答案整理(2024最新版)
    很多Java工程师的技术不错,但是一面试就头疼,10次面试9次都是被刷,过的那次还是去了家不知名的小公司。问题就在于:面试有技巧,而你不会把自己的能力表达给面试官。应届生:你该如何准备简历,面试项目和面试说辞?Spring底层逻辑是什么?1-3年经验的程序员:面试中你该讲哪些值钱......
  • C语言面试题
    1.static的作用1.修饰全局变量:不可以被外部文件访问,只可以在本文件中使用,限定它的作用域2.修饰函数:不可以被外部文件访问,只可以在本文件中使用,限定函数的作用域如果想要其他文件可以引用本地的函数,则要在函数定义时使用关键字,extern,表示该函数是外部函数可以被其他文件调......
  • IO、进程、线程面试题
    1.标准IO和文件IO的区别1.标准IO标准IO是基于缓存的IO,也就是说,在进行IO操作时,数据会先被读入缓存,然后再进行实际的IO操作。标准IO的优点是对于大文件的读写操作效率比较高,因为可以利用缓存来避免频繁的系统调用。此外,标准IO还提供了一系列方便的API函数,例如printf、scanf等......
  • 持续总结中!2024年面试必问 20 道并发编程面试题(七)
    上一篇地址:持续总结中!2024年面试必问20道并发编程面试题(六)-CSDN博客十三、请解释什么是生产者-消费者问题。生产者-消费者问题(Producer-ConsumerProblem)是计算机科学和操作系统中的一个经典同步问题。这个问题描述了两种不同的进程或线程:生产者(Producer)和消费者(Consumer),它......
  • 持续总结中!2024年面试必问 20 道并发编程面试题(八)
    上一篇地址:持续总结中!2024年面试必问20道并发编程面试题(七)-CSDN博客十五、请解释什么是阻塞队列(BlockingQueue)。阻塞队列(BlockingQueue)是一种特殊的队列,它是Java并发集合的一部分,用于在多线程环境中进行线程间通信。当生产者线程(Producer)尝试将元素放入队列时,如果队列已......