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

面试笔记-基础篇

什么是面向对象?

面向对象是一种编程思想,它将数据(属性)和操作数据的行为(方法)组合成一个独立个体(对象),并通过这个个体来实现程序的设计与编写。
面向对象有三大特性,封装、继承、多态。
封装: 封装是把对象的属性私有化,同时提供一些可被外界访问属性的方法;
继承: 继承是以父类为基础创建新的子类,子类可以继承父类的属性和方法,也可以增加新的属性和方法,通过继承可以很方便的代码复用;
多态: 多态是同一个行为可以有不同表现形式,不同的子类重写同一个方法可以不同的实现,可以用继承父类重写方法或实现接口重写方法来实现多态。

==和equals的区别?

==: 基本数据类型比较的值,引用数据类型比较的是内存地址,也就是判断两个对象是不是同一个对象。
equals: 不能直接用于基本数据类型比较,如果没重写时,默认0bject类方法等同于==,可以重写equals方法比较对象的值是否相等,比如String中对比的就是值。

为什么重写equals时必须重写hashCode?

为了保证equals相同的两个对象hashCode必须相同,如果只重写equals方法,可能会出现equals相同而hashCode不同的情况。
在散列集合中,是用hashCode来计算索引,如果只重写equals方法,出现了equals相同而hashCode不同的情况,数据就乱套了。

final关键字的作用?

可以用来修饰类、方法和属性。
修饰的类不能被继承;
修饰的方法不能被重写;
修饰的属性是基本类型或字符串时为常量,值无法修改;
如果是引用数据类型,数据可以改,但是指向该数据的地址引用不能改,如果这个引用数据类型是成员变量,必须赋值。

什么情况下更倾向使用抽象类而不是接口?

需要共享一些成员变量而不是常量时,抽象类可以包含字段属性,能够存储状态信息,接口只能放常量。
需要使用构造方法做一些数据初始化操作时,抽象类可以包含构造方法,可以在构造方法中初始化一些特定逻辑,或在实例化之前执行一些准备工作,而接口不能加构造方法。
最主要是设计上的考量,如果是需要建立一个有状态共享的实体或需要一个共同的构造逻辑,则更倾向于使用抽象类,如果关注点主要是定义方法签名或者常量,那么接口更为合适。

Java创建对象有哪几种方式?

new创建对象、反射创建对象、实现Cloneable接口调用clone方法创建对象、实现Serializable接口通过ObjectInputStream反序列化方式创建对象。

ArrayList与LinkedList的区别?

一般来说,ArrayList是动态数组的数据结构,查询、更新效率更高,LinkedList是双向链表的数据结构,新增和删除效率更高。
ArrayList基于数组实现,可以根据数组下标查询数据,速度较快,LinkedList基于链表实现,查询数据会根据索引判断数据属于上半部分还是下半部分,再遍历对比查找,速度较慢。
同理,更新数据是查询数据后做替换操作,因此ArrayList也会更快一些。
ArrayList增删慢,有两个原因:
首先有可能涉及扩容,数组是固定大小的,当容量已满又有新元素插入时,ArrayList的扩容是再创建一个1.5倍的新数组,再把原数组数据拷贝过去,这需要一定时间;
其次,如果是在指定索引位置插入元素,会需要把插入位置后面的元素全部往后移动,涉及移动的元素越多,则插入越慢。
删除元素同理,只是删除时是把元素往前移动。
LinkedList没有扩容操作,在插入元素或删除元素时,只需要修改前驱节点。后继节点与插入节点的指向就行,不需要移动元素。

HashMap的扩容机制?

HashMap是基于数组、链表和红黑树实现的,用于存放key值的桶数组的长度是固定的(默认16),随着数据的插入数量增加以及负载因子(默认0.75)的作用下(元素数量超过容量与负载因子的乘积),就需要扩容来存放更多的数据,在java1.8优化后,是不需要再重新计算每个元素的哈希值去分配位置,因为HashMap的初始容量是2的次幂(设置非2次幂的值会找一个最近的2次幂数),扩容后长度是原来的2倍,即新的容量也是2的次幂,那么在扩容后,元素要么在原位置,要么在原位置再移动2的次幂,也就是新索引=原索引+旧容量。
节点迁移主要逻辑:未形成链表,直接分配到新table,如果是树节点,进行节点分割,否则将链表拆成两个链表,遍历旧链表并把节点放到新链表。

HashMap先用hashCode还是equals?

HashMap的实现是通过使用哈希表(数组加上链表或红黑树)来存储键值对,当需要在HashMap中查询、插入或删除一个元素时,首先会调用键对象的hashCode方法来获取哈希码,这个哈希码用于定位键值对存储的桶的位置,然后调用键对象的equals方法来遍历比较桶中的链表或红黑树数据,只有在哈希码相同的情况下,才进行equals方法的比较,如果两个键的hashCode返回值不同,那么它们肯定不相等,先使用hashCode方法可以快速排除一些不匹配的情况。

ConcurrentHashMap实现原理?

Java8之前,ConcurrentHashMap是通过分段锁机制实现的,ConcurrentHashMap使用一个Segment数组,每个Segment都是一个HashEntry数组,且都有自己的锁,多个线程可以同时访问不同的Segment,不需要竞争同一个锁,当某个Segment的容量超过阈值会进行扩容,这个过程也不会阻塞其他Segment操作。Java8开始,ConcurrentHashMap改为使用Node数据结构加CAS操作来优化性能,ConcurrentHashMap使用一个大的Node数组,每个Node可以是一个链表或者红黑树,在插入或更新键值对时,使用CAS操作来更新Node数组,如果Node已经被其他线程修改,当前线程会重试直到成功,对于链表转红黑树操作,仍然使用Synchronized,但在粒度上更细,只锁定需要修改部分。

更多内容正在更新中…


http://www.kler.cn/a/535437.html

相关文章:

  • 芝法酱学习笔记(2.6)——flink-cdc监听mysql binlog并同步数据至elastic-search和更新redis缓存
  • 剑指 Offer II 014. 字符串中的变位词
  • 笔试-业务逻辑4
  • 云计算部署模式全面解析
  • 导入了fastjson2的依赖,但却无法使用相关API的解决方案
  • Qt展厅播放器/多媒体播放器/中控播放器/帧同步播放器/硬解播放器/监控播放器
  • 网络安全辅助系统 框架图 网络安全模块
  • Vue中的的通信方式有几种?
  • vue2+vue3 HMCXY基础入门
  • ONE NET MQTT+HTTP多端控制
  • 实际时钟(RTC)的介绍
  • Qt最新热点
  • 一个可以在浏览器console内运行的极简爬虫,可列出网页内指定关键词的所有句子。
  • pandas+openpyxl处理Excel
  • 哪个命令查看docekr 和docker compose 安装成功了
  • 规则引擎LiteFlow
  • Python----Python高级(并发编程:线程Thread,多线程,线程间通信,线程同步,线程池)
  • 尚硅谷spring框架视频教程——学习笔记二(数据库、事务、webflux)
  • [实验日志] VS Code 连接服务器上的 Python 解释器进行远程调试
  • node.js的require()
  • 低至3折,百度智能云千帆宣布全面支持DeepSeek-R1/V3调用
  • Web3.0 技术应用溯源系统建设
  • MS17-010(永恒之蓝1.0)漏洞远程控制win7系统操作实战小白通俗易懂
  • 如何使用sqlalchemy的orm模式构建表结构1对1,1对多,多对多的关系
  • 如何打造一个更友好的网站结构?
  • Vue组件开发——进阶篇