对泛型之不能协变(convariant)的理解,以及不能协变导致的问题

2023-11-17

1.何为协变
假设有一个接口,以及一个他的实现类
如下:
接口为:

public interface GenericsInterface {
void test();
}


其实现类为:

public class Type2 implements GenericsInterface{
int i = 2;
public void test(){
System.out.println(i);
}

}




//子类的对象可以直接为父类的句柄进行引用,即为是可以协变的
GenericsInterface gi = new Type2();


2.泛型是不能协变的
在1的情况下添加一个类G1

public class G1<T> {
private T i = null;
public void print(){
System.out.println(i);
}
public T getI() {
return i;
}
public void setI(T i) {
this.i = i;
}

}


测试代码如下:

//子类的对象可以直接为父类的句柄进行引用,即为是可以协变的
GenericsInterface gi = new Type2();


//以子类SUBTYPE作为泛型参数的A类对象
//是不能由以SUBTYPE的父类作为泛型参数的A类句柄所引用,即为不可协变
G1<GenericsInterface> g4 = new G1<Type2>();//invalid


[color=red]由1,2两点可以推出以下的结论:
(1)子类的对象可以直接为父类的句柄进行引用,即为是可以协变的
(2)以子类SUBTYPE作为泛型参数的A类对象是不能由以SUBTYPE的父类TYPE作为泛型参数的A类句柄所引用,即为不可协变[/color]

3.java为什么要让泛型不能协变呢?
请看以下的示例

List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));

[color=blue]因为 ln是 List<Number>,所以向其添加 Float似乎是完全合法的。但是如果 ln是 li的别名,那么这就破坏了蕴含在 li定义中的类型安全承诺 —— 它是一个整数列表,这就是泛型类型不能协变的原因。[/color]


4.泛型不能协变导致的问题
如下示例

G1[] g1array = new G1[3];
G1<String>[] g1array2 = new G1<String>[3];//invalid
G1<?>[] g1array3 = new G1<?>[3];


为什么当数组中的G1类的泛型参数具体化后变成invalid的呢?
也就是说在实例化G1数组,往G1数组添加成员之前,就把泛型参数具体指定时,是非法的

由以下可以看出原因

List<String>[] lsa = new List<String>[10]; // illegal
Object[] oa = lsa;//OK because List<String> is a subtype of Object
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[0] = li;
String s = lsa[0].get(0);


最后一行将抛出 ClassCastException,因为这样将把 List<Integer>填入本应是 List<String>的位置。因为数组协变会破坏泛型的类型安全,所以不允许实例化泛型类型的数组(除非类型参数是未绑定的通配符,比如 List<?>)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对泛型之不能协变(convariant)的理解,以及不能协变导致的问题 的相关文章

