精通Java必备的100道面试题——面向对象面试题
Q1:谈⼀谈你对⾯向对象的理解
⾯向过程让计算机有步骤地顺序做⼀件事,是过程化思维,使⽤⾯向过程语⾔开发⼤型项⽬,软件复⽤和维护存在很⼤问题,模块之间耦合严重。⾯向对象相对⾯向过程更适合解决规模较⼤的问题,可以拆解问题复杂度,对现实事物进⾏抽象并映射为开发对象,更接近⼈的思维。
例如开⻔这个动作,⾯向过程是 open(Door door),动宾结构,door 作为操作对象的参数传⼊⽅法,⽅法内定义开⻔的具体步骤。⾯向对象的⽅式⾸先会定义⼀个类Door,抽象出⻔的属性(如尺⼨、颜⾊)和⾏为(如 open 和 close),主谓结构。
⾯向过程代码松散,强调流程化解决问题。⾯向对象代码强调⾼内聚、低耦合,先抽象模型定义共性⾏为,再解决实际问题。
Q2:⾯向对象的三⼤特性?
封装是对象功能内聚的表现形式,在抽象基础上决定信息是否公开及公开等级,核⼼问题是以什么⽅式暴漏哪些信息。主要任务是对属性、数据、敏感⾏为实现隐藏,对属性的访问和修改必须通过公共接⼝实现。封装使对象关系变得简单,降低了代码耦合度,⽅便维护。
迪⽶特原则就是对封装的要求,即 A 模块使⽤ B 模块的某接⼝⾏为,对 B 模块中除此⾏为外的其他信息知道得应尽可能少。不直接对 public 属性进⾏读取和修改⽽使⽤ getter/setter ⽅法是因为假设想在修改属性时进⾏权限控制、⽇志记录等操作,在直接访问属性的情况下⽆法实现。如果将 public 的属性和⾏为修改为 private ⼀般依赖模块都会报错,因此不知道使⽤哪种权限时应优先使⽤ private。
继承⽤来扩展⼀个类,⼦类可继承⽗类的部分属性和⾏为使模块具有复⽤性。继承是"is-a"关系,可⽤⾥⽒替换原则判断是否满⾜"is-a"关系,即任何⽗类出现的地⽅⼦类都可以出现。如果⽗类引⽤直接使⽤⼦类引⽤来代替且可以正确编译并执⾏,输出结果符合⼦类场景预期,那么说明两个类符合⾥⽒替换原则。
多态以封装和继承为基础,根据运⾏时对象实际类型使同⼀⾏为具有不同表现形式。多态指在编译层⾯⽆法确定最终调⽤的⽅法体,在运⾏期由 JVM 动态绑定,调⽤合适的重写⽅法。由于重载属于静态绑定,本质上重载结果是完全不同的⽅法,因此多态⼀般专指重写。
Q3:重载和重写的区别?
重载指⽅法名称相同,但参数类型个数不同,是⾏为⽔平⽅向不同实现。对编译器来说,⽅法名称和参数列表组成了⼀个唯⼀键,称为⽅法签名,JVM 通过⽅法签名决定调⽤哪种重载⽅法。不管继承关系如何复杂,重载在编译时可以根据规则知道调⽤哪种⽬标⽅法,因此属于静态绑定。
JVM 在重载⽅法中选择合适⽅法的顺序: ① 精确匹配。 ② 基本数据类型⾃动转换成更⼤表示范围。 ③⾃动拆箱与装箱。 ④ ⼦类向上转型。 ⑤ 可变参数。
重写指⼦类实现接⼝或继承⽗类时,保持⽅法签名完全相同,实现不同⽅法体,是⾏为垂直⽅向不同实现。
元空间有⼀个⽅法表保存⽅法信息,如果⼦类重写了⽗类的⽅法,则⽅法表中的⽅法引⽤会指向⼦类实 现。⽗类引⽤执⾏⼦类⽅法时⽆法调⽤⼦类存在⽽⽗类不存在的⽅法。
重写⽅法访问权限不能变⼩,返回类型和抛出的异常类型不能变⼤,必须加 @Override 。
Q4:类之间有哪些关系?
类关系 | 描述 | 权⼒强侧 | 举例 |
继承 | ⽗⼦类之间的关系:is-a | ⽗类 | ⼩狗继承于动物 |
实现 | 接⼝和实现类之间的关系:can- do | 接⼝ | ⼩狗实现了狗叫接⼝ |
组合 | ⽐聚合更强的关系:contains-a | 整体 | 头是身体的⼀部分 |
聚合 | 暂时组装的关系:has-a | 组装⽅ | ⼩狗和绳⼦是暂时的聚合关系 |
依赖 | ⼀个类⽤到另⼀个:depends-a | 被依赖 ⽅ | ⼈养⼩狗,⼈依赖于⼩狗 |
关联 | 平等的使⽤关系:links-a | 平等 | ⼈使⽤卡消费,卡可以提取⼈的信息 |
Q5:Object 类有哪些⽅法?
equals:检测对象是否相等,默认使⽤ == ⽐较对象引⽤,可以重写 equals ⽅法⾃定义⽐较规则。
equals ⽅法规范:⾃反性、对称性、传递性、⼀致性、对于任何⾮空引⽤ x,x.equals(null) 返回
false。
hashCode:散列码是由对象导出的⼀个整型值,没有规律,每个对象都有默认散列码,值由对象存储地址得出。字符串散列码由内容导出,值可能相同。为了在集合中正确使⽤,⼀般需要同时重写 equals 和 hashCode,要求 equals 相同 hashCode 必须相同,hashCode 相同 equals 未必相同,因此hashCode 是对象相等的必要不充分条件。
toString:打印对象时默认的⽅法,如果没有重写打印的是表示对象值的⼀个字符串。
clone:clone ⽅法声明为 protected,类只能通过该⽅法克隆它⾃⼰的对象,如果希望其他类也能调⽤该⽅法必须定义该⽅法为 public。如果⼀个对象的类没有实现 Cloneable 接⼝,该对象调⽤ clone ⽅抛出⼀个 CloneNotSupport 异常。默认的 clone ⽅法是浅拷⻉,⼀般重写 clone ⽅法需要实现
Cloneable 接⼝并指定访问修饰符为 public。
finalize:确定⼀个对象死亡⾄少要经过两次标记,如果对象在可达性分析后发现没有与 GC Roots 连接的引⽤链会被第⼀次标记,随后进⾏⼀次筛选,条件是对象是否有必要执⾏ finalize ⽅法。假如对象没有重写该⽅法或⽅法已被虚拟机调⽤,都视为没有必要执⾏。如果有必要执⾏,对象会被放置在 F-Queue 队列,由⼀条低调度优先级的 Finalizer 线程去执⾏。虚拟机会触发该⽅法但不保证会结束,这是为了防⽌某个对象的 finalize ⽅法执⾏缓慢或发⽣死循环。只要对象在 finalize ⽅法中重新与引⽤链上的对象建⽴关联就会在第⼆次标记时被移出回收集合。由于运⾏代价⾼昂且⽆法保证调⽤顺序,在JDK 9 被标记为过时⽅法,并不适合释放资源。
getClass:返回包含对象信息的类对象。
wait / notify / notifyAll:阻塞或唤醒持有该对象锁的线程。
Q6:内部类的作⽤是什么,有哪些分类?
内部类可对同⼀包中其他类隐藏,内部类⽅法可以访问定义这个内部类的作⽤域中的数据,包括
private 数据。
内部类是⼀个编译器现象,与虚拟机⽆关。编译器会把内部类转换成常规的类⽂件,⽤ $ 分隔外部类名与内部类名,其中匿名内部类使⽤数字编号,虚拟机对此⼀⽆所知。
静态内部类:属于外部类,只加载⼀次。作⽤域仅在包内,可通过 外部类名.内部类名 直接访问,类内只能访问外部类所有静态属性和⽅法。HashMap 的 Node 节点,ReentrantLock 中的 Sync 类,ArrayList 的 SubList 都是静态内部类。内部类中还可以定义内部类,如 ThreadLoacl 静态内部类
ThreadLoaclMap 中定义了内部类 Entry。
成员内部类:属于外部类的每个对象,随对象⼀起加载。不可以定义静态成员和⽅法,可访问外部类的所有内容。
局部内部类:定义在⽅法内,不能声明访问修饰符,只能定义实例成员变量和实例⽅法,作⽤范围仅在声明类的代码块中。
匿名内部类:只⽤⼀次的没有名字的类,可以简化代码,创建的对象类型相当于 new 的类的⼦类类型。⽤于实现事件监听和其他回调。
Q7:访问权限控制符有哪些?
访问权限控制符 | 本类 | 包内 | 包外⼦类 | 任何地⽅ |
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
⽆ | √ | √ | × | × |
private | √ | × | × | × |
Q8:接⼝和抽象类的异同?
接⼝和抽象类对实体类进⾏更⾼层次的抽象,仅定义公共⾏为和特征。
语法维度 | 抽象类 | 接⼝ |
成员变量 | ⽆特殊要求 | 默认 public static final 常量 |
构造 ⽅法 | 有构造⽅法,不能实例化 | 没有构造⽅法,不能实例化 |
⽅法 | 抽象类可以没有抽象⽅法,但有抽象 ⽅法⼀定是抽象类。 | 默认 public abstract,JDK8 ⽀持默认/静态⽅法,JDK9 ⽀持私有⽅法。 |
继承 | 单继承 | 多继承 |
Q9:接⼝和抽象类应该怎么选择?
抽象类体现 is-a 关系,接⼝体现 can-do 关系。与接⼝相⽐,抽象类通常是对同类事物相对具体的抽象。
抽象类是模板式设计,包含⼀组具体特征,例如某汽⻋,底盘、控制电路等是抽象出来的共同特征,但内饰、显示屏、座椅材质可以根据不同级别配置存在不同实现。
接⼝是契约式设计,是开放的,定义了⽅法名、参数、返回值、抛出的异常类型,谁都可以实现它,但必须遵守接⼝的约定。例如所有⻋辆都必须实现刹⻋这种强制规范。
接⼝是顶级类,抽象类在接⼝下⾯的第⼆层,对接⼝进⾏了组合,然后实现部分接⼝。当纠结定义接⼝和抽象类时,推荐定义为接⼝,遵循接⼝隔离原则,按维度划分成多个接⼝,再利⽤抽象类去实现这些,⽅便后续的扩展和重构。
例如 Plane 和 Bird 都有 fly ⽅法,应把 fly 定义为接⼝,⽽不是抽象类的抽象⽅法再继承,因为除了 fly
⾏为外 Plane 和 Bird 间很难再找到其他共同特征。
Q10:⼦类初始化的顺序
① ⽗类静态代码块和静态变量。 ② ⼦类静态代码块和静态变量。 ③ ⽗类普通代码块和普通变量。 ④
⽗类构造⽅法。 ⑤ ⼦类普通代码块和普通变量。 ⑥ ⼦类构造⽅法。
最后呢,本文章的所有知识取自于B站高淇老师讲的Java300集教程,里面更加全面的讲述了关于Java面试中所能遇到的各种问题,包括解决问题的方法。小编也给大家准备了充分的资源:
https://www.bilibili.com/video/BV1qL411u7eE