2020Java后端开发面试题总结(春招+秋招+社招)

1,098 阅读22分钟

前言

2021年了,想必大家都有想跳槽涨薪的念头吧,那么肯定就得有一些准备咯,首先面试题是一定得刷的,其次再是一些其他的言谈举止的注意,这些都是其次,最最最重要的还是技术和不怯场!!!要自信!!! 进入主题吧,今天给大家分享一些Java面试中频繁被问到的一些面试题,希望能够帮助到大伙儿~

最近将个人学习笔记整理成了PDF文档,主要包含了Java基础,数据结构,jvm,多线程、Spring系列全家桶等内容包括:MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、Spring Boot、Spring Cloud、RabbitMQ、Kafka、Linux 等技术栈)

文章目录

Java基础——基础知识

Java基础——集合框架/泛型/容器

Java基础——多线程

Java基础——框架基础:注解/反射/流行框架

Java基础——面向对象:继承/多态/封装

Java基础——设计模式

Java基础——JVM/类加载

Java基础——I/O

网络编程和计网

数据库

操作系统

数据结构

Java基础—基础知识

一、八种基本数据类型的大小,以及他们的封装类。

byte(Byte) 1 ,short(Short) 2 ,int(Integer) 4 ,long(Long) 8 ,float(Float) 4 ,double(Double)8,boolean(Boolean),char(Character)2

二、Switch能否用string做参数?

switch语句中的变量类型可以使byte,short,int,char。从jdk1.7后可以使用String类型,是通过switch中的String.hashcode将String转换成int进行判断的。

三、equals与==的区别。

==操作符是用来比较两个变量的值是否相等,即就是比较变量在内存中的存储地址是否相同,equals()方法时String类从Object类中继承的,被用来检测两个对象的内容是否相同。

四、String s=new String(‘xyz’);创建了几个object对象?

会创建一个String类型的变量s。在类加载到此处之前没有出现“xyz”字面量的话,加载此处会创建一个对应“xyz”的String常量对象。在符合规范的JVM上,执行到此处new关键字会创建一个String对象。

五、 Object有哪些公用方法?

1、clone()创建斌返回此对象的副本

2、equals()判断

3、getclass()返回object的运行类

4、hashcode()返回对象的哈希码值

5、notify()唤醒正在等待对象监听器的单个进程

6、notifyAll()唤醒正在等待对象监听器的所有进程

7、wait()导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。

8、toString()返回此对象的字符串表示形式

9、finalize()当垃圾收集确定不需要该对象时,垃圾回收器调用该方法

六、Java的四种引用,强弱软虚,用到的场景。

强引用:垃圾回收器不会回收

软引用:如果内存空间足够,垃圾回收器就不会进行回收,如果内存空间不足,垃圾回收器就会进行回收

弱引用:一旦发现了只有弱引用的对象,垃圾回收器就会进行回收。

虚引用:如果发现该对象还具有虚引用,就会在回收该对象之前,吧这个虚引用加入到与之关联的引用队列中。

七、静态变量和实例变量的区别。

静态变量前要加上关键字static,实例变量则不会。

实例变量是属于某个对象的属性,必须创建了实例对象,其中的实例变量才会分配空间,才能使用这个实例变量。静态变量不属于任何的实例对象,而是属于类,也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,就会被分配空间。总之就是,静态变量不需要创建任何的对象就可以直接使用,而实例变量需要先创建实例对象才能被使用。

八、 Overload和Override的区别:

重载Overload表示的是同一个类中可以有多个相同名称的方法,但这些方法的参数列表不同,即就是参数参数或参数类型不同。重载时返回值当然可以不一样,但是如果参数列表完全一致时,不能通过返回类型不一致而实现重载,这是不可以的。

重写Override表示子类中的方法可以与父类中的方法名称和参数完全相同,通过子类创建的对象来调用这个方法时,将调用子类中定义的方法,即就是子类中的该方法将父类的该方法覆盖了。子类覆盖父类方法时只能抛比父类更少或者更小的异常。重写的方法其返回必须和被覆盖的方法返回一致。

九、抽象类和接口的区别。

抽象类可以有默认的方法进行实现,可以有构造器,可以有main方法进行运行,可以直接在该类中添加实现的方法接口没有默认的方法进行实现,没有构造器,不可以使用main方法进行运行,在接口中添加方法时需要在具体实现的类中添加方法。

