Java 泛型了解么?
泛型是一种在编译时提供类型安全检查的机制,可以增加我们代码的可读性和安全性。泛型可以在编译时期对泛型参数进行校验来指定选入对象的类型,比如 ArrayList<Person> persons = new ArrayList<Person>() 这行代码就指明了该 ArrayList 对象只能传入 Person 对象,如果传入其他类型的对象就会报错。
什么是类型擦除?
类型擦除是Java泛型的一个重要概念,它指的是泛型信息只在编译阶段存在,在进入JVM之前,与类型相关的信息会被擦除掉,或者说被替换掉。这意味着泛型类(擦除后我们称之为原始类)和非泛型类在运行时实际上是相同的类。
Java 为什么要选择类型擦除这种实现方式?
类型擦除其实一直为我们程序员所诟病,给我们带了一些不必要的麻烦,那为什么还有选择类型擦除呢,其目的是为了向低版本兼容
类型擦除导致了哪些弊端?
泛型信息真的就没了吗?
并不是,泛型信息消失只是对于jvm而言,它会存储在。class文件中,这意味着我们可以通过反射去恢复这些泛型信息。
介绍⼀下常⽤的通配符?
问号通配符 ?
表示未知类型。通配符可用于参数、字段、局部变量和返回类型。可以近似的理解为泛型的泛型。
-
通配符匹配出来的泛型类型只能读取,不能写入。因为不知道这个容器放什么类型的数据,所以只能读取不能添加。
-
最好不要在返回类型中使用通配符,因为确切知道方法返回的类型更安全。
public static void main(String[] args) {List<String> name = new ArrayList<String>();List<Integer> age = new ArrayList<Integer>();List<Number> number = new ArrayList<Number>();name.add("icon");age.add(18);number.add(314);getData(name); // icongetData(age); // 18getData(number); // 314
}// List<?>,在逻辑上是List<String>,List<Integer>等所有List<具体类型实参>的父类。
public static void getData(List<?> data) {System.out.println("data :" + data.get(0));
}
2.4. 上下边界限定
- 上界限定通配符:
<? extends E>
,表示只接受E类型及其子类型。 - 下界限定通配符:
<? super E>
, 表示只接受E类型及其父类型。
public static void main(String[] args) {List<String> name = new ArrayList<String>();List<Integer> age = new ArrayList<Integer>();List<Number> number = new ArrayList<Number>();name.add("icon");age.add(18);number.add(314);getUperNumber(name); // 编译时报错,String类型不是Number的子类getUperNumber(age); // 18getUperNumber(number); // 314
}public static void getData(List<?> data) {System.out.println("data :" + data.get(0));
}// List<? extends Number>,在逻辑上是List<Number>,List<Integer>等类的父类。
public static void getUperNumber(List<? extends Number> data) {System.out.println("data :" + data.get(0));
}
信息来源于:【每次一个技术点】泛型之类型擦除_哔哩哔哩_bilibili
讲解的非常好,up主的基本功非常好,一些细节上的问题,和语言设计时出现的缺点都讲的透透的!