最近面试的小伙伴不少,对此我整理了一份Java面试题手册:基础知识、JavaOOP、Java集合/泛型面试题、Java异常面试题、Java中的IO与NIO面试题、Java反射、Java序列化、Java注解、多线程&并发、JVM、Mysql、Redis、Memcached、MongoDB、Spring、SpringBoot、SpringCloud、RabbitMQ、Dubbo、MyBatis、ZooKeeper、数据结构、算法、Elasticsearch、Kafka、微服务、Linux等等。
能够分享给你们学习。【持续更新中】java
完整版Java面试题地址:【2021最新版】Java面试真题汇总mysql
序号 | 内容 | 地址连接 |
---|---|---|
1 | 【2021最新版】JavaOOP面试题总结 | http://www.noobyard.com/article/p-rncfmibs-oe.html |
2 | 【2021最新版】多线程&并发面试题总结 | 未更新 |
3 | 【2021最新版】JVM面试题总结 | 未更新 |
4 | 【2021最新版】Mysql面试题总结 | 未更新 |
5 | 【2021最新版】Redis面试题总结 | 未更新 |
6 | 【2021最新版】Memcached面试题总结 | 未更新 |
7 | 【2021最新版】MongoDB面试题总结 | 未更新 |
8 | 【2021最新版】Spring面试题总结 | 未更新 |
9 | 【2021最新版】Spring Boot面试题总结 | 未更新 |
10 | 【2021最新版】Spring Cloud面试题总结 | 未更新 |
11 | 【2021最新版】RabbitMQ面试题总结 | 未更新 |
12 | 【2021最新版】Dubbo面试题总结 | 未更新 |
13 | 【2021最新版】MyBatis面试题总结 | 未更新 |
14 | 【2021最新版】ZooKeeper面试题总结 | 未更新 |
15 | 【2021最新版】数据结构面试题总结 | 未更新 |
16 | 【2021最新版】算法面试题总结 | 未更新 |
17 | 【2021最新版】Elasticsearch面试题总结 | 未更新 |
18 | 【2021最新版】Kafka面试题总结 | 未更新 |
19 | 【2021最新版】微服务面试题总结 | 未更新 |
20 | 【2021最新版】Linux面试题总结 | 未更新 |
答: Array(数组)是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的。web
Array获取数据的时间复杂度是O(1),可是要删除数据倒是开销很大,由于这须要重排数组中的全部数据,(由于删除数据之后,须要把后面全部的数据前移)面试
缺点:数组初始化必须指定初始化的长度,不然报错。算法
例如:sql
int[] a = new int[4];//推荐使用int[] 这种方式初始化 int c[] = { 23,43,56,78};//长度:4,索引范围:[0,3]
List—是一个有序的集合,能够包含重复的元素,提供了按索引访问的方式,它继承Collection。数组
List有两个重要的实现类:ArrayList和LinkedList。安全
ArrayList:能够看做是可以自动增加容量的数组。网络
ArrayList的toArray方法返回一个数组。数据结构
ArrayList的asList方法返回一个列表。
ArrayList底层的实现是Array,数组扩容实现。
LinkList是一个双链表,在添加和删除元素时具备比ArrayList更好的性能,但在get与set方面弱于ArrayList。固然,这些对比都是指数据量很大或者操做很频繁。
答:
一、二者父类不一样
HashMap是继承自AbstractMap类,而Hashtable是继承自Dictionary类。不过它们都实现了同时实现了map、Cloneable(可复制)、Serializable(可序列化)这三个接口。
二、对外提供的接口不一样
Hashtable比HashMap多提供了elments() 和contains() 两个方法。elments() 方法继承自Hashtable的父类Dictionnary。elements() 方法用于返回此Hashtable中的value的枚举。
contains()方法判断该Hashtable是否包含传入的value。它的做用与containsValue()一致。事实上,contansValue() 就只是调用了一下contains() 方法。
三、对null的支持不一样
Hashtable:key和value都不能为null。
HashMap:key能够为null,可是这样的key只能有一个,由于必须保证key的惟一性;能够有多个key
值对应的value为null。
四、安全性不一样
HashMap是线程不安全的,在多线程并发的环境下,可能会产生死锁等问题,所以须要开发人员本身处理多线程的安全问题。
Hashtable是线程安全的,它的每一个方法上都有synchronized 关键字,所以可直接用于多线程中。
虽然HashMap是线程不安全的,可是它的效率远远高于Hashtable,这样设计是合理的,由于大部分的使用场景都是单线程。当须要多线程操做的时候可使用线程安全的ConcurrentHashMap。
ConcurrentHashMap虽然也是线程安全的,可是它的效率比Hashtable要高好多倍。由于ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。
五、初始容量大小和每次扩充容量大小不一样
六、计算hash值的方法不一样
答:
泛型是Java SE 1.5以后的特性, 《Java 核心技术》中对泛型的定义是:
“泛型” 意味着编写的代码能够被不一样类型的对象所重用。
“泛型”,顾名思义,“泛指的类型”。咱们提供了泛指的概念,但具体执行的时候却能够有具体的规则来约束,好比咱们用的很是多的ArrayList就是个泛型类,ArrayList做为集合能够存放各类元素,如
Integer, String,自定义的各类类型等,但在咱们使用的时候经过具体的规则来约束,如咱们能够约束集合中只存放Integer类型的元素,如:
List<Integer> iniData = new ArrayList<>()
使用泛型的好处?
以集合来举例,使用泛型的好处是咱们没必要由于添加元素类型的不一样而定义不一样类型的集合。
如:整型集合类,浮点型集合类,字符串集合类。
咱们能够定义一个集合来存放整型、浮点型,字符串型数据,而这并非最重要的,由于咱们只要把底层存储设置了Object便可,添加的数据所有均可向上转型为Object。
更重要的是咱们能够经过规则按照本身的想法控制存储的数据类型。
答:
主要包含set(集)、 list(列表包含 Queue)和 map(映射)。
Collection: Collection 是集合 List、 Set、 Queue 的最基本的接口。
Iterator:迭代器,能够经过迭代器遍历集合中的数据
Map:是映射表的基础接口
答:
分别是 ArrayList、 Vector 和LinkedList 。
List接口结构图
答:
同) 而是按照哈希值来存的因此取数据也是按照哈希值取得。元素的哈希值是经过元素的hashcode 方法来获取的, HashSet 首先判断两个元素的哈希值,若是哈希值同样,接着会比较equals 方法 若是 equls 结果为 true , HashSet 就视为同一个元素。若是 equals 为 false 就不是同一个元素。
哈希值相同 equals 为 false 的元素是怎么存储呢,就是在一样的哈希值下顺延(能够认为哈希值相同的元素放在一个哈希桶中)。也就是哈希同样的存一列。
如图 1 表示 hashCode 值不相同的状况; 图 2 表示 hashCode 值相同,但 equals 不相同的状况。
HashSet 经过 hashCode 值来肯定元素在内存中的位置。 一个 hashCode 位置上能够存放多个元素。
答:
HashMap 根据键的 hashCode 值存储数据,大多数状况下能够直接定位到它的值,于是具备很快的访问速度,但遍历顺序倒是不肯定的。 HashMap 最多只容许一条记录的键为 null,容许多条记录的值为 null。 HashMap 非线程安全,即任一时刻能够有多个线程同时写 HashMap,可能会致使数据的不一致。若是须要知足线程安全,能够用 Collections 的 synchronizedMap 方法使HashMap 具备线程安全的能力,或者使用 ConcurrentHashMap。 咱们用下面这张图来介绍HashMap 的结构。
大方向上,HashMap里面是一个数组,而后数组中每一个元素是一个单向链表。上图中,每一个绿色的实体是嵌套类Entry的实例,Entry包含四个属性:key、value、hash值和用于单向链表的next。
capacity:当前数组容量,始终保持 2^n,能够扩容,扩容后数组大小为当前的2倍。
oadFactor:负载因子,默认为0.75。
threshold:扩容的阈值,等于capacity * loadFactor。
Java8对HashMap进行了一些修改, 最大的不一样就是利用了红黑树,因此其由 数组+链表+红黑树 组成。
根据Java7HashMap的介绍,咱们知道,查找的时候,根据hash值咱们可以快速定位到数组的具体下标,可是以后的话,须要顺着链表一个个比较下去才能找到咱们须要的,时间复杂度取决链表的长度,为O(n)。为了下降这部分的开销,在Java8中, 当链表中的元素超过了8个之后,会将链表转换为红黑树,在这些位置进行查找的时候能够下降时间复杂度为O(logN)。
答:
泛型类的声明和非泛型类的声明相似,除了在类名后面添加了类型参数声明部分。和泛型方法同样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。由于他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
public class Box<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } }
答:
1.编译时异常。
2.运行时异常。
答:
1.Error和Exception都是java错误处理机制的一部分,都继承了Throwable类。
2.Exception表示的异常,异常能够经过程序来捕捉,或者优化程序来避免。
3.Error表示的是系统错误,不能经过程序来进行错误处理。
答:
error表示恢复不是不可能但很困难的状况下的一种严重问题。好比说内存溢出。不可能期望程序能处理这样的状况exception 表示一种设计或实现问题。也就是说,它表示若是程序运行正常,从不会发生的状况
答:
File FileInputSteam,FileOutputStream
BufferInputStream,BufferedOutputSream PrintWrite FileReader,FileWriter
BufferReader,BufferedWriter ObjectInputStream,ObjectOutputSream
答:
当用户线程发起一个read操做后,并不须要等待,而是立刻就获得了一个结果。 若是结果是一个error时,它就知道数据尚未准备好,因而它能够再次发送read操做。一旦内核中的数据准备好了,而且又再次收到了用户线程的请求,那么它立刻就将数据拷贝到了用户线程,而后返回。因此事实上,在非阻塞IO模型中,用户线程须要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,而会一直占用CPU。
典型的非阻塞IO模型通常以下:
while(true){ data = socket.read(); if(data!= error){ //处理数据 break; } }
可是对于非阻塞IO就有一个很是严重的问题, 在while循环中须要不断地去询问内核数据是否就绪,这样会致使CPU占用率很是高,所以通常状况下不多使用while循环这种方式来读取数据。
答:
Buffer,故名思意, 缓冲区,其实是一个容器,是一个连续数组。 Channel提供从文件、网络读取数据的渠道,可是读取或写入的数据都必须经由Buffer。
上面的图描述了从一个客户端向服务端发送数据,而后服务端接收数据的过程。客户端发送数据时,必须先将数据存入Buffer 中,而后将Buffer中的内容写入通道。服务端这边接收数据必须经过Channel将数据读入到Buffer中,而后再从Buffer中取出数据来处理。
在NIO中, Buffer是一个顶层父类,它是一个抽象类,经常使用的Buffer的子类有:ByteBuffer、 IntBuffer、 CharBuffer、 LongBuffer、DoubleBuffer、 FloatBuffer、ShortBuffer。
答:
Selector类是NIO的核心类, Selector可以检测多个注册的通道上是否有事件发生,若是有事件发生,便获取事件而后针对每一个事件进行相应的响应处理。这样一来,只是用一个单线程就能够管理多个通道,也就是管理多个链接。这样使得只有在链接真正有读写事件发生时,才会调用函数来进行读写,就大大地减小了系统开销,而且没必要为每一个链接都建立一个线程,不用去维护多个线程,而且避免了多线程之间的上下文切换致使的开销。
答:
jdbc就是典型的反射
Class.forName('com.mysql.jdbc.Driver.class');//加载MySQL的驱动类
这就是反射。如hibernate,struts等框架使用反射实现的。
答:
Class对象的 newInstance()
调用 Constructor 对象的 newInstance()
//获取 Person 类的 Class 对象 Class clazz=Class.forName("reflection.Person"); //使用.newInstane 方法建立对象 Person p=(Person) clazz.newInstance(); //获取构造方法并建立对象 Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class); //建立对象并设置属性13/04/2018 Person p1=(Person) c.newInstance("李四","男",20)
答:
使用 Java 对象序列化, 在保存对象时,会把其状态保存为一组字节,在将来, 再将这些字节组装成对象。必须注意地是, 对象序列化保存的是对象的”状态”,即它的成员变量。由此可知,对象序列化不会关注类中的静态变量。
答:
虚拟机是否容许反序列化,不只取决于类路径和功能代码是否一致,一个很是重要的一点是两个类的序列化ID是否一致(就是 privatestatic final long serialVersionUID
答:
在 Java 语言里深复制一个对象,经常能够先使对象实现Serializable接口,而后把对象(实际上只是对象的一个拷贝)写到一个流里,再从流里读出来,即可以重建对象。
答:
元注解的做用是负责注解其余注解。 Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它annotation类型做说明。
@Target 修饰的对象范围
@Target说明了Annotation所修饰的对象范围: Annotation可被用于packages、types(类、接口、枚举、Annotation 类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch 参数)。在 Annotation 类型的声明中使用了target可更加明晰其修饰的目标。
@Retention 定义 被保留的时间长短
Retention 定义了该 Annotation 被保留的时间长短:表示须要在什么级别保存注解信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效),取值(RetentionPoicy)由:
SOURCE:在源文件中有效(即源文件保留)
CLASS:在 class 文件中有效(即 class 保留)
RUNTIME:在运行时有效(即运行时保留)
@Documented 描述-javadoc
@ Documented用于描述其它类型的annotation应该被做为被标注的程序成员的公共API,所以能够被例如javadoc此类的工具文档化。
@Inherited阐述了某个被标注的类型是被继承的
@Inherited元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。若是一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation 将被用于该class的子类。
答:
Annotation(注解)是Java提供的一种对元程序中元素关联信息和元数据(metadata)的途径和方法。 Annatation(注解)是一个接口,程序能够经过反射来获取指定程序中元素的Annotation对象,而后经过该Annotation对象来获取注解中的元数据信息。
该面试题答案解析完整文档获取方式:Java集合/泛型面试题、Java异常面试题、Java中的IO与NIO面试题、Java反射、Java序列化、Java注解。
篇幅有限,其余内容就不在这里一 一展现了,整理不易,欢迎你们一块儿交流,喜欢小编分享的文章记得关注我点赞哟,感谢支持!重要的事情说三遍,转发+转发+转发,必定要记得转发哦!!!