您的位置 首页 java

Java泛型面试题26道,一线互联网面试真题,最全最新整理

在一线互联网公司的 Java 面试中,这 26 道 Java 泛型 面试真题经常都会被问到,你都能应对如流么?

如果不能,本篇文章就一定要收藏、并时常温习,万一面试时被问到,答不上来了,因此错过好 offer 就太可惜了。

Java泛型面试题26道,一线互联网面试真题,最全最新整理

泛型学习资料:《泛型最全知识导图》、《大厂泛型面试真题26道》,到本篇结尾处获得~

1 Java 中的泛型是什么,以及泛型的作用有哪些?

  • Java 泛型 是 JDK 5 中引入的一个新特性;
  • 可以增强代码的可读性以及稳定性。编译器可以对泛型参数进行检测,并且通过泛型参数可以指定传入的对象类型。例如:ArrayList<Persion> persons = new ArrayList<String>() ,这行代码就指明了该 ArrayList 对象只能传入 Persion 对象,如果传入其他类型的对象,就会报出错误;
  • 可以用于构建泛型集合。原生 List 返回类型是 Object ,需要手动转换类型才能使用,使用泛型后编译器自动转换。

2 Java 泛型的特性与优缺点?

泛型的特性

Java 中的泛型,只在编译时有效。

  • 在编译时,正确检验泛型结果后,将泛型的相关信息擦出,在对象进入和离开方法的边界处,添加类型检查和类型转换的方法。
  • 在编译后,程序会采取去泛型化的措施,即泛型信息不会进入到运行时阶段。

泛型的优点

  • 代码可复用: 一套代码可支持不同的类型;
  • 可读性更高 :不用强制转换,代码更加简洁;
  • 程序更安全 :在编译时就检查类型安全,如在编译时没有警告,运行时就不会出现 ClassCastException (类型转换异常),降低 crash 率;
  • 稳定性强 :在创建集合时,就限定了集合元素的类型。因此,在取出元素时,不需要强制类型装换了。

没有泛型前, 我们是通过对类型 Object 的引用,来实现参数的“任意化”的。这样操作的缺点是要做显式的强制类型转换,要求开发者对实际参数类型、在可以预知的情况下进行。 引入泛型后, 我们就不用把参数的类型写死在代码,而是在使用时,再确定具体的类型。在调用方法时,也不用强转对象、写很多重复方法了。

PS. 为了可以和 Java 5 之前的 二进制 类库进行兼容,泛型在编译之后,会执行 类型擦除。

3 为什么说 Java 泛型是伪泛型?

我们说 Java 的泛型是伪泛型,是因为 Java 的泛型只在编译期起作用,就是在我们写代码时,起到一个检查的作用,运行期的泛型类型,被擦除了。

因此,在运行期,ArrayList<String> 和 ArrayList<int> 是相同的类型。

要证明是伪泛型,非常简单。看下面代码:

 List<Integer> li = new ArrayList<Integer>();
List<Float> lf = new ArrayList<Float>();
 boolean  issame = li.getClass() == lf.getClass();
System.out.println(issame);//true  

伪泛型会导致一些陷阱:

 public  static   void  main( string [] args) throws  Exception  {
 
        List list = new ArrayList();
        list.add("hello");
        list.add("world");
 
        List<Integer> intlist = list;
 
        for (int i = 0; i < intlist.size(); i++) {
            System.out.println(intlist.get(i)*100);
        }
    }  

上述代码编译通过,但是运行时 intlist.get(i)*100 会报错,很明显 intlist 中的元素是无法进行乘法运算的,导致报错。

 public static void main(String[] args) throws Exception {
 
        // string集合的集合
        List<ArrayList<String>> array_string_list = new ArrayList<ArrayList<String>>();
 
        // 原始的集合 指向 string集合的集合
        List arry = array_ String _list;
 
        ArrayList<String> lst_string = new ArrayList<String>();
        lst_string.add("abcde");
        // 原始集合可以不受限制的賦值任何集合,甚至是任何对象,反正最终都是变成Object对象
        arry.add(lst_string);
 
        
        ArrayList<Integer> lst_int = new ArrayList<Integer>();
        lst_int.add(10);
        // 原始集合可以不受限制的賦值任何集合
        arry.add(lst_int);
 
        // arry即array_string_list,有2个元素,第一个元素是string的泛型集合,第二个元素是int的泛型集合。
        // 形成混乱,导致运行出错
        System.out.print(array_string_list.size());// 2个元素
        System.out.print(array_string_list.get(1).get(0));//运行时遇到转型错误。
    }  

