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

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

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


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


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


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


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


这显然是不对,因此我进行了简单的测试:

q1.png

这里我们看到就算我们用接口接对象,对象依旧能够通过强转回原来的样子,而就算是接口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


---------11月13日更新----------------

随着自己技术的成长,对此问题有了更深层次的理解,所以重新写了另一篇文章如何理解子类对象赋值给父类(深入理解动态绑定、静态绑定)

相关文章
|
1月前
|
Java
【专栏】Java反射机制,该机制允许程序在运行时获取类信息、动态创建对象、调用方法和访问属性
【4月更文挑战第27天】本文探讨了Java反射机制,该机制允许程序在运行时获取类信息、动态创建对象、调用方法和访问属性。反射通过Class、Constructor、Method和Field类实现。文中列举了反射的应用场景,如动态创建对象、调用方法、访问属性和处理注解,并提供了相关实例代码演示。
|
1月前
|
编译器 数据安全/隐私保护 C++
【类与对象】封装&对象的初始化及清理
【类与对象】封装&对象的初始化及清理
|
1月前
|
存储 Java 编译器
类、对象、方法
摘要: 本文介绍了面向对象编程的概念,以京东购买手机为例,展示了如何通过分类和参数选择商品,强调软件与现实生活的对应关系。柯南三步走揭示了京东如何通过搜索和筛选帮助用户找到所需商品,而这一切背后的编程思想即为面向对象编程。面向对象编程涉及抽象、自定义类型和实例化对象等步骤,其中自定义类型(如Java中的类)用于封装现实生活中的复杂数据。文章还讲解了如何定义类、实例化对象以及访问权限修饰符、构造方法、this关键字、方法的使用,强调了方法参数和返回值在不同数据类型上的处理差异。整个讨论旨在阐明Java中面向对象编程的基本原理和实践应用。
23 5
|
1月前
|
设计模式 算法 编译器
【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
20 0
|
1月前
|
存储 C++
c++类和对象一对象特性一成员变量和成员函数分开存储
c++类和对象一对象特性一成员变量和成员函数分开存储
21 0
|
1月前
|
存储 Java
Java 类与对象(对象的分配机制、对象的创建过程、匿名对象)
Java 类与对象(对象的分配机制、对象的创建过程、匿名对象)
23 0
|
1月前
|
监控 安全 Java
Java反射:深入了解动态类操作
Java反射:深入了解动态类操作
78 0
|
8月前
|
Java 编译器
类 对象 封装
类 对象 封装
55 0
|
存储 C++ 开发者
你还不进来看看C++类与对象【7】 —— 动态多态底层原理剖析&&(纯)虚析构解决父类指针不能释放子类属性问题嘛
你还不进来看看C++类与对象【7】 —— 动态多态底层原理剖析&&(纯)虚析构解决父类指针不能释放子类属性问题嘛
113 0
你还不进来看看C++类与对象【7】 —— 动态多态底层原理剖析&&(纯)虚析构解决父类指针不能释放子类属性问题嘛
为什么说对象是类的一个实例?底层原理是什么?
为什么说对象是类的一个实例?底层原理是什么?
210 0