王垠的这道Java高级面试题,看似容易,其实很难!

王垠的解释器学习材料 王垠虽然疯了,但是他写的解释器教材还是引入的蛮好的。 阅读详情

前言:
这篇博客转自微信的公众号上一篇文章,作为借鉴,也是给自己偶尔可以看下的素材。
不过正确性目前不确定,待商榷,所以我没有做一个自己学习的理解弄出原创出来,待以后觉得理解的差不多了,就会总结一下的。
不过目前总结的一句话是编译看左,运行看右。编译时类型是父类(Object),运行时类型选择是右边声明的子类(String),这个时候用Integer去赋值给父类,编译时不会报错,运行期间就会报错。
原文链接:

https://mp.weixin.qq.com/s?__biz=MzIzMzgxOTQ5NA==&mid=2247490937&idx=1&sn=2d974f3ec0132bb30dca182ac708be60&chksm=e8fe8170df890866429a9518d7cc7de31b838c13df964781b1d73883c21412907fc71ffb69c3&mpshare=1&scene=23&srcid=&sharer_sharetime=1582708588478&sharer_shareid=8ee32394799c755cc16e6a0b51d02544#rdz

最近,在垠神的微博上,看到他出的一道关于Java的高级面试题,与各位同学分享一下,题目内容如下图:
在这里插入图片描述

这道题目主要是关于Java中协变与逆变的思考,先说一下运行结果,编译期会放行,运行期会抛异常:

java.lang.ArrayStoreException: java.lang.Integer

正如《Effective Java》的作者所说,Java允许数组协变是Java本身的缺陷,他也没闹明白为什么要这么设计,估计是为了妥协吧。

关于Java协变与逆变的思考,我也在网上找了一些资料和自己的理解,说实话,写这篇文章确实有难度,不能保证文章的内容完全正确,欢迎各位同学指正。

什么是协变与逆变?

其实关于它的定义,维基百科上面讲的很详细,我就在这里简单的说一下。

逆变与协变用来描述类型转换(type transformation)后的继承关系。

其定义:如果A、B表示类型,f(⋅)表示类型转换,≤表示继承关系(比如,A≤B表示A是由B派生出来的子类)

f(⋅)是逆变(contravariant)的,当A≤B时有f(B)≤f(A)成立;

f(⋅)是协变(covariant)的,当A≤B时有f(A)≤f(B)成立;

f(⋅)是不变(invariant)的,当A≤B时上述两个式子均不成立,即f(A)与f(B)相互之间没有继承关系。

看这些概念是不是有点晦涩难懂,其实在《Thinking in Java》讲泛型那章提到一个例子挺好的说明问题的。

class Fruit {}
class Apple extends Fruit {}
class Orange extends Fruit {}

比如,有两个类型Apple和Fruit,它们之间的关系是Apple≤Fruit,即Apple是Fruit的子类型;通过它们构造出对应的数组类型Fruit[]和Apple[],最终这对数组类型的关系是Apple[] ≤ Fruit[],即数组类型也保持着原类型之间的关系,这说明数组具有协变性。

Fruit[] fruits = new Apple[10];

从上面的代码,我们也可以看出:子类型的数组可以赋予父类型的数组进行使用。

接着,我们再来看看下面这句代码:

fruits[0] = new Orange();//抛 java.lang.ArrayStoreException

你注意到没有,Java为了确保类型安全,必须明确知道数组内部元素的类型(声明时),而且记住这个数组类型,每次往数组里面插入新元素(运行)时,都会进行类型检测,如果不匹配,就会抛出异常:java.lang.ArrayStoreException。

到这一步,我们便能理解了垠神上面的那个代码为啥会抛异常。

数组为什么要设计协变?

我挺赞同文章开头那种说法,在Java SE5之前没有泛型,急需要这种设计来解决当务之急,所以才这么设计。

就比如我们常用的Arrays.equals()方法,代码如下:

public static boolean equals(Object[] a, Object[] a2) {
      if (a==a2)
          return true;
      if (a==null || a2==null)
          return false;

      int length = a.length;
      if (a2.length != length)
          return false;

      for (int i=0; i<length; i++) {
          Object o1 = a[i];
          Object o2 = a2[i];
          if (!(o1==null ? o2==null : o1.equals(o2)))
              return false;
      }

      return true;
}

由于没有泛型,所以把数组这么设计,来进行妥协,让多态的作用发挥出来,所以,是不是缺陷?就需要根据具体的时间点和环境而议。

谈谈泛型

Java的泛型设计,确实很牛逼,可以穿梭于协变、逆变与不变之间。

ArrayList<Number> list = new ArrayList<Integer>(); //type mismatch