十、String、StringBuffer与StringBuilder的区别。

String表示内容不可修改的字符串,StringBuffer表示内容可以修改的字符串,String覆盖了equals()方法和hashcode()方法,而StringBuffer没有覆盖两个方法,,所以StringBuffer对象存储到java集合类中时会出现问题。

StringBulider也表示内容可以修改的字符串,但是其线程是不安全的,运行效率高。

十一、 Java面向对象的特征与含义。

封装、继承、抽象、多态

1、封装:封装的目的在于实现程序的“高内聚,低耦合”,防止程序相互依赖而带来的变动影响。封装是保证是把对同一事物进行操作的方法和相关的方法放在同一个类中,把方法和他操作的数据放在同一个类中。

2、抽象:抽象就是找出事物的相似和共性,然后将这些事物归为同一类,这个类只考虑这些事物的相似和共性,忽略和当前主题不相关的因素。

3、继承:子类继承父类的内容作为自己的内容,可以加入新的内容或者是修改父类的内容而更加适合特殊的需要。提高了额程序的可重用性和可扩张性。

4、多态:多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。

十二、java多态的实现

接口实现,继承父类进行方法重写,

同一个类中进行方法重载。

十三、error和exception区别

error表示有可能恢复但比较困难的的一种严重问题,程序是不能进行处理的exception表示一种设计或者实现问题。

十四、运行时异常和一般异常的区别

异常表示程序运行过程中可能出现的非正常状态。运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见的运行错误。java编译器要求方法必须声明抛出可能出现的非运行时异常,但是并不要求必须声明抛出未被捕获的异常

十五、Java中的异常处理机制和简单原理和应用

JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发 NullPointerException。另一种情况就是JAVA允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用 throw关键字引发异常。所有的异常都是java.lang.Thowable的子类。

十六、Java语言如何进行异常处理,throws,throw,try catch finally代表什么意义,try块中可以抛出异常吗?

Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例。当一个

方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throws)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理。

用try来指定一块预防所有”异常”的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的”异常”的类型。

throw语句用来明确地抛出一个”异常”。

throws用来标明一个成员函数可能抛出的各种”异常”。

Finally为确保一段代码不管发生什么”异常”都被执行一段代码。

可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句,”异常”的框架就放到堆栈上面,直到所有的try语句都完成。 如果下一级的try语句没有对某种”异常”进行处理,堆栈就会展开,直到遇到有处理这种”异常”的try语句。

十七、 try catch finally,try里有return,finally还执行么?

1、finally语句总会执行

2、如果try、catch中有return语句,finally中没有return,那么在finally中修改除包装类型和静态变量、全局变量以外的数据都不会对try、catch中返回的变量有任何的影响(包装类型、静态变量会改变、全局变量)

3、尽量不要在finally中使用return语句,如果使用的话,会忽略try、catch中的返回语句,也会忽略try、catch中的异常,屏蔽了错误的发生。

4、finally中避免再次抛出异常,一旦finally中发生异常,代码执行将会抛出finally中的异常信息,try、catch中的异常将被忽略

十八、 Java中final、finally和finalize的区别

final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。

内部类要访问局部变量,局部变量必须定义成final类型,例如,一段代码……

finally是异常处理语句结构的一部分,表示总是执行。

finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用。

十九、 常见的运行时异常

系统异常是RuntimeException的子类,常见的系统异常有:

ArrayIndexOutOfBoundsException - 数组越界访问

ClassCastException - 类型转换异常

NullPointerException - 试图访问一空对象的变量、方法或空数组的元素

IllegalArgumentException - 方法的参数无效

NoClassDefFoundException - JAVA运行时系统找不到所引用的类

集合:

二十、Collection框架的结构

集合框架(Collection Framework)泛指java.util包的若干个类和接口.如Collection,List,ArrayList,LinkedList,Vector(自动增长数组),HashSet,HashMap等。

集合框架中的类主要封装的是典型的数据结构,如动态数组,链表,堆栈,集合,哈希表等.

集合框架类似编程中经常用到的工具类,使得编码这专注于业务层的实现,不需要从底层实现相关细节—“数据结构的封装”和”典型算法的实现”。

二十一、Collection包结构

Collection是集合类的上级接口,是单列集合。继承他的接口主要有Set 和List.

Set接口的子接口有:HashSet,TreeSet

