Java基础面试

本文详细讲解了Java中的接口和抽象类的区别,以及List、Set、Map的特性和实现类,包括HashMap的实现原理。此外,还涵盖了JVM、多线程同步、异常处理、单例模式、基本数据类型和网络IO模型(BIO、NIO、AIO)以及泛型的概念。
摘要由CSDN通过智能技术生成
1.接口和抽象类的区别

1.抽象类只能通过子类使用extends继承来实现,接口使用implements关键字来实现

2.抽象类可以有main函数,但是我们不能使用,接口没有main函数

3.抽象类有构造方法,接口没有构造方法

4.一个类可以实现多个接口,但是只能继承一个抽象类

2.List、Set、Map的区别

1.List、Set都是继承Collection的接口,他们都是单列集合。List接口允许元素重复且有序,Set接口不允许元素重复,且没有顺序(因为其通常维护自己内部的顺序,eg:HashSet是通过哈希表、TreeSet是通过红黑树来维护自己的内部顺序,所有对set随机访问是没有任何意义的)

2.Map是储存键值对(key-value)的双列集合。key和value是一一对应的关系,key值不能相同,value值可以相同,不允许元素重复(原因和set一样,下面的实现类会解释)

3.List的实现类是ArrayList、LinkedList、Vector、Stack。Set的实现类是HashSet、TreeSet、LinkedHashSet。Map的实现类是HashMap、HashTable、TreeMap

3.List、Set、Map的实现类
List的实现类是ArrayList、LinkedList、Vector、Stack

ArrayList:ArrayList是一个动态数组,是我们最常用的集合,它允许任何符合规则的元素插入,甚至包括NULL。每一个ArrayList都有一个初始长度10,当到达10会进行扩容,扩容之后的长度是原来的1.5倍。ArrayList擅长查找元素,不擅长删除和插入操作,ArrayList是非同步的,所以线程不安全。

LinkedList:LinkedList是一个双向链表,他除了满足ArrayList基本操作方法还提供了get、insert、remove方法在双向链表的头部和尾部。由于实现方式不同,LinkedList所有操作都需要从头遍历,因此其更擅长删除和插入操作,不擅长查找元素。LinkedList是非同步的,所以线程不安全。

Vector:与ArrayList相似,可以理解为线程安全的ArrayList

Stack:继承于Vector,实现了一个先进后出的栈。提供了push(进栈)pop(出栈) research (查找栈内元素)peek(查看栈顶元素) empty(判断栈内元素是否为空)操作

Set的实现类是HashSet、TreeSet、LinkedHashSet

HashSet:堪称查询速度最快的集合,是基于哈希表实现的,其内部是由HashCode决定的,元素允许为NULL,但是只能有一个,由于它是由HashCode决定顺序的,因此他不能保证set的迭代顺序。

TreeSet:是基于红黑树(平衡的二叉搜索树)实现的。元素有序,不允许为NULL

LinkedHashSet:是基于哈希表和双线链表实现的。哈希表用来存储元素,双向链表用于管理元素顺序,使元素看起来像是根据插入顺序存储的。根据元素添加顺序遍历该集合。

Map的实现类是HashMap、HashTable、TreeMap

HashMap:通过哈希表实现的(重点了解一下HashMap的实现原理),高效,支持NULL值和NULL键,线程不安全。

HashTable:线程安全,低效,不支持NULL值和NULL键。

LinkedHashMap:线程不安全,是HashMap的子类,保存了记录的插入顺序。

TreeMap:线程不安全,能够把它保存的记录根据键排序,默认是键值的升序排序。

4.说一下HashMap的实现原理

1.底层使用哈希表数据结构,即数组+链表+(红黑树)

jdk1.8之前使用拉链法(数组+链表)jdk1.8之后采用数组+链表+红黑树,当链表长度大于8且数组长度大于64,则从链表转化为红黑树

