深入理解Java泛型的用法 征服Java面试

Java泛型

相信看到这篇文章的人都是来为面试做准备的,这篇文章就带你彻底征服面试官对Java泛型的考察。
我们首先带着几个问题去了解。

一.泛型是什么,你为什么要使用泛型

1.泛型是java中的一种形式参数,可以理解为Java的一个语法。
2.好处:
1).使用泛型能增加我们代码的可重用性。
2).泛型能帮我们把一些错误提前在编译期。例如ClassCastException,在编译期间就会提示你类型转换错误。
解释:
为什么说泛型能帮我们把错误提前在编译期呢?比如我们在某个类中用参数的类型Object替代泛型,那你在使用的时候就需要把
Object类型强转为我们赋值的类型。这样就很有可能在运行时发生ClassCastException,如果我们使用泛型,那么在编译的时候
能直接使用你指定的类型。而不需要强转。

**

二.Java泛型的原理?什么是泛型擦除机制?

**
Q:Java编译器具体是如何擦除泛型的
A:Java泛型是JDK1.5引入进来的特性,为了向下兼容,虚拟机本身是不支持泛型的,所以Java实现的是一种伪泛型机制,也就是说Java在编译期擦除了所有的泛型信息,这样Java就不需要产生新的类型到字节码,所有的泛型类型最终都是一种原始类型,在Java运行时根本就不存在泛型信息。
Q:Java编译器具体是如何擦除泛型的
A:1.检查泛型边界,获取目标类型
2. 擦除类型变量,并替换为限定类型,如果泛型类型的类型变量没有限定(),则 用Object作为原始类型,如果有限定(),则用XClass作为原始类型, 如果有多个限定(T extends XClass1&XClass2),则使用第一个边界XClass1作为原始类。
3. 在必要时插入类型转换以保持类型安全。
4. 生成桥方法以在扩展时保持多态性。

三. 使用泛型以及泛型擦除带来的影响(副作用)

Q: 1. 不能使用instanceof 运算符
A: 因为擦除后,ArrayList只剩下原始类型,泛型信息String不存在了,所有没 法使用instanceof。
Q: 2. 泛型在静态方法和静态类中的问题
A: 因为泛型类中的泛型参数的实例化是在定义泛型类型对象
(比如ArrayList)的时候指定的,而静态成员是不需要使用。
对象来调用的,所有对象都没创建,如何确定这个泛型参数是什么。
Q: 3. 泛型类型中的方法冲突
A: 因为擦除后两个equals方法变成一样的了。
Q: 4. 没法创建泛型实例
A: 因为类型不确定
Q: 5 没有泛型数组
A: 因为数组是协变,擦除后就没法满足数组协变的原则

四.Pecs原则 限定原则

什么叫Pecs原则
1.Producer Extend 代码表示为 List<? extend T>
那它代表什么意思呢,它表示限定上届为T,该List里面装的都是T的子类。
看下面这段代码,定义了一个copy方法,接受的是List<? extends B> 类型的参数,它表示接受的参数就是B的子类类型的list。那这个参数我们可传入C类型的list,因为C是B的子类。copy方法中只能对list进行get操作,为什么呢?因为我们限定了该类型的上届,里面可以放任何B类型的子类,但我们不知道当前到底是放什么子类的list,可以是C,也可能是继承了B的D。如果让你add元素,就可能导致发生运行时错误,所以就干脆不让你add。但是编译器可以肯定的是get出来的元素一定是B。所以你是可以get出B类型的元素。

 public static void main(String[] args) {
        List<C> s3 = new ArrayList<>();
        copy(s3);
    }

    public static void copy(List<? extends B> list) {
       B b = list.get(0);
       list.add(new B());  //编译错误
    }
    
class A {

}

class B extends A {

}

class C extends B {

}

2.Consumer Super 代码表示为List<? super T>
这个又代表什么意思呢,它表示下届为T,该List里面装的都是T的父类。
看下面的段代码,copy1方法接受B类型的所有父类参数。所有我们可以传入A类型的List。
在copy方法中可以对list进行add操作,add可以是A的任何子类。你也可以get出来元素,但是你get出来的只能是Object类型的,因为限定的是上届,编译器是不知道,add的到底是A的哪个子类,所以get出来只能是Objec类型。

    public static void main(String[] args) {
        List<A> s4 = new ArrayList<>();
        copy1(s4);
    }

    public static void copy1(List<? super B> list) {
       Object o  =  list.get(0);
       C c = new C();
       list.add(c);
    }


}

 class A {

}

class B extends A {

}

class C extends B {

}

如果你理解不了Pesc原则的话,就记住一句话,总结下就是上限只读,下届只添加。
关于面试的基本也就问这些了,再问就是C语言的东西了~~ 我也不会 哈哈哈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章