List接口的子接口有:Arraylist,LinkedList,Vector

二十二、Collection与Collections的区别。

Collection是集合类的上级接口,继承他的接口有Set和List

Collections是针对集合类的一个帮助类,它提供一系列的静态方法实现集合的搜索,排序,线程安全等操作。

二十三、 Colection框架中实现比较要实现什么接口?

comparable:只包含compareTo()方法

comparator:compare()和equals()

二十四、Map、Set、List、Queue、Stack的特点与用法。

1、Map是以键值对的形式进行存储的,其中key是唯一不可重复的,value的可以重复,当插入的值是key相同,后加入的会将已有的覆盖。他有几个具体的实现类,包括Treemap和HashMap,TreeMap是有序的,HashMap是无序的。

2、List 有序,可重复

|--ArrayList

底层数据结构是数组,查询快,增删慢,线程不安全,效率高

|--Vector

底层数据结构是数组,查询快,增删慢,线程不安全,效率高

|--LinkedList

底层数据结构是链表,查询慢,增删块,线程安全,效率低

3、Set 无序,唯一

|--HashSet

底层数据结构是哈希表

如何保证元素的唯一性:

依赖两个方法,hashCode()和equals()

|--LinkedHashSet

底层数据结构是链表和哈希表,由链表保证元素有序,由哈希表保证元素唯一

|--TreeSet底层数据结构是红黑树,

如何保证元素的排序:

自然排序:让元素所属的类实现Comparable接口

比较器排序:让集合接收一个Comparator的实现类对象

如何保证元素的唯一性:

根据比较的返回值是否是0来决定的

4、Query队列遵循先进先出的原则,不允许插入null值,其中提供了相应的进队和出队的方法,建议使用offer()方法来添加元素,使用poll()方法删除元素

5、Stack遵从后进先出的原则,继承自Vector。他通过5个操作对Vector类进行扩展,它提供了push和pop操作,以及去堆栈顶点的peek()方法,测试堆栈是否为空的empty方法

6、使用方法:

如果涉及到堆栈,队列等操作,建议使用List

对于快速插入和删除元素建议使用LinkedList

需要快速随机访问元素建议使用ArrayList

二十五、 Set里面的元素不能重复,用什么方法区分重复与否?

Set里的元素是唯一不能重复的,元素是否重复使用equals()方法进行判断。

equals()方法和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是两个分离的对象的内容和类型相匹配的话,返回真值。

二十六、HashMap和Hashtable的区别。

1、Hashtable是基于Dictionary类的,HashMap是Map接口的一个实现类

2、Hashtable是线程安全的,即是同步的;HashMap线程不是安全的,不是同步的。

3、HashMap可以将空值作为key或value

二十七、 HashMap、LinkedHashMap、TreeMap的区别。

1、HashMap是根据键的hashcode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,取得的数据完全是随机的

2、LinkedHashMap保存了记录的插入顺序,在使用Iterator进行遍历的时候,先得到的肯定是先插入的数据,可以在构造时带参数,按照应用次数来进行排序

3、TreeMap实现SortMap接口,能够把它保存的记录根据键排序。默认的是升序排序,也可以指定排序的比较器,进行遍历的时候得到的是排序过的记录。

二十八、HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。

1、HashMap是java数据结构中两大结构数组和链表的组合。HashMap底层数组,数组中的每一项又是一个链表。程序会先根据key的hashcode()方法返回值决定该Entry在数组中的

存储位置,如果该位置上没有元素,就会将元素放置在此位置上,如果两个Entry的key相同,会调用equals,返回值是true则覆盖原来的value值,返回false则会形成Entry链,位于头部。

2、ArrrayList的底层实现是数组,在执行add操作时,会先检查数组 大小是否可以容纳新的元素,如果不够就会进行扩容。然后会将原来的数据拷贝到新的数组中。

3、LinkedList底层是一个链表,其实现增删改查和数据结构中的操作完全相同,而且插入是有序的。

4、LinkedHashMap的底层结构式是双链表,其他的逻辑处理与HashMap一致,同样没有锁保护,多线程使用时存在风险。

5、ConcurrentHashMap是segment数组结构和HashEntry数组结构组成的,segment在ConcurrentHashMap中充当锁的角色,HashEntry用于存储键值对数据。segment的结构是数组和链表,一个segment中有一个HashEntry,每个HashEntry是一个链表结构的元素。对HashEntry中的数据进行修改时,需要先获得它所对应的segment锁。每个ConcurrentHashMap默认有16个segment。

