1.什么是面向对象?
依据化约论,将想描述的具体对象分割成若干特征字段的集合,即为对象。换种说法,就是把一个具体的对象抽象出你需要的具体属性加以描述,即为对象。
举个例子:猫
我们可以抽象成的对象如下:
{名称:猫;脚的数量:4;有无尾巴:有;叫声:喵},虽然很简陋,有太多的细节我们舍弃了,但得到的这个描述集合就是我们定义的名为“猫”的对象。
而在程序中,不同的对象之间通过消息传递进行相互作用,实现程序的运行。
面向过程的编程=数据+算法,面向对象的编程=对象+消息。
2.面向对象三大基本特征
封装、继承、多态
封装:利用抽象数据类型将数据和基于数据的操作聚合在一起,使其构成一个不可分割的独立实体(对象)
继承:继承实现了 IS-A 关系,可以理解为A继承B,A是B的一个子集,B所具有全部非私有特征,A也全部具备
多态:多态分为编译时多态和运行时多态。编译时多态主要指方法的覆盖与重载,运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定。
3.面向对象五大基本原则
单一职责原则(SRP):一个类应该仅有一个引起它变化的原因
开放封闭原则(OCP) :对扩展是开放的,对更改是封闭的
里氏替换原则(LSP) :子类可以替换父类并且出现在父类能够出现的任何地方
依赖倒置原则(DIP) :传统的结构化编程中,最上层的模块通常都要依赖下面的子模块来实现,也称为高层依赖低层!
所以DIP原则就是要逆转这种依赖关系,让高层模块不要依赖低层模块
接口隔离原则(ISP):使用多个专门的接口比使用单个接口要好的多
4.java如何实现平台无关性?
java程序可以编译成格式名为class的二进制文件/字节码文件,这些文件可以通过基于不同操作系统/运行环境中的jvm解析为特定平台的操作指令,实现在不同平台的运行。
5.jvm支持语言
kotlin
groovy
jruby
Jython
Scala
6.值传递与引用传递
值传递:面向对象程序中传递的消息是一个具体的值,传递的时候是进行了对象的复制。一个参数的值改变,不会造成对象中其他参数的值改变。
引用传递:面向对象程序中传递的消息是一个内存地址,修改后对应对象会发生改变,传递的时候只是同一对象的内存首地址,没有对对象进行完全的复制。一个参数的值改变,会造成对象中其他参数的值改变。(具体可以参考c语言 一个对象开辟空间后,内存首地址变动,导致对象里面所有参数都发生了变化)
值传递和引用传递的区别并不是传递的内容。而是实参到底有没有被复制一份给形参
7.为什么说java只有值传递?
https://www.cnblogs.com/wchxj/p/8729503.html
要点:
1.我们以为的传对象就是引用传递是错误的,这个是值传递,传递的是复制后的对象的内存首地址
2.造成我们错误理解的:修改对象中的参数,好像是对这个对象进行了修改,实际上还是通过值传递,将一个新的参数复制并修改了了对象中对应参数所指向内存空间的存储内容。
http://www.yinwang.org/blog-cn/2016/06/08/java-value-type 搭配这个阅读,会有更加深入的了解
8.什么是多态、方法重写与重载
多态是指父类型的引用指向子类型的对象。用一句比较通俗的话:同一操作作用于不同的对象,可以产生不同的效果。
方法重写:子类继承父类后对,父类已经实现的方法进行覆盖,重新编写该方法的功能
格式特点:
1.方法名、参数列表必须完全一致
2.返回类型可以相同,也可以不同,不同必须是原来返回类型的子类型(可隐式转换即可)JAVA近期版本的新特性,在之前子类返回值类型必须和父类返回值类型保持一致
2.子类抛出的异常下不能超过父类相应方法抛出的异常(子类异常不能大于父类异常)
3.子类方法的访问级别不能低于父类相应方法的访问级别(子类访问级别不能低于父类访问级别)
方法重载:同一类中,同名方法通过不同入参申明为另一种方法,区别于其他同名方法
格式特点:
1.方法名相同。
2.方法的参数表必须不同
如果参数个数不同,就不管它的参数类型了!
如果参数个数相同,那么参数的类型必须不同。
3.方法的返回类型、修饰符可以相同,也可不同。
9.java的继承与实现
java只支持单继承,但可以实现多个接口
子类通过super调用父类方法
new子类时,会默认调用父类的无参构造方法
向上类型转换:父类变量可以直接接受子类的对象,子类变量接受父类对象需进行强转(强转时的赋值机制?)
方法可见性重写:子类必须支持父类所有的对外方法。重写时,子类的方法不能降低父类方法的可见性:如果父类中方法为public的,那么子类中的方法也必须为public的;如果父类中的方法为protected的,那么子类中的方法可以为protected,也可以为public
final修饰类,表示该类不能被继承;final修饰非final中的方法,表示该方法不能在子类中被重写(待验证?)
(使用final修饰方法的两个好处:(1)防止方法被覆盖;(2)关闭java中的动态绑定)。
建议:优先使用组合而非继承
java方法的动态绑定与静态绑定:
绑定:将一个方法的调用与方法所在的类(方法主体)关联起来。即决定调用哪个方法和变量。
静态绑定:在编译过程中就已经知道这个方法到底是哪个类中的方法
java当中的方法只有final、static、private修饰的的方法和构造方法是静态绑定的。
static修饰的方法:可以被子类继承,但是不能被子类重写(覆盖),但是可以被子类隐藏。(待验证?)
(子类对象转换成父类对象后,能够访问父类被隐藏的变量和方法,而不能访问父类被覆盖的方法)
动态绑定:在运行时期根据具体对象的类型进行绑定。
动态绑定的过程:
1.虚拟机提取对象实际类型的方法表
2.虚拟机搜索方法签名
3.调用方法
java中重载的方法使用静态绑定(存疑),重写的方法使用动态绑定。
10.构造函数与默认构造函数
构造函数:即创建对象时调用的方法,可以指定不同的入参作为初始化对象的赋值来源,但构造函数方法名称必须与类同名
默认构造函数:不进行显式创建,默认是无参的构造函数
11.类变量、成员变量与局部变量
类变量:在类中申明的成员变量,存储在堆中
成员变量:类中用于存储指定参数的内容的变量
局部变量:方法中用于临时计算承载参数的过渡变量,存储在栈中
12.成员变量和方法作用域
成员变量:
public static申明的对象可全工程直接通过类进行调用
public 申明的对象,可在对象初始化之后,通过对象直接调用
其他申明的对象只能通过对象方法获取
方法中申明的局部变量将随着方法{}作用域的结束而结束