同理,上面的代码在最后一行也会导致运行出错。所以编程的时候,要注意伪泛型的陷阱。

4 Java 泛型底层原理是什么?是如何工作的 ?

Java泛型的实现原理是类型擦除。

之所以泛型的代码和之前版本的代码能够很好地兼容,是因为 泛型信息只存在于代码编译时,在进入 JVM 之前,与泛型相关的信息就会被擦掉,专业术语叫做类型擦除

例如:List<String> 在运行时,仅用一个 List 来表示,是为了确保和 Java 5之前的版本开发二进制类库兼容。

我们无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。

5 为什么要使用泛型?

相比杂乱的使用 Object 变量、再进行强制类型转换的代码,使用泛型机制编写的代码,既可以被很多不同类型的对象所重用,还具有更好的安全性和可读性。

6 从 ArrayList 的角度,说说为什么要使用泛型?

在 Java 增加泛型机制之前,就已经有一个 ArrayList 类,这个 ArrayList 类的泛型概念是使用 继承 来实现的。

 public class ArrayList {
     private  Object[] elementData;
    public Object get(int i) {....}
    public void add(Object o) {....}
}  

这个类有两个问题:

  • 问题1:当获取一个值的时候,必须进行强制类型转换;
  • 问题2:没有错误检查,可以向数组中添加任何类的对象。
 ArrayList  File s = new ArrayList();
files.add(new File(""));
String filename = (String)files.get(0);  

对于这个调用,编译和运行都不会出错。

但是,在其它地方使用 get 方法,获取刚刚存入的这个 File 对象强转为 String 类型时,就会产生错误。

泛型对于这种问题的解决方案是提供一个 类型参数

 ArrayList<String> files = new ArrayList<>();  

这样能让代码的可读性更好,我们很容易就能看出这个数据列表中包含的是String对象。 编译器也可以很好地利用这个信息,当我们调用get 时,不用再使用强制类型转换,编译器就知道返回值类型为 String ,而不是 Object :

 String filename = files.get(0);  

编译器还知道 ArrayList<String> 的 add 方法中有一个类型为String的参数,,并且可以检查,避免插入错误类型的对象,相比使用 Object 类型的参数更加安全:

 files.add(new File(""));  

这样的代码是无法通过编译的,出现编译错误,相比类在运行时出现类的强制类型转换异常,要好得多。

7 Java 泛型有哪些限制,在哪些情况下无法使用?

泛型的限制一般是由泛型擦除机制导致的,擦除为 Object 后,就无法进行类型判断了。

泛型的限制:

  • 只能声明,不能实例化 T 类型变量;
  • 泛型参数不能是基本类型。因为基本类型不是 Object 子类,应该用基本类型对应的引用类型代替;
  • 不能实例化泛型参数的数组,擦除后为 Object 后无法进行类型判断;
  • 不能实例化泛型数组;
  • 泛型无法使用 Instance of 和 getClass() 进行类型判断;
  • 可以声明,但不能抛出和捕获 T 类型的异常;
  • 不能实现两个不同泛型参数的同一接口,擦除后多个父类的桥方法将冲突;
  • 不能使用static修饰泛型变量。

8 说说你对 typescript 中泛型的理解?应用场景?

TypeScript 的基本概念

  • 是由 Microsoft Corporation 开发和维护的面向对象的编程语言;
  • 是 JavaScript 的超集,包含所有元素;
  • 遵循OOPS概念,在TSC(TypeScript编译器)的帮助下,我们可以将 Type script代码(.ts文件)转换为JavaScript(.js文件)。

TypeScript 中泛型的应用场景

我们在编写 typescript 的时候,定义函数、接口或类的时候,不预先定义好具体的类型,而是在使用时再指定类型的一种特性的时候,这种情况下就可以使用泛型。

9 说说泛型的使用方式有哪些?