二十九、迭代器Iterator

Iterator提供了统一遍历操作集合元素的统一接口,Collection接口实现Iterator接口。每个集合都通过实现Iterator接口中的iterator()方法返回实例,然后对元素进行迭代操作,但是在迭代元素的时候不能使用集合的方法删除元素,否则会抛出异常,可以使用Iterator接口中的remove()方法进行删除。

三十、 快速失败(fail-fast)和安全失败(fail-safe)的区别。

Iterator的安全失败是基于对底层集合做拷贝,因此它不受源集合修改的影响。util包下的所有集合类都是快速失败的,util.concurren包下面的所有类都是安全失败的。

Java基础—集合框架/泛型/容器

概念

一、容器(Container) Spring 提供容器功能,容器可以管理对象的生命周期、对象与对象之间的依赖关系,您可以使用一个配置文件(通常是 XML),在上面定义好对象的名称、如何产生(Prototype 方式或 Singleton 方式)、哪个对象产生之后必须设定成为某个对象的属性等,在启动容器之后,所有的对象都可以直接取用,不用编写任何一行程序代码来产生对象,或是建立对象与对象之间的依赖关系。 换个更直白点的说明方式:容器是一个 Java 所编写的程序,原先必须自行编写程序以管理对象关系,现在容器都会自动帮您作好。 常用容器:WebSphere,WebLogic,Resin,Tomcat。

容器类

容器类 其实就是一种用来存储数据的数据结构,在 JAVA 中容器可分为即 “集合”(Set)、“列表”(List)、“映射”(Map)。至于,为什么需要容器,总的来说,主要是在以数组作为数据的存储结构中,其长度难以扩充,同时数组中元素类型必须相同。而容器可以弥补数组的这两个缺陷。

Java 容器类包含 List、ArrayList、Vector 及 map、HashTable、HashMap。

ArrayList 和 HashMap 是异步的,Vector 和 HashTable 是同步的,所以 Vector 和 HashTable 是线程安全的,而 ArrayList 和 HashMap 并不是线程安全的。因为同步需要花费机器时间,所以 Vector 和 HashTable 的执行效率要低于 ArrayList 和 HashMap。

二、集合框架的说明

所有集合类都位于 java.util 包下。Java 的集合类主要由两个接口派生而出:Collection 和 Map,Collection 和 Map 是 Java 集合框架的根接口,这两个接口又包含了一些子接口或实现类。

1.Set、List 和 Map 可以看做集合的三大类:

2.List 集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问。

Set 集合是无序集合,集合中的元素不可以重复,访问集合中的元素只能根据元素本身来访问(也是集合里元素不允许重复的原因)。

3.Map 集合中保存 Key-value 对形式的元素,访问时只能根据每项元素的 key 来访问其 value。

三、集合框架详细说明

1、Collection 是一个接口,是高度抽象出来的集合,它包含了集合的基本操作和属性。Collection 包含了 List 和 Set 两大分支。 (1)List 是一个 有序的队列,每一个元素都有它的索引。第一个元素的索引值是 0。List 的实现类有 LinkedList, ArrayList, Vector, Stack。

(2)Set 是一个不允许有重复元素的集合。Set 的实现类有 HastSet 和 TreeSet。 HashSet 依赖于 HashMap,它实际上是通过 HashMap 实现的;TreeSet 依赖于 TreeMap,它实际上是通过 TreeMap 实现的。

2、Map 是一个映射接口,即 key-value 键值对。Map 中的每一个元素包含 “一个 key” 和 “key 对应的 value”。AbstractMap 是个抽象类,它实现了 Map 接口中的大部分 API。而 HashMap,TreeMap,WeakHashMap 都是继承于 AbstractMap。Hashtable 虽然继承于 Dictionary,但它实现了 Map 接口。

3、接下来,再看 Iterator。它是遍历集合的工具,即我们通常通过 Iterator 迭代器来遍历集合。我们说 Collection 依赖于Iterator,是因为 Collection 的实现类都要实现 iterator () 函数,返回一个 Iterator 对象。ListIterator 是专门为遍历 List 而存在的。