2.添加数据时,计算key值确定元素在数组的下标,key相同则替换,不同则存入链表或红黑树中,获取数据通过key的hash计算数组下标获取元素。

5.JDK、JRE、JVM的区别

jdk是Java开发工具包,包含了Java的开发环境和运行环境

JRE是Java运行环境

JVM是Java虚拟机,Java多平台运行就是通过JVM实现的

6.重载和重写的区别

重载:即在一个类中,方法名必须相同,参数列表和返回值可以不同

重写:子类重写父类的方法,方法名必须相同,参数列表和返回值必须相同

7.String、StringBuffer、StringBuilder的区别

String:是通过final修饰的,字符串常量(线程安全)

StringBuffer:字符串变量(对方法或者调用的方法加了同步锁,所以线程安全)

StringBuilder:字符串变量(没有对方法加同步锁,所以线程不安全)

如果操作少量数据使用String

如果操作单线程字符串缓冲区下的大量数据应该使用StringBuilder

如果操作多线程字符串缓冲区下的大量数据应该使用StringBuffer

8.Java中==和equals的区别

==:在基本数据类型比较的是值,在引用数据类型的比较时比较的是内存存放的地址

equals:默认比较的是内存存放的地址,但是可以对其进行重写

9.同步锁、死锁、乐观锁、悲观锁

同步锁:当多个线程同时访问同一个数据时,很容易出现问题。为了避免这种情况的发生,我们要保证线程互斥,就是指并发执行的多个线程,在同一时间内只允许一个线程访问共享数据。java中使用synchronized关键字来取得一个对象的同步锁

死锁:多个线程同时被堵塞,他们中的一个或多个都在等待资源的释放

乐观锁:总是假设最好的情况,即每次去拿数据都认为数据没有发生变化,但是在更新的时候需要判断一下在此期间这个数据是否被修改。使用版本号机制和CAS算法来实现

悲观锁:总是假设最坏的情况,即每次去拿数据都认为数据发生了变化,因此每次去拿数据的时候都要加锁,这样当别人想要拿数据就会被堵塞。

10.Java异常

Throwable是所有Java程序中错误处理的父类,其有两个子类:Error、Exception

Error:这是由JVM检测到的无法预期的错误,是属于JVM层次的严重错误,因此无法捕获只能抛出异常,且无法采取任何恢复操作

Exception:

1)运行时异常:都是RuntimeException类及其子类异常。eg:NullPioneerException空指针异常、IndexOutOfBounds下标越界异常。这些异常都属于不检查异常,程序可以选择捕获处理也可以选择不处理,这是逻辑错误引起的,因此在逻辑角度应该尽可能避免这些错误。运行时Java编译器不会去检查它,即使没有使用try…catch捕获它或throws语句抛出它,程序也会编译通过。

2)编译异常:除RuntimeException之外的异常,属于Exception的子类,这类异常必须处理,如果不处理,则不会编译通过。eg:IOEException、SQLException以及自定义异常

11.什么是单例模式

即类的实例在多线程环境下只被创建一次

饿汉式单例模式:一开始初始化,线程安全

懒汉式单例模式:延迟初始化,线程不安全

双检锁单例模式:延迟初始化,线程安全

12.Java基本数据类型

整型:byte int short long 

浮点型:float double

布尔型:boolean

字符型:char

13.BIO、NIO、AIO的区别

BIO:BlockIO,同步阻塞式IO,就是我们平常使用的传统IO,特点是模式简单,使用方便,并发处理能力低

NIO:NewIO,同步非阻塞IO,是传统IO的升级,客户端和服务器端通过channel(通道)通讯实现了多路复用

AIO:AsynchronousIO,是NIO的升级,也叫NIO2,实现了异步非阻塞IO,异步IO的操作基于事件和回调机制

14.泛型

泛型,即参数化类型,解决不确定对象具体类型的问题。Java编译器生成的字节码是不包含泛型信息的,泛型类型信息在编译过程会被擦除,这个过程就叫做泛型擦除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值