泛型一般有 三种使用方式

  • 泛型类 :是最常见的泛型使用方式,即泛型直接用在实体类上,声明类的同时声明泛型类型;
  • 泛型接口 :即泛型用在接口 interface 上,实现泛型的类,必须传入泛型实参,然后在实现类中用该实参替换 T ;
  • 泛型方法 :在方法声明时,同时声明泛型。 在方法的返回值, 参数列表以及方法体中都可以使用泛型类型。

10 Java 泛型中的 T,E,K,V 是什么,说说它们的含义?

本质上 都是 通配符 ,只是一种 编码约定俗成。

我们可以将 T 换成 A-Z 之间的任意字母,不会影响程序的正常运行。但是,如果换成其他的字母代替 T , 可读性可能会差一些。

通常情况下,T,E,K,V,?是这样约定的:

T (type)

Type 类,表示具体的一个 Java 类型

K (key)

代表 Java 键值中的 Key

V (value)

代表 Java 键值中的 Value

E (element)

代表 Element ,特性是一种枚举

在使用中表示不确定类型

11 泛型的通配符是什么,有哪些使用场景?

泛型通配符的概念:

  • 泛型通配符用 ? 表示,代表不确定的类型,是泛型的一个重要组成。
  • 它的引入,是为了解决类型被限制死之后,不能动态根据实例来确定的缺点。

泛型通配符的使用场景:

  • 用于类型参数中;
  • 用于实例变量,或者局部变量中;
  • 有时也可作为返回类型,例如Object的getClass方法。

PS.

泛型通配符只能用于泛型类的使用(声明变量、方法的参数),不能用于泛型定义、New 泛型实例。

12 泛型通配符有什么作用?

通配符是用来解决泛型无法协变的问题,一般用于声明方法 形参

  • 泛型本身不支持协变和逆变,通配符可以解决该问题。 在 Java 中,数组可以协变。例如:Dog extends Animal , Animal[] 与 Dog[] 是可以兼容的;集合不可以协变,List<Animal> 不是 List<Dog> 的父类,为了建立两个集合之间的联系,此时需要引用通配符来解决。
  • 泛型 T 是确定的类型,通配符更为灵活(不确定),更多用于扩充参数的范围;
  • 泛型 T 就像是变量,将传来的一个具体的类型拿来使用,而通配符则是一种规定,规定你能传哪些参数,就像是一个特殊的实际类型参数。

13 什么是泛型中的限定通配符和非限定通配符 ?

限定通配符

  • <? extends T>,它通过确保类型必须是 T 的子类,来设定类型的上界;
  • <? super T>,它通过确保类型必须是 T 的父类,来设定类型的下界。

泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。

非限定通配符

非限定通配符的格式为 <?>,可以用任意类型来替代。

14 上界通配符<? extends T> 和 下界通配符 List <? super T> 有什么区别 ?

相同点:

这两 个List 的声明,都是限定通配符的例子。

不同点:

  • List<? extends T> 可以接受任何继承自 T 的类型的 List ;
  • List<? super T> 可以接受任何 T 的父类构成的 List 。例如:List<? extends Number> 可以接受List<Integer>、或 List<Float> 。

第15题-26题

Java泛型面试题26道,一线互联网面试真题,最全最新整理

泛型面试真题第15-26道

全部泛型26道题目及答案,全部内容有10000多字。篇幅太长,打开就很慢,因此没有全部展示。

我已经整理了完整的文档。

Java泛型面试题26道,一线互联网面试真题,最全最新整理

《26道泛型面试题及答案》文档

以上,结合《泛型知识全景导图》 一起学习复习,帮助构建泛型知识体系、快速掌握泛型核心知识。

Java泛型面试题26道,一线互联网面试真题,最全最新整理

泛型知识全景导图

Java泛型面试题26道,一线互联网面试真题,最全最新整理

如果觉得有帮助,请顺手 点赞 支持下,谢谢。

我是大全哥,持续更新成体系的Java核心技术。 知识成体系 学习才高效 ,我们下期见~

end

文章来源:智云一二三科技

文章标题:Java泛型面试题26道,一线互联网面试真题,最全最新整理

文章地址:https://www.zhihuclub.com/187150.shtml

关于作者: 智云科技

热门文章

网站地图