java高级泛型学习笔记

泛型 用于增强在编译期类型检测,减少因类型问题引发的运行时异常
泛型有更强的类型检查
泛型可以避免类型转换
泛型可以泛型算法,增加代码复用性

泛型类
泛型接口
泛型方法

//泛型类
public class Box<T>{

}

//泛型接口
public interface Generics<T>{
public T text();
}

interface GenericsN<T, S, U, V>{

}

//泛型类接口的继成和实现
class Generics2<T> implement Generics <T>{
Generisc2 <Integer> generics = new Generics2<>();
}

class Generics3 implement Generics <String>{

}
class GeeriscMethod{
//泛型方法
public <T> void test(T t){

}

//泛型方法
public <T> T test(T t){
return t;
}

//不是泛型方法
public void test2(list<String> list){
}
//不是泛型方法
public void test3(List<?> list){

}

//不是泛型方法
public <T> void test4(Box<E>: box){
}
}

最常见的类型变量有:
E:元素(在Java集合框架中有广泛的应用)
K:键
N:数字
T:类型
V:值
S,U,V等:第二, 第三,第四个类型

类型参数与类型变量的不同
Foo<T>中的T为类型参数
Foo<String>中的String为类型变量

钻石运算符
JDK7以下版本
Box<Integer> integerBox = new Box<Integer>();
JDK7以上版本
Box<Integer> integerBox1 = new Box<>(); //The Diamond(菱形)类型推断

原始类型
缺少实际类型变量的泛型就是一个原始类型
举例:
class Box<T>{}
Box b= new Box(); //这个Box就是Box<T>的原始类型

受限的类型参数
功能:对泛型变量的范围作出限制
格式:
单一限制:<U extends Number>
多种限制:<U extends A & B & C>
extends表达的意义:这里指的是广义上的“扩展”,兼有“类继承”和“接口实现”之意
多种限制下的格式语法要求:如果上限类型是一个类,必须第一位标出,否则编译错误

泛型算法实现的关键:利用受限类型参数

java泛型PECS原则
如果你只需要从集合中获得类型T,例用<? extends T>通配符
如果你只需要将类型T放到集合中,使用<? super T>通配符
如果你既要获取又要放置元素,则不使用任何通配符。例如list<Apple>
PECS即 Producer extends Consumer super, 为了便于记忆

为何要PECS原则?为了提升API的灵活性

类型推断
类型推断是Java编译器查看每个方法调用和相应声明认确定使调用适用的类型参数的能力。
推断算法确定参数的类型,以及确定结果是否被分配或返回的类型(如果有)
最后,推断算法尝试找到与所有参数一起使用的最具体的类型

static <T> T pick(T a1, T a2){return a2; }

//public final class String
implements java.io.Serializable, Comparable<String>, CharSequence

//public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Serializable s = pick("d", new ArrayList<String>());
通配符
泛型中的问号符“?”名为“通配符”
受上下限控制的通配符, 上限(super)不能获取数据 ,下限(extends)不能添加数据
通配符的适用范围:
参数类型
字段类型
局部变量类型
返回值类型(但返回一个具体类型的值更好)
java泛型是一种伪泛型,为是兼容低版本。


面试题
Array中可以用泛型吗?
不可以

你可以把List<String>传递给一个接受List<Object>参数的方法吗?
ArrayList<String> arrayList1 = new ArrayList<Object>(); //不可以 ArrayList<String> 和ArrayList<Object> 没有继成关系
ArrayList<Object> arrayList1 = new ArrayList<String>(); //不可以 ArrayList<String> 和ArrayList<Object> 没有继成关系

Java中Set与Set<?>到底区别在哪?
前者是原始类型,不会接受类型检查, 后者要接受类型检查

java中List<?>和List<Object>之间的区别的什么?
java中List<?>是一个未知类型的List,
List<Object>其实是任意类型的List

java的泛型是什么?使用泛型的好处是什么?
泛型是一种参数化的类型的机制。 一个用于类型检测提前到编译器,便于更早好现错误。二是用于代码复用

泛型是怎么工作的?什么是类型擦除?
代码在编译期,编译器会检测泛型的类型。转化为字节码时,退化,被擦除。
不擦除,虚拟机认不出来。

List<? extends T> 和List <? super T> 之间有什么区别?
前面是只读,后面是只写

如何编写一个泛型方法,让它能接受泛型参数,并返回泛型类型?
Java中如何使用泛型编写带有参数的类?
public V put(K key, V value)
{
return cache.put(key, value);
}
public class Pair<K, V>{
private K key;
private V value;
public Pair(K key, V value){}
}
泛型类型变量不能是基本的数据类型
ArrayList<double> arr1 = new ArrayList<>(); //错误
ArrayList<Doouble> arr = new ArrayList<>();

运行进类型查询
ArrayList<String> arrayList = new ArrayList<String>();
if(arrayList instanceof ArrayList<String>) //报错, 因为类型擦除
if(arrayList instanceof ArrayList<?>) //可以

泛型在静态方法和静态类中的问题
public class Test2<T>{
public static T one; //不可以
public static T show(T one){ //不可以
return null;
}
public static <T> T show1(T one){ //可以第一个T相当于重新定义,和Class里面的T没有关系
}
}

如何阻止Java中的类型未检查的警告?
加注解可以用@SuppressWarnings("unchecked")注解来屏蔽

C++模板和java泛型什么区别?
C++里面是供了一套宏定义,直接替换,Java里面是伪泛型。

posted @ 2021-10-17 22:33  zhudaheng123  阅读(73)  评论(0)    收藏  举报