Java泛型擦除——以super关键字指定类型下限的在泛型擦除时会被擦成啥样的呢?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java泛型擦除——以super关键字指定类型下限的在泛型擦除时会被擦成啥样的呢?相关的知识,希望对你有一定的参考价值。
个人认为是Object类型?对吗?
参考技术A class Demo1public static void main(String[] args)
List<? super Animal> c1 = new ArrayList<Animal>();
c1.add(new Animal());
//get返回Object
c1.get(0);
List<? super String> c2 = new ArrayList<String>();
c2.add("A");
//get返回Object
c2.get(0);
List<String> c3 = new ArrayList<String>();
c3.add("B");
//get返回String
c3.get(0);
看结果似乎是的追问
//get返回Object
c2.get(0);
这里怎么能说get返回的是Object呢?c2.get(0).getClass().getName()的得到的可是java.lang.String
getClass()只能说明这个值的类型
// public final native Class getClass();
ArrayList c5 = new ArrayList();
c5.add(45);
//java.lang.Integer
System.out.println(c5.get(0).getClass().getName());
//这里需要转换
int a=(Integer)c5.get(0)+5;
System.out.println(a);
理解Java泛型和类型擦除
目录
对象放进List
介绍
泛型的本质是参数化类型,泛型提供了编译时类型的安全检测机制,该机制允许程序在编译时检测非法的类型,比如要实现一个能够对字符串(String)、整形(Int)、浮点型(float)、对象(Object)进行大小比较的方法,就可以使用泛型。
泛型标记
序号 | 泛型标记 | 说明 |
1 | E-Element | 在集合中使用,表示在集合中存放的元素 |
2 | T-Type | 表示Java类,包括基本的类和我们自定义的类 |
3 | K-Key | 表示键,比如Map中的Key |
4 | V-value | 表示值 |
5 | N-Number | 表示数值类型 |
6 | ? | 表示不确定的Java类型(类型通配符也可以使用) |
泛型限定
上限<? extends T>
使用通配符"?"和"extends"关键字指定泛型的上限,具体用法是<? extends T>,表示该通配符所代表的类型是T类的子类或者接口T的子接口。
下限<? super T>
使用通配符"?"和"super"关键字指定泛型的上限,具体用法是<? super T>,表示该通配符所代表的类型是T类型的父类或者父接口。
https://www.cnblogs.com/lucky_dai/p/5485421.html
泛型方法
泛型方法指将方法的参数类型定义为泛型,以便在调用的时候接收不同类型的参数。
package fanxing;
import java.util.Date;
public class GenericClassTest
public static void main(String[] args)
genericMethod(1,1.1D,1.2F);
public static <T> void genericMethod(T... param)
for (T element : param)
if(element instanceof Integer)
System.out.println("处理 Integer 类型数据中...");
else if(element instanceof Double)
System.out.println("处理 Double 类型数据中...");
else if(element instanceof Float)
System.out.println("处理 Float 类型数据中...");
else if(element instanceof Long)
System.out.println("处理 Long 类型数据中...");
else if(element instanceof Date)
System.out.println("处理 Date 类型数据中...");
泛型类
泛型类指在定义类时在类上定义了泛型,以便类在使用时可以根据传入的不同参数类型实例化不同的对象。
package fanxing;
public class GenericClassTest<T>
public static void main(String[] args)
GenericClassTest<Integer> list = new GenericClassTest<>();
list.add(11);
GenericClassTest<String> strList = new GenericClassTest<>();
strList.add("111");
private T t;
public void add(T t)
this.t = t;
public T get()
return t;
泛型接口
泛型接口和泛型类类似,通过在接口名后面添加类型参数的声明部分来实现。
package fanxing;
/**
* 泛型接口
* @param <T>
*/
public interface TGeneric<T>
T getId();
package fanxing;
import java.util.Random;
/**
* 泛型接口实现类
* @param <T>
*/
public class GenericIntergerTest implements TGeneric<Integer>
@Override
public Integer getId()
Random random = new Random();
return random.nextInt();
public static void main(String[] args)
GenericIntergerTest test = new GenericIntergerTest();
System.out.println(test.getId());
类型擦除
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。
JVM并不知道泛型的存在,因为泛型在编译阶段就已经被处理成普通的类和方法;
处理机制是通过类型擦除,擦除规则:
- 若泛型类型没有指定具体类型,用Object作为原始类型;
- 若有限定类型< T exnteds XClass >,使用XClass作为原始类型;
- 若有多个限定< T exnteds XClass1 & XClass2 >,使用第一个边界类型XClass1作为原始类型;
泛型擦除的体现
在写代码时,无法把一个 String 类型的实例加到 ArrayList<Integer> 中,因为ArrayList<Integer> 和 ArrayList<String> 在编译的时候是完全不同的类型,但是运行结果却是true。这就Java泛型的类型擦除造成的。
因为不管是 ArrayList<Integer> 还是 ArrayList<String>,在编译完成后都会被编译器擦除成了 ArrayList。
Java 泛型擦除是 Java 泛型中的一个重要特性,其目的是避免过多的创建类而造成的运行时的过度消耗。所以,想 ArrayList<Integer> 和 ArrayList<String> 这两个实例,其类实例是同一个。
对象放进List<String>
当我们正常的将 Activity 对象放进 List<String> list = new ArrayList<>( ) 这样的集合去,会报一个错:
泛型的约束让我们无法将 Activity 对象放进泛型为 String 的集合中去。那么咋整呢?
通过泛型擦除的体现已经知道ArrayList<String>(或者ArrayList<Integer>)编译后都是java.util.ArrayList,泛型的约束是在编译时约束的,真正运行的 class 是没有泛型约束的。所以只要在运行时将 Activity 对象加入List<String>中就可以了:
以上是关于Java泛型擦除——以super关键字指定类型下限的在泛型擦除时会被擦成啥样的呢?的主要内容,如果未能解决你的问题,请参考以下文章
Java 泛型泛型用法 ( 泛型编译期擦除 | 上界通配符 <? extends T> | 下界通配符 <? super T> )