随机推荐

  • 【数据结构】&&【C++】平衡搜索二叉树的模拟实现(AVL树)

    数据结构 C 平衡搜索二叉树的模拟实现 AVL树 一 AVL树的性质 二 AVL树的模拟实现 AVL树结点的定义 AVL树的插入 平衡因子的更新 左单旋 右单旋 双旋 左右旋 右左旋 AVL树的删除 检查是否是AVL树 三 完整代码 一 A
  • Tp5 left join 带条件 数据不返回

    背景 下面两种方式都是在查询吸毒人员的基本信息 pa account 表示该吸毒人员的评估小组 一般情况下 录入吸毒人员基础信息都会录入其关联的评估小组 但是部分也不录入 理论上 无论评估小组有没有录入 left join 都要返回左表ad
  • 微信小程序:日历模块页面

    文章目录 1 前言 2 功能需求 3 界面展示 4 部分代码展示 5 结语 完整项目下载 下载链接 1 前言 在制作背单词打卡小程序中 用户需要方便地查看历史学习信息 为了使页面美观并保持交互简洁 采用日历作为日期选择器是极为必要的 本指南
  • nginx中间件常见漏洞总结

    nginx中间件常见漏洞总结 1 中间件漏洞的概念 1 1 中间件 容器 服务器的基本概念辨析 2 Nginx 配置错误导致漏洞 2 1 uri 导致的CRLF注入漏洞 2 1 1 漏洞成因 2 1 2 利用方式 2 1 3 修改方案 2
  • 程序员必备技能-使用git把github的代码下载到本地使用

    在代码的学习过程中 难免需要看下github上的优秀项目 或者在参加某个培训班的时候 老师的示例代码存放在github中 想在本地的IDE中跑跑试试 这篇文章提供一个简单的获取github项目在自己的IDE中打开的方法 目录 一 获取git
  • STM32F103ZET6【HAL开发】STM32CUBEMX------3.2高级定时器输出带死区的互补PWM

    一 STM32F103只有高级定时器才能输出互补的PWM波形 定时器的对应IO如下表 二 下面以TIM1为例 演示三对带死区的PWM波形在STM32CUBEMX里面的配置 TIM1 CH1 TIM1 CH1N TIM1 CH2 TIM1 C
  • [matlab]10种经典的时间序列预测模型

    matlab 10种经典的时间序列预测模型 本文演示了 10 种不同的经典时间序列预测方法 它们是 自回归 AR 移动平均线 自回归移动平均线 自回归积分移动平均线 ARIMA 季节性自回归积分移动平均线 SARIMA 具有外生回归量的季节
  • R语言3.11 因子分析因子旋转

    因子旋转 目的 寻找每个主因子的实际意义 如果各主因子的典型代表变量不突出 就需要进行旋转 使因子载荷矩阵中载荷的绝对值向0和1两个方向分化 方法 正交旋转Varimax 最大方差正交旋转 斜交旋转Promax Fa2 factanal X
  • 集成学习-Adaboost

    Author 鲁力 Email jieyuhuayang foxmail com Datawhale Adaboost 算法简介 集成学习 ensemble learning 通过构建并结合多个学习器 learner 来完成学习任务 通常可
  • Keras和Tensorflow(CPU)安装、Pytorch(CPU和GPU)安装以及jupyter使用虚拟环境

    微信公众号 数学建模与人工智能 Keras和Tensorflow CPU 安装 Pytorch CPU和GPU 安装 Keras和Tensorflow CPU 安装 一 安装我用的是清华大学源 二 深度学习模型保存与加载 三 错误 Tens
  • matlab中的掩膜抠图

    改进版 矩阵中的循环操作非常耗时 so 用矩阵逻辑与操作替代for循环 one ones s img 1 s img 2 segM segM uint8 one for i 1 s img 1 for j 1 s img 2 if segM
  • 微信小程序16进制颜色码

    颜色码http www w3school com cn cssref css colornames asp
  • 时间序列算法理论及python实现(2-python实现)

    如果你在寻找时间序列是什么 如何实现时间序列 那么请看这篇博客 将以通俗易懂的语言 全面的阐述时间序列及其python实现 时间序列算法理论详见我的另一篇博客 时间序列算法理论及python实现 知 青 博客园 5 Python实现ARIM
  • ChatGPT 最好的替代品

    前两天我们邀请了微软工程师为我们揭秘 ChatGPT 直播期间有个读者问到 有了 ChatGPT BERT 未来还有发展前途吗 我想起来最近读过的一篇博客 最好的 ChatGPT 替代品 不过聊到这俩模型 就不得不提到 Transforme
  • 堆排序(Heapsort)-- 高级排序算法

    1 堆排序 Heapsort 堆排序 Heapsort 是指利用堆这种数据结构所设计的一种排序算法 二叉堆本质上是一种完全二叉树 它分为两个类型 最大堆和最小堆 最大堆任何一个父节点的值 都大于等于它左右孩子节点的值 最小堆任何一个父节点的
  • 同步(Synchronous)和异步(Asynchronous)

    概念性 同步和异步通常用来形容一次方法调用 同步方法调用一旦开始 调用者必须等到方法调用返回后 才能继续后续的行为 异步方法调用更像一个消息传递 一旦开始 方法调用就会立即返回 调用者就可以继续后续的操作 而 异步方法通常会在另外一个线程中
  • idea设置默认maven

    idea修改默认maven配置 方法一 不推荐 打开project default xml文件 在其中加入如下几行配置 代码如下 保存修改之后新建一个maven项目查看效果 方法二 新增Projects Settings 方法一 不推荐 需
  • 线性滤波器&非线性滤波器

    前言 采用线性滤波和非线性滤波是在空间域上处理图像最常用的滤波方法 matlab在处理图像滤波方面拥有可调用的函数 十分便利 我们可以根据自己的需要自行选择滤波方式对图像进行滤波 值得一提的是 图像锐化在某种程度上来说就是线性滤波 一 线性
  • emc re 整改 超标_EMC辐射骚扰超标如何整改?

    辐射骚扰是电脑 GPS导航等工作时向空间发射的一种电磁波干扰 这种干扰会影响其他电器特别是高灵敏度电器的正常工作 组成整机系统的主板 显示卡 开关电源 显示器 键盘 鼠标等都可能引起辐射骚扰超标 对于辐射骚扰通常用电磁场的大小来度量 其单位
  • 对泛型之不能协变(convariant)的理解,以及不能协变导致的问题

    1 何为协变 假设有一个接口 以及一个他的实现类 如下 接口为 public interface GenericsInterface void test 其实现类为 public class Type2 implements Generic