1.Java系列之基础面试题总结

1. 构造器是否可重写

首先,构造器是不能被继承的,因为每个类的类名都不相同,而构造器名称与类名相同,所以根本谈不上继承。

又由于构造器不能继承,所以就不能被重写。但是,在同一个类中,构造器是可以被重载的

2. String类能被继承吗,为什么

不可以,因为String类有final,而final修饰的类是不能被继承的

3. String,StringBuffer,StringBuilder的区别
  • String:不可变,每次对String进行操作都会产生新对象,效率低且浪费内存空间
  • StringBuffer: 可变字符序列,效率低,线程安全
  • StringBuilder: 可变字符序列,效率高,线程不安全

StringBuilder、 StringBuffer继承AbstractStringBuilder,无参数默认初始容量为16,
追加字符串的时候长度超过16则扩容:增加自身长度一倍再加2,如果还放不下,则扩容为所需长度minCapacity

private int newCapacity(int minCapacity) {
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
}       
4. 线程池五元组了解吗

线程池五元组指的是在使用线程池时,每个线程都需要维护的五个基本信息,包括线程所属的进程ID(PID)、线程ID(TID)、线程所监听的端口号(PORT)、线程状态和任务队列等信息。

其中,PID是进程ID,用于唯一标识一个进程,是操作系统分配给进程的一个唯一标识符;TID是线程ID,用于唯一标识一个线程,是操作系统分配给线程的一个唯一标识符;PORT是端口号,用于标识一个网络连接,不同的线程可以监听同一个端口号,通过不同的TID进行区分;线程状态是线程当前的运行状态,包括空闲、忙碌、等待等状态;任务队列则是线程池中用于存放待执行任务的队列。

维护这些信息可以让线程池更加高效地管理线程,提高线程的复用率,避免了频繁创建和销毁线程的开销,从而提高程序的性能

5. IO模型有哪些,讲讲你理解的nio,bio,aio的区别是啥,谈谈reactor模型

在计算机网络编程中,常用的IO模型主要有阻塞IO(Blocking IO,BIO)、非阻塞IO(Non-Blocking IO,NIO)、多路复用IO(Multiplexing IO,MIO)和异步IO(Asynchronous IO,AIO)。

  • 阻塞IO(BIO):线程会一直阻塞等待直到IO操作完成,期间无法处理其他任务。这种模型适用于并发性较低、并发请求处理较慢的场景。
  • 非阻塞IO(NIO):线程不会阻塞等待IO操作完成,而是通过轮询IO状态来判断是否就绪,如果未就绪则可以处理其他任务。但这种方式需要一直轮询,会增加CPU的负担。
  • 多路复用IO(MIO):通过一个线程处理多个IO请求,典型的实现方式有select、poll、epoll等。这种方式可以有效地减少CPU的负担,但同时也会存在性能瓶颈。
  • 异步IO(AIO):线程发起IO操作后可以立即返回继续执行其他任务,IO操作完成后再回调通知线程。这种方式适用于并发请求较多、并发处理速度较快的场景。

在Java中,常用的IO模型有BIO、NIO和AIO,其中:

  • BIO:Java标准IO模型,使用阻塞IO方式,适用于并发性较低、并发请求处理较慢的场景。
  • NIO:Java New IO模型,使用多路复用IO方式,适用于并发请求数较多、请求处理速度较快的场景。相较于BIO,NIO可以更好地处理高并发请求。
  • AIO:Java Asynchronous IO模型,使用异步IO方式,适用于需要处理大量IO请求的场景。相较于NIO,AIO的效率更高,能够更好地利用CPU资源。

Reactor模式是一种基于事件驱动的IO模型,它使用一个单独的线程来接收和分发事件,而不是为每个连接分配一个线程。当有新的连接到来时,Reactor线程会将其加入到一个事件队列中,然后通过一个或多个IO线程来处理队列中的事件。这种模型可以有效地减少线程的数量,提高系统的并发性和可伸缩性。在Java中,NIO使用的Selector就是一种Reactor模式的实现

6. 介绍下常用的Map
  • TreeMap:基于红黑树实现,实现SortedMap接口,默认升序排序
  • HashMap:基于哈希表实现
  • HashTable:和 HashMap 类似,但它是线程安全的。它是遗留类,不应该去使用它,而是使用 ConcurrentHashMap 来支持线程安全
  • LinkedHashMap:使用双向链表来维护元素的顺序,顺序为插入顺序或者最近最少使用(LRU)顺序
6.1 为什么HashMap是非线程安全的?什么情况下会出现线程安全问题?

HashMap会进行resize操作,在resize操作的时候会造成线程不安全
1)put的时候多线程导致数据不一致
2)get操作可能因为resize而引起死循环(cpu100%)

6.2 JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计

