如何理解对象赋值给接口的操作(关键在对象!)

分类专栏:
Java心得

文章标签:
Java
随笔
原创

今天被人问了一个问题,然后我去查了源码,虽然解决了问题,但进而引发我另一个思考——如何理解对象赋值给一个接口。

众所周知,如果一个对象赋值给它的接口,那么这个用接口“接”的对象只有接口所定义的方法和属性,失去了原本对象独有的方法和内容。(当然也规范了代码,不过本文暂不讨论这些)

按我之前的理解就是——如果把原对象比作一辆拥有众多功能的跑车,那么接口就是大家统一规格的小汽车。如果把这“跑车”赋值给小汽车,那么势必会失去一些独有的功能和属性。

但原来的属性和方法真会消失吗?

我突然又想到很多框架为了通用性,方法返回值常常为Object,那如果是Object,失去了原来的的属性和方法,只保留Object的属性和方法的话,那框架如何继续操作呢?

这显然是不对,因此我进行了简单的测试:在这里插入图片描述这里我们看到就算我们用接口接对象,对象依旧能够通过强转回原来的样子,而就算是接口Object,打印时依旧会输出这个对象的值。

这已经充分地说明了一点——用接口接对象,其属性和方法并没有丢失

那我们该如何理解呢?

实际上我们得从Java的对象理解开始说起。

对象是什么?

学过c语言的小伙伴都知道c中有个叫做指针的东西(相当于指向内存地址的坐标),java相对于c来讲的一大“优势”(有人可能认为是优势,也有人可能认为是劣势)就是Java中没有指针,这极大的减少了因指针滥用的风险。 但java中真的没有指针吗?

Java中处处都是指针!

没错,Java处处都是指针,Java的对象就是指针,这也是我们为什么要复制一个相同的对象时得用clone方法,这也是我们为什么比较两对象值是否相等时要用equals方法而不是==。

因为对象就是指针!!!

以下是我在网上找到的一段话,概括的挺好的,分享给大家

JAVA中的对象类型本质上应该叫做 对象指针 类型。那么传统的对象类型呢?在JAVA里已经不见了踪影! 既然没有了传统的对象类型,那么 对象指针变量 前面的也就可以不要了。对象指针变量也就可以简称为对象变量了, 反正也不会和其它概念混淆! 所有的对象变量都是指针,没有非指针的对象变量,想不用指针都不行,这就是指针的泛化和强化。 不叫指针了,就叫对象变量,这就是概念上的淡化和弱化。 没有了指针的加减运算,也没有了*、->等运算符,这是对指针的简单化。

既然清楚了Java中对象即是指针,那么我们回到现在的问题上来。

如果把一个对象赋值给一个接口,那么实际上会发生什么呢? 真的去重新开辟了块内存空间,再把原来的属性值装进这个空间吗? 不不不,对象只是指针,对象的赋值只是指针的复制而已,把对象赋值给接口也只是把这个对象的地址给这个接口而已!

那么对象实际改变了吗? 并没有! 那改变了什么呢? 改变的只是程序“解析”(这里我愿意用解析一词来形容)这个对象或者说这个指针所指向的内存空间而已! 因为“解析的格式”(或者说解析的标准),对于一些不认识的属性和方法你当然就不能使用喽!

总结

对象赋给接口只是指针而已,至于为什么不能使用原来对象中的方法和属性,当然是因为“解析”的格式不同导致程序根本不认识接口中没有的方法和属性喽!

建议

虽然Java中没有指针的概念,但是最好把它看做指针,这对于你理解底层机制或者算法结构都有很多好处,也让你避免出现诸如为什么对象复制要用clone方法之类的疑惑了。

-----8月8日更新------- 自从小小的接触了下字节码后,对这个问题有了新的理解

方法在编译器会在编译阶段就进行静态分派。指向的还是父类的类,父类里面没有test3()方法

按照这个思路,赋值给接口后,虽然指向的还是实现类,但是编译器会去找其接口(也就是它的静态类型)

详细可以去看这篇文章https://www.cnblogs.com/bigbaby/p/12348956.html

记录点滴,乐于分享,转载请注明出处 愿我们以梦为马,不负人生韶华。 我们追梦在路上! 愿与君共勉!

  • 作者:金昊霖
  • 发表时间:2020-7-04
  • 版权声明:自由转载-非商用-非衍生-保留署名(创意共享3.0许可证)
  • 评论

    测试
    测试
    测试
    <script> alert("kk"); </script>
    留言