【J0007期】Java面试题库:泛型

9 篇文章 1 订阅
9 篇文章 0 订阅

Q1:

什么是泛型?

Java泛型( generics)是JDK 5中引⼊的⼀个新特性, 允许在定义类和接口的时候使⽤类型参数( type parameter) 。

声明的类型参数在使⽤时⽤具体的类型来替换。泛型最主要的应⽤是在JDK 5中的新集合类框架中。

 

泛型最⼤的好处是可以提⾼代码的复⽤性。以List接口为例,我们可以将String、 Integer等类型放⼊List中, 如不⽤泛型, 存放String类型要写⼀个List接口, 存放Integer要写另外⼀个List接口, 泛型可以很好的解决这个问题。

Q2:

编写一个泛型方法,让它能接受泛型参数并返回泛型类型 ?

1    public V put(K key, V value) {
2        return cache.put(key, value);
3    }

Q3:

什么是类型擦除?

通过类型参数合并,将泛型类型实例关联到同一份字节码上。

编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上。

泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如 List在运行时仅用一个List来表示。这样做的目的,是确保能和Java 5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。

 

类型擦除的主要过程如下:

1.将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。

2.移除所有的类型参数。

 

Q4:

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

限定通配符:

对类型进行了限制。有两种限定通配符:

一种是 它通过确保类型必须是T的子类来设定类型的上界,

另一种是它通过确保类型必须是T的父类来设定类型的下界。

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

 

非限定通配符:

表示了非限定通配符,因为可以用任意类型来替代。

 

Q5:

泛型中K T V E ?object等的含义 ?

E - Element (在集合中使用,因为集合中存放的是元素)

T - Type(Java 类)

K - Key(键)

V - Value(值)

N - Number(数值类型)

?- 表示不确定的java类型(无限制通配符类型)

Object - 是所有类的根类,任何类的对象都可以设置给该Object引用变量,使用的时候可能需要类型强制转换,但是用使用了泛型T、E等这些标识符后,在实际用之前类型就已经确定了,不需要再进行类型强制转换。

 

Q6:

List、List<Object>、List<?>的区别?

public class ListWithoutGeneric {
    public static void main(String[] args) {
        // 第一段:不使用泛型的方式
        List a1 = new ArrayList();
        a1.add(new Object());
        a1.add(new Integer(1));
        a1.add(new String("a1"));
 
        // 第二段:把a1赋值给List<Object>类型的a2,看似a2与a1没有区别
        List<Object> a2 = a1;
        a2.add(new Object());
        a2.add(new Integer(2));
        a2.add(new String("a2"));
        // 但是如果尝试把一个带有其它类型泛型的b2赋值给a2,则会编译报错
        List<String> b2 = new ArrayList<>();
        // 编译报错,这也是List与List<Object>的区别
        a2 = b2;
 
        // 第三段:把a1赋值给List<Integer>类型的a3,赋值过程没有编译报错,主要为了向前兼容(泛型jdk1.5之后才出现)
        List<Integer> a3 = a1;
        a3.add(new Integer(3));
        // java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.Integer
        Integer integer = a3.get(0);
        // 编译报错,不允许add非Integer类型
        a3.add(new Object());
        a3.add(new String("a3"));
 
        // 第四段:把a1赋值给List<?>类型的a4
        List<?> a4 = a1;
        a4.remove(0);
        a4.clear();
        a4.add(null);
        // 编译出错,不允许add非null的数据
        a4.add(new Object());
    }
}

1、第一段:定义了一个没使用泛型的List a1,向a1中添加不同类型的元素,所有功能都可以正常使用,但使用时会有类型强制转换异常的风险。

2、第二段:把a1赋值给List<Object>类型的a2,再往a2添加不同类型元素,不会编译报错,看似a2与a1没有区别,但是如果尝试把一个带有其它类型泛型(List<String>)的b2赋值给a2,则会编译报错,除非让泛型保持一致。

这也是List与List<Object>的区别:泛型之间只有同类型才能相互赋值。

3、第三段:把a1赋值给List<Integer>类型的a3,赋值过程没有编译报错,主要为了向前兼容(泛型jdk1.5之后才出现),但如果直接用Integer类型取值,会报类型转换异常。因为a3有了泛型约束,再添加其它类型元素,则会编译报错。

4、List<?>是通配符集合,一般作为参数来接收外部的集合,或者返回一个不知道具体元素类型的集合。它可以被任何类型的集合引用赋值,也可以删除元素。但是因为类型的不确定,所有不能添加非null元素(null属于任何类型)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值