4、再看 Enumeration,它是 JDK 1.0 引入的抽象类。作用和 Iterator 一样,也是遍历集合;但是 Enumeration 的功能要比 Iterator 少。在上面的框图中, Enumeration 只能在 Hashtable, Vector, Stack 中使用。

5、最后,看 Arrays 和 Collections。它们是操作数组、集合的两个工具类。

四、集合与数组

五、层次关系

六、几种重要的接口和类简介

七、遍历

八、ArrayList 和 LinkedList

九、Map 集合

十、主要实现类区别小结 .........

Java基础—多线程

一、多线程基本概念

二、线程相关的常用方法

三、继承Thread类

四、实现Runnable 接口

五、Java 分为两种线程:用户线程和守护线程

六、用户线程就是前台线程,守护线程就是后台线程

七、什么是可重入锁?

八、Lock 与 synchronized 的不同

九、synchronized的使用

十、atomic 包底层实现原理

十一、Lock底层原理

十二、多线程不安全的底层原因以及两种加锁方式的区别

十三、Java多线程中 的各种锁

十四、Java多线程中 的各种锁(补充)

十五、阻塞队列BlockingQueue

十六、Java线程池、Java线程池进阶、Java中的ThreadLocal

Java基础—框架基础:注解/反射/流行框架

一、优化 Hibernate 所鼓励的7大措施

二、序列化和反序列化

三、Java中池的概念

四、Java反射

五、Spring的IOC和AOP概念和实现原理

六、 仿照 Spring 实现简单的 IOC

七、仿照 Spring 实现简单的 AOP

八、Spring bean 的生命流程

九、仿写Spring 进阶之 AOP和IOC协作

Java基础—面向对象:继承/多态/封装

一、重写与重载

二、单继承和多继承

三、多态

四、super和this关键字

Java基础—设计模式

一、单例模式之懒汉式和饿汉式

二、设计模式之观察者模式

三、设计模式之工厂模式

四、设计模式之代理模式

Java基础—JVM/类加载

一、初始化执行代码顺序(包含static块和构造块)以及类方法和实例方法

二、JVM内存结构

三、JVM组成部分

四、类加载机制

五、类加载器

六、Java类加载器之间的关系

七、虚拟机中的对象

八、虚拟机 分配内存

九、Java中的引用类型

十、JVM如何判断是否回收对象

十一、垃圾回收算法

十二、JVM运行时数据区域

十三、JVM垃圾收集器

十四、JVM垃圾回收

十五、Java中的内存泄露和内存溢出

Java基础——I/O

一、I/O 基本概念

二、I/O 模型 ——阻塞、非阻塞、多路复用、异步

三、JAVA中 BIO 与 NIO、AIO

网络编程和计网

一、Java中的原码、反码和补码

二、forward 和 redirect

三、URL的组成

四、通信的基础——IP、DNS、MAC地址

五、关于ip地址的理解

六、GFW(中国防火长城)工作原理

七、OSI七层模型和 五层体系结构

八、TCP 三次握手和四次挥手协议

九、TCP协议 (可靠保证、TCP、UDP、拥塞、ARQ)

十、HTTP 和 HTTPS

十一、Http/1.0、Http/1.1、Http2

十二、Https 加密过程详解

十三、HTTP协议的补充(POST、GET请求方法、幂等性)

十四、网络攻击(XSS、CSRF)详解

十五、DDoS 攻击详解

十六、SQL注入攻击详解

数据库

一、结果集 (ResultSet)全面解析

二、基本概念

三、索引

四、事务

五、存储引擎

六、数据库优化

七、数据库锁

八、主从复制和读写分离

操作系统

一、线程进程部分

二、内存和中断

三、互斥和同步

四、Linux相关命令

五、Linux IO 模式及 select、poll、epoll 详解

数据结构

一、链表、数组、字符、树篇

二、堆、栈、队列篇

三、B树、B+树、B*树

四、Java实现排序算法,比较时间复杂度

五、红黑树

六、数据结构之栈

七、搜索与回溯算法-Java实现

八、高效判断一个数,是不是素数

最后

个人学习笔记已整理成了PDF文档,主要包含了Java基础,数据结构,jvm,多线程、Spring系列全家桶等内容包括:MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、Spring Boot、Spring Cloud、RabbitMQ、Kafka、Linux 等技术栈)

祝大家新年快樂,面试涨薪顺顺利利!!!