Java面向对象系列[v1.0.0][擦除和转换]

擦除和转换

在严格的泛型代码里,带泛型声明的类总应该带着类型参数,但是也允许使用带泛型声明的类时不指定实际的类型,如果没有为这个泛型类指定实际的类型,则称作原始类型,默认是声明该泛型形参时指定的第一个上限类型
当把一个具有泛型信息的对象赋给另一个没有泛型信息的变量时,所有在尖括号之间的类型信息都将被丢掉,例如List类型被转换为List,则该List对集合元素的类型检查变成了泛型参数的上限即Object

class Apple<T extends Number>
{
   T size;
   public Apple()
   {
   }
   public Apple(T size)
   {
      this.size = size;
   }
   public void setSize(T size)
   {
      this.size = size;
   }
   public T getSize()
   {
      return this.size;
   }
}
public class ErasureTest
{
   public static void main(String[] args)
   {
	// 创建Apple对象,该Apple对象a的泛型代表了Integer类型
      Apple<Integer> a = new Apple<>(6);    
      // a的getSize方法返回Integer对象
      Integer as = a.getSize();
      // 把a对象赋给Apple变量,丢失尖括号里的类型信息
      Apple b = a;    
      // 因为Apple类的泛型形参的上限是Number类,所以size1是Number类型,但具体是Number的哪个子类就不知道了
      Number size1 = b.getSize();
      // 下面代码引起编译错误
      // Integer size2 = b.getSize();  
   }
}

如代码所示声明了一个带泛型声明的Apple类,其泛型形参的上限是Number,这个泛型形参用来定义Apple类的size变量

理论上说List是List的子类,如果直接把一个List对象赋值给一个List对象应该是会引起编译错误的,但实际是不会的,对于泛型而言,只会提示“未经检查的转换”

import java.util.*;
import static java.lang.System.*;
public class ErasureTest2
{
   public static void main(String[] args)
   {
      List<Integer> li = new ArrayList<>();
      li.add(6);
      li.add(9);
      List list = li;
      // 下面代码引起“未经检查的转换”的警告,编译、运行时完全正常
      List<String> ls = list;  
      // 但只要访问ls里的元素,如下面代码将引起运行时异常。
      out.println(ls.get(0));
   }
}

类似的是:

public class ErasureTest2
{
	public static void main(String[] args)
	{
		List li = new ArrayList();
		li.add(6);
		li.add(9);
		System.out.println((String)li.get(0));
	}
}

程序试图从li中获取一个元素,并且试图通过强制类型转换把它转换成一个String,将引发运行时异常

发布了207 篇原创文章 · 获赞 124 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/dawei_yang000000/article/details/105347830