当前位置: 首页 > news >正文

精通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

平等

⼈使⽤卡消费,卡可以提取⼈的信

Q5Object 类有哪些⽅法?

equals:检测对象是否相等,默认使⽤ == ⽐较对象引⽤,可以重写 equals ⽅法⾃定义⽐较规则。

equals ⽅法规范:⾃反性、对称性、传递性、⼀致性、对于任何⾮空引⽤ xx.equals(null) 返回

false

hashCode:散列码是由对象导出的⼀个整型值,没有规律,每个对象都有默认散列码,值由对象存储地址得出。字符串散列码由内容导出,值可能相同。为了在集合中正确使⽤,⼀般需要同时重写 equals hashCode,要求 equals 相同 hashCode 必须相同,hashCode 相同 equals 未必相同,因此hashCode 是对象相等的必要不充分条件。

toString:打印对象时默认的⽅法,如果没有重写打印的是表示对象值的⼀个字符串。

cloneclone ⽅法声明为 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 abstractJDK8 ⽀持默认/静态⽅法,JDK9 ⽀持私有⽅法。

继承

单继承

多继承

Q9:接⼝和抽象类应该怎么选择?

抽象类体现 is-a 关系,接⼝体现 can-do 关系。与接⼝相⽐,抽象类通常是对同类事物相对具体的抽象。

抽象类是模板式设计,包含⼀组具体特征,例如某汽⻋,底盘、控制电路等是抽象出来的共同特征,但内饰、显示屏、座椅材质可以根据不同级别配置存在不同实现。

接⼝是契约式设计,是开放的,定义了⽅法名、参数、返回值、抛出的异常类型,谁都可以实现它,但必须遵守接⼝的约定。例如所有⻋辆都必须实现刹⻋这种强制规范。

接⼝是顶级类,抽象类在接⼝下⾯的第⼆层,对接⼝进⾏了组合,然后实现部分接⼝。当纠结定义接⼝和抽象类时,推荐定义为接⼝,遵循接⼝隔离原则,按维度划分成多个接⼝,再利⽤抽象类去实现这些,⽅便后续的扩展和重构。

例如 Plane Bird 都有 fly ⽅法,应把 fly 定义为接⼝,⽽不是抽象类的抽象⽅法再继承,因为除了 fly

⾏为外 Plane Bird 间很难再找到其他共同特征。

Q10:⼦类初始化的顺序

① ⽗类静态代码块和静态变量。 ② ⼦类静态代码块和静态变量。 ③ ⽗类普通代码块和普通变量。 ④

⽗类构造⽅法。 ⑤ ⼦类普通代码块和普通变量。 ⑥ ⼦类构造⽅法。

最后呢,本文章的所有知识取自于B站高淇老师讲的Java300集教程,里面更加全面的讲述了关于Java面试中所能遇到的各种问题,包括解决问题的方法。小编也给大家准备了充分的资源:
https://www.bilibili.com/video/BV1qL411u7eE

 

相关文章:

  • Tcmalloc内存分配算法的分析
  • 中国按摩器行业市场需求与投资规划分析报告
  • 分布式医疗大数据存储方案研究综述
  • BOPPPS+课程思政教学模式在计算机导论课程中的应用
  • 中国冶金工程行业数据专项调研分析报告
  • mac (M系列)docker 中elasticsearch 搭建和基础使用 7.15.5版本
  • 党务管理信息系统,让组织人员架构管理更便利,操作更流畅
  • 2022年全球及中国公司秘书服务行业头部企业市场占有率及排名调研报告
  • HTML相关(四)
  • opencv parallel_for_使用及注意
  • 拿下国产高端市场第一背后,vivo与苹果、华为的共性
  • postgresql 实现变量替换框架
  • numpy在数字图像处理中的应用
  • A tour of gRPC:09 - gRPC Interceptor 拦截器
  • 【Docker】——Network
  • AngularJS指令开发(1)——参数详解
  • Effective Java 笔记(一)
  • github指令
  • golang中接口赋值与方法集
  • iOS | NSProxy
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • Java精华积累:初学者都应该搞懂的问题
  • JS+CSS实现数字滚动
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • React as a UI Runtime(五、列表)
  • React-生命周期杂记
  • Sass Day-01
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 机器学习中为什么要做归一化normalization
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 近期前端发展计划
  • 模型微调
  • 如何合理的规划jvm性能调优
  • 我的业余项目总结
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • 翻译 | The Principles of OOD 面向对象设计原则
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • 容器镜像
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #每天一道面试题# 什么是MySQL的回表查询
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • $forceUpdate()函数
  • (多级缓存)缓存同步
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (十一)c52学习之旅-动态数码管
  • (转)Linq学习笔记
  • (转)树状数组
  • .NET : 在VS2008中计算代码度量值
  • .NET delegate 委托 、 Event 事件,接口回调
  • .NET 设计一套高性能的弱事件机制
  • .NET轻量级ORM组件Dapper葵花宝典
  • /etc/shadow字段详解
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • [.net] 如何在mail的加入正文显示图片