上面这句代码编译时,会报错:type mismatch。由于Integer ≤ Number,而实例化的list对象是错误的,因此,默认情况下,Java的泛型是不变的。
有同学可能会问:有时需要实现逆变与协变,怎么办呢?
这时,可以使用通配符 ? 。

<? extends>实现了泛型的协变,比如:

List<? extends Number> list = new ArrayList<Integer>();

<? super>实现了泛型的逆变,比如:

List<? super Number> list = new ArrayList<Object>();

那问题又来了,究竟什么时候用extends什么时候用super呢?可以参考《Effective Java》这本书,见下图:
在这里插入图片描述

总结一下吧:

要从泛型类取数据时,用extends;

要往泛型类写数据时,用super;

既要取又要写,就不用通配符(即extends与super都不用)。

上面这些总结很浅显,只是对Java基础知识的回顾,更深层的研究,还需要各位同学进一步深入研究。

Java高级工程师20道面试题、答案及案例 例如,程序次序规则指出,一个线程内的每个操作,happens-before于该线程内任意后续的操作。无论try块中是否抛出异常,finally块总会被执行,这在资源管理中至关重要,用于确保如数据库连接、文件流等资源的正确关闭,即使在catch块中发生异常或try块中有return语句,finally仍会执行。当一个变量被声明为volatile后,对它的修改会立刻刷新到主内存中,其他线程能看见最新值,同时编译器和处理器不能对volatile字段的读写做任何优化,即每次都会从内存中读取该值,而不是缓存中。 阅读详情

相关推荐

2024最新Java高频精选面试题讲解,高级java开发工程师面试题

至此,文章终于到了尾声。技术能力:先写岗位所需能力,再写加分能力,不要写无关能力;项目经历:只写明星项目,描述遵循 STAR 法则;简历印象:简历遵循三大原则:清晰,简短,必要,要有的放矢,不要海投;以及最后为大家准备的福利时间:简历模板+Java面试题+热门技术系列教程视频以及最后为大家准备的福利时间:简历模板+Java面试题+热门技术系列教程视频[外链图片转存中…(img-laenPCAQ-1711102825640)]

2401_83641533的博客 1281

王垠

4. 相关链接 王垠的Email:shredderyin@gmail.com 王垠的自建博客:http://www.yinwang.org/ 王垠的新浪博客:http://blog.sina.com.cn/yinwang0 知乎上的[王垠]话题:http://www.zhihu.com/topic/19587684 王垠在IUB的个人主页:https://www.cs.indiana.e

xu_ya_fei的专栏 4304

我为什么不在乎人工智能 / 王垠

目录我为什么不在乎人工智能机器一样的心我的人工智能梦识别系统和语言理解机器对话系统和人类客服纪念我的聊天机器人 helloooo自动编程是不可能的傻机器的价值AlphaGo与人工智能棋类是相对容易的AI问题认知是真正困难的AI问题机器学习是什么AlphaGo并不是人工智能历史性的突破文 / 王垠有人听说我想创业,给我提出了一些“忽悠”的办法。他们说,既然你是程序语言专家,而现在人工智能(AI)又非常热,那你其实可以搞一个“自动编程系统”,号称可以自动生成程序,取代程序员的工作,节省许许多多的人力支出,这样就

AI天才研究院 2万+

王垠博客 linux,前段时间花了一个通宵把王垠(Yin Wang)博客的所有文章看完了...

前段时间花了一个通宵把王垠的博客看完了,觉得还是受益匪浅的,所以也给大家谈谈感想。首先说起王垠这个人嘛,最早了解他的是因为他那篇神一般的传教洗脑文章《完全用Linux工作》,虽然后来被喷成狗。这篇文章在国内的Linux圈子里面非常有名,甚至可以说是国内Linux宗教里的一面旗帜了。虽然我不是完全因为这篇文章入的Linux大坑,但是不可否认当时的我也成功被煽动成了一个Linux脑残粉…甚至到了现在我...

weixin_36250058的博客 4497

2023最新ChatGPT整理的40道Java高级面试题

以下是一些Java高级面试题: 介绍一下JVM的内部结构及其工作原理 什么是反射?如何使用反射实现动态代理 说一下Java中常见的设计模式 Java中的IO操作有哪些方式?它们之间有什么区别? 什么是Spring框架?它的优点是什么? 说一下Java中的并发编程和多线程,包括线程池、锁、同步和异步等方面 介绍一下Java中的异常处理机制和常见的异常类 Java中的集合框架有哪些?它们之间有什么区别? 请简要描述一下Java中的垃圾回收机制 什么是序列化?如何在Java中实现序列化和反序列化? 。。。。。。

