本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2024-11(1)

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

发布于2020-11-19 20:59     阅读(1590)     评论(0)     点赞(27)     收藏(4)


       偶然拜读IT界知名大佬王垠老师的博客,发现一个有意思的题目:

1 // 这段代码里面到底哪一行错了?为什么?
2 // 原文:http://www.yinwang.org/blog-cn/2020/02/13/java-type-system
3 public static void f() {
4     String[] a = new String[2];
5     Object[] b = a;
6     a[0] = "hi";
7     b[1] = Integer.valueOf(42);
8 }

       虽然小菜才疏学浅,但本着学习交流的态度,写下此篇文章来分析一下这个问题。

 

       首先我们要读懂每一行代码在做什么:

      

       String[] a = new String[2]; 定义一个字符串类型的数组a,并初始化。

       Object[] b = a; 定义一个对象类型的数组b,并将字符串类型数组a赋值给b。

       a[0] = "hi"; 使用变量a访问数组中的第一个元素,赋值。

       b[1] = Integer.valueOf(42); 使用变量b访问数组中的第二个元素,赋值。

 

       只有简单的四行代码,相信读者都可以看的懂。

       先不考虑太多,直接执行一下代码,编译通过,运行报错:java.lang.ArrayStoreException: java.lang.Integer。

       错误提示我们第四行代码有问题,不可以将整型数据存储到数组b中,而b是一个Object类型的数组,编译通过,却无法赋值。

       分析一下原因,数组b的引用指向数组a,我们操作数组b,实际在内存中,访问的应该是数组a,而数组a是一个字符串类型数组,整个过程中,并不存在Object类型的数组,仅有一个字符串类型的数组在内存中被创建,如图:

       变量a和变量b只不过是门面,通过这两道门,到达的是同一个房间。只不过a门只允许String类型通过,而b门没有任何限制。

       因此,假如我们写下a[0] = Integer.valueOf(42);,编译器立刻会发现错误,提示类型错误,而b[1] = Integer.valueOf(42);的写法是符合规则的,但由于实际数据结构是String数组,所以运行肯定无法通过。

       为什么会这样?出现这种问题的根本原因,在于Object[] b = a;,严格来说,这种语法是错误的,但是在JDK规范中却被认可。

       为什么说是错误的?面向对象中的继承我们再熟悉不过了,子类完全具有父类的能力,子类可以退化成为父类。

       单说String的确是Object的子类,完全符合规则,但数组是另一回事,本例中String数组仅仅能容纳String类型的元素,而Object数组可以容纳任意类型的元素,String数组并非完全具有Object数组的能力。

       从另一个角度看,无论是String[] a还是Object[] b,这两种写法中的变量a和变量b,仅仅能决定指针的指向(引用哪个具体的数组),而无法控制数组内的元素,只能整体操作,而数组必然要涉及某个元素的部分操作,这就造成数组内部数据结构的“逸出”,必然会出现问题。

综上,数组之间的抽象是错误的,数组之间没有直接的继承的能力,不属于面向对象继承的讨论范畴。

       实际编写代码时,不必过分纠结这个问题,尽量不使用这种危险的操作,而是用更加优雅的方式去实现:

1 // 这样就能很好的发现错误,避免给自己挖坑
2 public static void f() {
3     String[] a = new String[2];
4     Object b = a;  //数组本身也是对象
5     a[0] = "hi";
6     ((String[]) b)[1] = Integer.valueOf(42);
7 }

 



所属网站分类: 技术文章 > 博客

作者:java小王子

链接:http://www.javaheidong.com/blog/article/1369/38715ad68837b5a31612/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

27 0
收藏该文
已收藏

评论内容:(最多支持255个字符)