Segment继承ReentrantLock,每个锁控制一段,当每个Segment越来越大时,锁定粒度则变大,性能会下降
ConcurrentHashMap底层采用数组+链表+红黑树,大量采用CAS操作,加锁采用synchronized,只对桶的头节点进行加锁,粒度较小。

减少内存开销。如果采用ReentrantLock需要节点继承AQS来获得同步支持,增加内存开销,
内部优化。synchronized是由JVM直接支持的,JVM能够在运行时做相应优化如,锁粗化、锁消除、锁自旋等

6.3 有没有顺序的Map实现类,如果有,他们是怎么保证有序的

TreeMap和LinkedHashMap有序的(TreeMap默认升序,LinkedHashMap记录插入的顺序)
TreeMap是基于比较器Comparator实现有序的,LinkedHashMap是基于链表实现数据插入有序的

6.4 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。

HashMap、ConcurrentHashMap、TreeMap、 LinkedHashMap

HashMap线程不安全,由数组(Node数组)+链表+红黑树(链表长度大于8转换为红黑树)实现,采用hash表来存储,key采用hashcode,数量超过threshold时进行2倍扩容,默认容量16,负载因子0.75,桶的数量11,
采用链地址法解决hash冲突,简单来说,就是数组加链表的结合。在每个数组元素上都一个链表结构,当数据被Hash后,得到数组下标,把数据放在对应下标元素的链表上
Java 8系列之重新认识HashMap

大量采用CAS操作,JDK1.7对Segment进行加锁,JDK1.8对桶中的头结点进行加锁
ConcurrentHashMap的实现原理

TreeMap和LinkedHashMap有序的(TreeMap默认升序,LinkedHashMap记录插入的顺序)

7. JAVA中的几种基本数据类型是什么,各自占用多少字节。
数据类型字节默认值
byte10
short20
char2‘\u0000’
int40
float40.0f
long80
double80.0d
boolean4false

PS: JVM规范中,boolean当做int处理,也就是4字节,而boolean数组当做byte数组处理,即boolean类型的数组里面每一个元素占一个字节

8. ArrayList和LinkedList有什么区别
  • ArrayList: 基于数组实现的非线程安全的集合。查询速度快,插入、删除中间元素速度慢
  • LinkedList: 基于链表实现的非线程安全的集合。查询速度慢,插入、删除中间元素快
  • Vector: 基于数组实现的线程安全的集合。采用synchronize加锁,性能比ArrayList差
  • CopyOnWriteArrayList: 基于数组实现的线程安全的写时复制集合,采用ReentrantLock加锁,性能比Vector高,适合读多写少的场景
9. 讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序。

父类静态变量
父类静态代码块
子类静态变量
子类静态代码块

父类非静态变量(父类实例成员变量)
父类构造函数
子类非静态变量(子类实例成员变量)
子类构造函数

10. 抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么
  • 接口只能做方法声明,抽象类既可以做方法声明也可以做方法实现
  • 接口里定义的变量只能是公共的静态常量,抽象类中变量是普通变量
  • 抽象类里可以没有抽象类,如果一个类中有抽象方法,则一定是抽象类
  • 抽象方法要被实现,所以不能是静态的,也不能是私有的
  • 接口继承接口,并可多继承接口,但类只能单继承

类不能继承多个类
接口可以继承多个接口
类可以实现多个接口

11. 继承、组合、聚合有什么区别

继承: is-a的关系,指一个类继承另一个类 public class A extends B{}
组合:contains-a,强聚合,A一定有B public class A {B b}
聚合:has-a, A可以有B public class A {List<B> b}

12. 请结合OO设计理念,谈谈访问修饰符public、private、protected、default在应用设计中的作用。

OO设计理念:封装、继承、多态

关键字类内部本包子类外部包
public
protected×
default××
private×××
13. 这样的a.hashcode() 有什么用,与a.equals(b)有什么关系

hashcode()提供了对象的hashcode值,是一个native函数,返回的默认值与System.identityHashCode(obj)一致
作用是用一个数字标识对象,比如HashMap中的key就是基于hashcode, hashcode只能说是标识对象,在hash算法中可以将对象相对离散些,但不是唯一的,根据hashcode定位到具体的链表后,需要遍历链表,然后通过equals()方法来对比key是否是一致的。
equals相等的两个对象,hashcode一定相等;hashcode相等的两个对象不一定equals相等

14. 有没有可能2个不相等的对象有相同的hashcode

有。同13

15. 深拷贝和浅拷贝区别

如果一个对象内部只有基本数据类型,那么clone()方法获取到的就是这个对象的深拷贝,而如果其内部还有引用数据类型,那么clone()方法:

浅拷贝 对基本数据类型进行值拷贝,对引用数据类型进行引用传递般的拷贝,此为浅拷贝
深拷贝 对基本数据类型进行值拷贝,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝

  • 序列化反序列化实现
  • clone方法 对其内部引用类型的变量,在进行一次clone

欢迎关注公众号算法小生

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法小生Đ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值