xmt1139057136的专栏 8520

MediaPipe+Unity动作捕捉实战:如何用普通摄像头驱动3D人物模型(附避坑指南)

本文详细介绍了如何利用MediaPipe和Unity实现低成本动作捕捉,仅需普通摄像头即可驱动3D人物模型。通过MediaPipe的3D坐标预测能力,结合Unity的骨骼映射优化,解决单目摄像头下的三维重建难题,并提供实战避坑指南和性能优化技巧,帮助开发者快速实现专业级的人物模型驱动效果。

weixin_29047545的博客 359

王垠:我和权威的故事

原文链接:https://www.douban.com/note/747557052/ 文章目录幻觉Donald KnuthUnixGo 语言Cornell(康奈尔大学)图灵奖常青藤联盟和“世界一流大学”程序语言专家逻辑学家再见了,权威们后记(关于 IU) 幻觉 每个人小时候心里都是没有权威的,就像每个人小时候也都不相信广告一样。可是权威就像广告,它埋伏在你的潜意识里。听一遍不信,听两遍不信……直到一千遍的时候,它忽然开始起作用了,而且这作用越来越强。 消灭广告所造成的幻觉,最好的办法就是去尝试,去.

汉密士的博客 2373

Arco Design Pro PC端商家后台框架 | Axure高保真原型库

摘要:本Axure原型设计方案基于字节跳动ArcoDesignPro规范,提供企业级后台快速搭建方案。包含动态表格、表单验证等核心组件,采用中继器驱动设计,支持响应式布局。方案覆盖80%后台常用交互,可节省60%原型制作时间,配套完整设计文档和组件库,实现原型到开发的高效衔接。特别适用于电商、SaaS等后台系统开发,支持权限管理、数据分析等场景,显著提升团队协作效率。

招风的黑耳优快云 3978

100道Java中高级面试题汇总+详细拆解

出自:Java面试题精选1-10期【10期】Redis 面试常见问答【09期】说说hashCode() 和 equals() 之间的关系?【08期】说说Object类下面有几种方法呢?【...

Java笔记虾 3万+

10分钟学会工程领域Hypermesh与Abaqus联立处理大量铆钉连接简化做法

铆钉连接是一种可靠且高强度的机械连接方式,广泛应用于多个领域。但是,工程结构上铆钉连接往往以较大的数量出现,若按照常规的一个个去选择生成,处理1个铆钉连接点需要1分钟来算,300个铆钉需要5个小时,耗费大量的时间成本。给出了一种高效处理铆钉连接的方法,提升效率50倍以上。

qq_34933927的博客 1616

异步FIFO的隐形陷阱:复位信号同步化实战解析

本文深入解析异步FIFO设计中复位信号同步化的隐形陷阱,重点分析赛灵思xpm_fifo_async原语在FPGA应用中的常见问题。通过实战代码和系统集成方案,提供复位同步化的最佳实践,帮助工程师避免跨时钟域通信故障,提升系统可靠性。

keras9composer的博客 246

最全java面试题及答案(208道)

最全java面试题及答案(208道)

星哲最开心 3万+

Zabbix7.0+DeepSeek大模型实现人工智能告警分析

本方案基于Zabbix7.0监控系统,通过底层webhook脚本机制集成Deepseek做故障分析提供解决方案,构建智能化运维体系。

xingdiango的博客 2374

Java 208 道面试题:Java 基础模块答案

目前市面上的面试题存在两大问题:第一,题目太旧好久没有更新了,还都停留在 2010 年之前的状态;第二,近几年 JDK 更新和发布都很快,Java 的用法也变了不少,加上 Java 技术栈也加入了很多新的框架,比如 Spring Boot、Spring Cloud 等,但类似的面试题却极少。 相比与这些问题,我的这 208 道面试题,包含了以下 4 个特点: 披沙拣金提炼出每个 Java 模块中...

磊哥聊Java 1万+

fatal: unable to access ‘https://github.com/‘: Recv failure: Connection was reset 解决方案

本文主要介绍了fatal: unable to access ‘https://github.com/’: Recv failure: Connection was reset 解决方案,希望能对使用github的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 2万+

044、手持视频抖动严重?OpenCV 光流 + IMU 融合的电子防抖工程方案

本文探讨了基于OpenCV光流和IMU融合的手持视频电子防抖方案。作者从实际工程经验出发,分析了纯光流和纯IMU方案的局限性,指出时间戳对齐和坐标系标定是关键挑战。文章详细介绍了融合滤波器的实现方法,推荐互补滤波替代卡尔曼滤波,并提出了动态调整融合系数的策略。在光流算法优化方面,建议采用网格化FAST特征点和前后向误差检测。最后分享了运动补偿裁剪策略和多线程流水线设计,强调在嵌入式设备上使用NEON指令优化性能。该方案通过精确的时间同步和传感器融合,有效解决了手持拍摄中的高频抖动问题。

