博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java™ 教程(泛型的限制)
阅读量:6449 次
发布时间:2019-06-23

本文共 3977 字,大约阅读时间需要 13 分钟。

泛型的限制

要有效地使用Java泛型,必须考虑以下限制:

  • 无法使用基元类型实例化泛型类型
  • 无法创建类型参数的实例
  • 无法声明类型为类型参数的静态字段
  • 无法对参数化类型使用强制类型转换或instanceof
  • 无法创建参数化类型的数组
  • 无法创建、捕获或抛出参数化类型的对象
  • 无法重载将每个重载的形式参数类型擦除为相同原始类型的方法

无法使用基元类型实例化泛型类型

考虑以下参数化类型:

class Pair
{ private K key; private V value; public Pair(K key, V value) { this.key = key; this.value = value; } // ...}

创建Pair对象时,不能将基本类型替换为类型参数KV

Pair
p = new Pair<>(8, 'a'); // compile-time error

你只能将非基本类型替换为类型参数KV

Pair
p = new Pair<>(8, 'a');

请注意,Java编译器将8自动装箱到Integer.valueOf(8),将'a'自动装箱到Character('a')

Pair
p = new Pair<>(Integer.valueOf(8), new Character('a'));

有关自动装箱的详细信息,请参阅。

无法创建类型参数的实例

你无法创建类型参数的实例,例如,以下代码导致编译时错误:

public static 
void append(List
list) { E elem = new E(); // compile-time error list.add(elem);}

作为解决方法,你可以通过反射创建类型参数的对象:

public static 
void append(List
list, Class
cls) throws Exception { E elem = cls.newInstance(); // OK list.add(elem);}

你可以按如下方式调用append方法:

List
ls = new ArrayList<>();append(ls, String.class);

无法声明类型为类型参数的静态字段

类的静态字段是类的所有非静态对象共享的类级变量,因此,类型参数的静态字段是不允许的,考虑以下类:

public class MobileDevice
{ private static T os; // ...}

如果允许类型参数的静态字段,则以下代码将混淆:

MobileDevice
phone = new MobileDevice<>();MobileDevice
pager = new MobileDevice<>();MobileDevice
pc = new MobileDevice<>();

因为静态字段os是由phonepagerpc共享的,所以os的实际类型是什么?它不能同时是SmartphonePagerTabletPC,因此,你无法创建类型参数的静态字段。

无法对参数化类型使用强制类型转换或instanceof

因为Java编译器会擦除泛型代码中的所有类型参数,所以无法验证在运行时使用泛型类型的参数化类型:

public static 
void rtti(List
list) { if (list instanceof ArrayList
) { // compile-time error // ... }}

传递给rtti方法的参数化类型集是:

S = { ArrayList
, ArrayList
LinkedList
, ... }

运行时不跟踪类型参数,因此它无法区分ArrayList<Integer>ArrayList<String>之间的区别,你可以做的最多是使用无界通配符来验证列表是否为ArrayList

public static void rtti(List
list) { if (list instanceof ArrayList
) { // OK; instanceof requires a reifiable type // ... }}

通常,除非通过无界通配符对其进行参数化,否则无法强制转换为参数化类型,例如:

List
li = new ArrayList<>();List
ln = (List
) li; // compile-time error

但是,在某些情况下,编译器知道类型参数始终有效并允许强制转换,例如:

List
l1 = ...;ArrayList
l2 = (ArrayList
)l1; // OK

无法创建参数化类型的数组

你无法创建参数化类型的数组,例如,以下代码无法编译:

List
[] arrayOfLists = new List
[2]; // compile-time error

以下代码说明了将不同类型插入到数组中时会发生什么:

Object[] strings = new String[2];strings[0] = "hi";   // OKstrings[1] = 100;    // An ArrayStoreException is thrown.

如果你使用泛型列表尝试相同的操作,则会出现问题:

Object[] stringLists = new List
[]; // compiler error, but pretend it's allowedstringLists[0] = new ArrayList
(); // OKstringLists[1] = new ArrayList
(); // An ArrayStoreException should be thrown, // but the runtime can't detect it.

如果允许参数化列表数组,则前面的代码将无法抛出所需的ArrayStoreException

无法创建、捕获或抛出参数化类型的对象

泛型类不能直接或间接扩展Throwable类,例如,以下类将无法编译:

// Extends Throwable indirectlyclass MathException
extends Exception { /* ... */ } // compile-time error// Extends Throwable directlyclass QueueFullException
extends Throwable { /* ... */ // compile-time error

方法无法捕获类型参数的实例:

public static 
void execute(List
jobs) { try { for (J job : jobs) // ... } catch (T e) { // compile-time error // ... }}

但是,你可以在throws子句中使用类型参数:

class Parser
{ public void parse(File file) throws T { // OK // ... }}

无法重载将每个重载的形式参数类型擦除为相同原始类型的方法

一个类不能有两个在类型擦除后具有相同的签名的重载方法。

public class Example {    public void print(Set
strSet) { } public void print(Set
intSet) { }}

重载将共享相同的类文件表示,并将生成编译时错误。


转载地址:http://mqlwo.baihongyu.com/

你可能感兴趣的文章
《Hadoop与大数据挖掘》一2.2.5 动手实践:Hadoop IDE配置
查看>>
《计算机系统:系统架构与操作系统的高度集成》——2.9 指令集体系结构选择...
查看>>
《贝叶斯思维:统计建模的Python学习法》——2.7 讨论
查看>>
《CCNP安全Secure 642-637认证考试指南》——8.5节完成助记表
查看>>
《Android应用开发》——1.1节下载开发软件
查看>>
《贝叶斯思维:统计建模的Python学习法》——1.7 Monty Hall难题
查看>>
升级TCP协议使网速提升30%,中国受益明显
查看>>
Go 语言对 Android 原生应用开发的支持情况
查看>>
《沟通的技术——让交流、会议与演讲更有效》一1.1 一切尽在计划之中
查看>>
Firefox 44 浏览器内建更好的 SSL 错误指示器
查看>>
《数据科学:R语言实现》——2.9 使用twitteR
查看>>
《思科UCS服务器统一计算》一第2章 服务器架构2.1 处理器的演变
查看>>
微软概述 Islandwood 计划
查看>>
《CUDA C编程权威指南》——3.2节理解线程束执行的本质
查看>>
《深入理解Android》一导读
查看>>
linux查看登录用户及踢掉用户
查看>>
如何防止网站因改版导致权重下降?
查看>>
《伟大的计算原理》一大数据
查看>>
《UG NX8.0中文版完全自学手册》一导读
查看>>
Windows和Linux端rsync推拉同步时中文乱码解决方法
查看>>