ai技术增长的博客 251

2019年总结:Java中高级面试题228道系列(6)

2019年Java面试题中高级系列228道 Java面试题(一) 第一篇更新1~20题的答案解析 https://blog.youkuaiyun.com/Design407/article/details/103408983 第二篇更新21~50题答案解析 https://blog.youkuaiyun.com/Design407/article/details/103427740 第三篇更新51~95题答案...

程序员追风的博客 8934

深度学习在地质勘探中的应用:使用Python构建卷积神经网络进行地震数据分析

在本文中,我们介绍了如何利用深度学习技术,特别是卷积神经网络(CNN),来处理和分析地震数据。我们使用了Python编程语言和TensorFlow框架构建了一个CNN模型,并使用地震数据进行了训练和评估。在本文中,我们将探讨如何利用深度学习技术,特别是卷积神经网络(CNN),来处理和分析地震数据。首先,我们需要获取地震数据集。通过本文的介绍,希望您能对深度学习在地质勘探领域的应用有更深入的了解,并能够应用这些技术来解决实际问题。在准备好地震数据和构建CNN模型后,我们需要将数据分为训练集和测试集。

斌擎科技 1472

30道精选Java中高级面试题及答案!

这些题目覆盖了Java中高级面试的核心考点。建议结合实际问题编码练习,并查阅官方文档加深理解。面试前,复习JVM、并发和设计模式是关键。祝您面试顺利!如果有具体问题需要深入讨论,欢迎继续提问。

程序员高级码农的博客 1791

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

100道最新Java面试题,常见面试题及答案汇总

除了掌握扎实的专业技能之外,你还需要一份《Java程序员面试宝典》才能在万千面试者中杀出重围,成功拿下offer。 小编特意整理了100道Java面试题,送给大家,希望大家都能顺利通过面试,拿下高薪。赶紧码住吧~~文末有福利 Q1:Java内部类和子类之间有什么区别? 答案:内部类是指在一个外部类的内部再定义一个类,内部类对外部类有访问权限,可以访问类中定义的所有变量和方法。 子类是从父类(superclass)中继承的类,子类可以访问父类所有public和protected的字段和方法。 Q2:Java语

shuux666的博客 3万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

王垠 java_解读王垠博客“一道 Java 面试题”

偶然拜读IT界知名大佬王垠老师的博客,发现一个有意思的题目:1 //这段代码里面到底哪一行错了?为什么?2 //原文:http://www.yinwang.org/blog-cn/2020/02/13/java-type-system3 public static voidf() {4 String[] a = new String[2];5 Object[] b =a;6 ...

weixin_29359765的博客 463

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

2019年Java中高级面试题总结(7),228道系列查漏补缺!

2019年Java面试题中高级系列228道 Java面试题(一) 第一篇更新1~20题的答案解析 第二篇更新21~50题答案解析 第三篇更新51~95题答案解析 Java面试题(二) 第四篇更新1~20题答案解析 第五篇更新21~50题答案解析 第六篇更新51~80题答案解析 Java 面试题(二) 81、说出几条 Java 中方法重载的最佳实践? 82、在多线程环...

程序员追风的博客 8464

Java高级面试题总结

本文内容涉及中高级面试知识点,涵盖众多大厂面试题

前方一片光明 1万+

Java 208 道面试题:Java 基础模块答案发布

目前市面上的面试题存在两大问题:第一,题目太旧好久没有更新了,还都停留在 2010 年之前的状态;第二,近几年 JDK 更新和发布都很快,Java 的用法也变了不少,加上 Java 技术栈也加入了很多新的框架,比如 Spring Boot、Spring Cloud 等,但类似的面试题却极少。 相比与这些问题,我的这 208 道面试题,包含了以下 4 个特点: 披沙拣金提炼出每个 Java 模块中...

weixin_33724059的博客 6628

王垠:一道 Java 面试题

描述 理解 题目中的这段程序在编译器正常,运行时异常。错误出现在 b[1] = Integer.valueOf(42); 这一行代码, a 赋值给 b,a 和 b 指向同一对象 new String[2],而 String[] 的实现是不支持 set integer 操作。 这行引发运行时异常。从实现角度来说,Java的数组是协变的:也就说Java的类型系统认为子类数组可以被赋值给父类数组。而...

豪伊大汉堡 954
上一篇: Web应用报错之HTTP状态码
下一篇: Invalid location of tag 解决方案
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值