终于熬过2020,分享一下负重前行的一年遇到的Java面试题

  • 一、Java基础面试
      • 1、多线程和线程池(高频重点考点·必备技能)
      • 2、集合(常见考点)
      • 3、其他基础问题(必备基础)
      • 4、数据库基础
      • 5、Redis---非关系型数据库
      • 6、Linux相关基础和指令
      • 7、框架:
      • 8、前端技术
      • 9、最后

前言:今年是个不平静的一年。博主去年临近毕业因为公司单方面毁约的原因,毕业被赶出校,仓促进了一家做人脸识别的小公司。对公司的知遇之恩其实一直铭记在心,老大人也特别好。由于开发团队人员较少的原因,这一年来前端后端安卓端都在写,接触得多、但是每个领域都不精。一年下来真的没啥技术上的沉淀。更多的就是CRUD。上半年遇到疫情,下半年项目在手,换工作的计划一直被拖后。现在手上的项目也马上试点了,自己也在陆续投递简历。尝试新机会。才发现自己的技术面还是太窄了。本应精通的后端也只会CRUD和SSM。最近也面了几个公司。也总结了一下遇到的面试题。在这儿分享一下。

  • 因为还在职,要带实习生和跟项目。所以也没全身心地投入到找工作中。九月份开始陆陆续续面过一些公司,有大有小、有国企有私企,仿佛回到了去年不停去各个学校听宣讲会的秋招。由于今年行情整体不是很好,待遇好多都不怎么样,自己满意的人家不要我,人家要我的我又不想去。收效也甚微。最近工作也基本落实了。来跟大家分享一下这期间我遇到的一些问题吧。

  • 注: 社招不同于校招,基础也会问,但大多会偏向于更深层的方向去问。博主一年多工作经验,投的都是一年多左右的岗位。别看我年限,我是个菜鸡。以下都是我遇到的,太多了总结了一些,有的写了没写。挑些重要的讲一下吧!

一、Java基础面试

1、多线程和线程池(高频重点考点·必备技能)

(1)、线程的创建方式和生命周期

  • 一般有四种办法:继承Thread、实现Runable接口、实现Callable接口、线程池创建线程。

  • a、创建线程类继承Thread,重写run方法,然后进行调用。

	public class MyThread extends Thread {
	    @Override
	    public void run() {
	        for (int i = 0; i<10; i++){
	            System.out.println("mythread线程正在执行:"+new Date().getTime());
	        }
	    }
	}
	//调用
	MyThread thread = new MyThread();//没有传入参数
	thread.start();

  • b、实现Runable接口
	public class MyRunable implements Runnable {
		public void run() {
		    for (int i=0; i<10; i++){
		        System.out.println("MyRunnable线程正在执行:"+new Date().getTime());
		    }
		}
	}
	
	//调用
	Thread thread = new Thread(new MyRunable());//注意传入参数
	thread.start();

  • c、实现Callable接口
	public class MyCallable implements Callable<String> {//注意泛型,传入的类型就是call方法的返回值类型
	    public String call() throws Exception {
	        for (int i=0; i<10; i++){
	            System.out.println("MyCallable正在执行:"+new Date().getTime());
	        }
	        return "MyCallable执行完毕!";
	    }
	}
	//调用
	FutureTask task = new FutureTask(new MyCallable());//注意需要创建FutureTask对象,传入Callable接口实现类的对象
	Thread thread = new Thread(task);//传入FutureTask对象
	thread.start();
	

  • d、线程池创建(后面在细节讲各个参数)
	public ThreadPoolExecutor(int corePoolSize,
	                          int maximumPoolSize,
	                          long keepAliveTime,
	                          TimeUnit unit,
	                          BlockingQueue<Runnable> workQueue,
	                          ThreadFactory threadFactory,
	                          RejectedExecutionHandler handler) {
	}

(2)、start()和run()的区别

  • tart与run方法的主要区别在于当程序调用start方法一个新线程将会被创建,并且在run方法中的代码将会在新线程上运行,然而在你直接调用run方法的时候,程序并不会创建新线程,run方法内部的代码将在当前线程上运行。

(3)、线程池的创建方法

  • 见第(4)题

(4)、线程池的几个重要参数

  • 见第(5)题

(5)、各个参数值的设置有哪些讲究

  • 传送门》》》线程池的介绍《《

2、集合(常见考点)

(1)、常见的集合list、set、map 子类介绍一下,原理、应用场景

  • 传送门 》》list、set、map区别和应用场景《《

(2)、HashMap发生hash冲突是怎么解决的,1.8之后引入了什么东西解决,链表过长(红黑树)。

  • a、在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
  • b、当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

(3)、HashMap的key存对象可以么,会出现什么问题

  • 这个问题博主专门搜了下,看这篇博客看懂的,可以参考下!
  • 》》传送门《《

(4)、多线程操作ArrayList如何实现线程安全,那个关键字可以实现

  • a、Collections.synchronizedList(List list)

  • b、CopyOnWriteArrayList

    • Description:CopyOnWriteArrayList和Collections.synchronizedList是实现线程安全的列表的两种方式。两种实现方式分别针对不同情况有不同的性能表现。其中CopyOnWriteArrayList的写操作性能较差,而多线程的读操作性能较好。而Collections.synchronizedList的写操作性能比CopyOnWriteArrayList在多线程操作的情况下要好很多,而读操作因为是采用了synchronized关键字的方式,其读操作性能并不如CopyOnWriteArrayList。因此在不同的应用场景下,应该选择不同的多线程安全实现类。

(5)、为什么get和set LinkedList会比ArrayList慢,add和remove 又更快

  • ArrayList 是一种可增长的数组的实现。
    使用ArrayList的优点在于 对 get和set的调用是花费常数时间。缺点就是有新的项插入,和现有的项删除代价昂贵,除非变动是
    在ArrayList的末端进行。

  • 使用LinkedList的优点在于新的项的插入和现有的项的删除开销很小。这意味着在表的前端进行添加和删除都是常数时间的操作,因此LinkedList提供了addFirst,removeFirst,addLast,removeLast,以及getFirst和getLast等都有效的添加删除和访问。缺点就在于它不容易作索引的,所以get的调用是昂贵的,除非非常接近表的两端。

(6)、HashMap ,HashTable 区别

  • HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。

  • HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。

  • HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

  • 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。

  • 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。

  • HashMap不能保证随着时间的推移Map中的元素次序是不变的。

(7)、Hashtable的优点和缺点。升级版CurrentHashMap。二者的区别。

  • 这里直接推荐博主发现的一篇宝藏博客,我也是看了这篇博客后才更深入理解了几个Map的区别的,大家可以参考下

    • 》》博客传送门《《

(8)、讲一下 HashMap 中 put 方法过程?

  • 这块建议大家去详细读下HashMap的源码,一切就会茅厕顿开了!手动滑稽~~~~

(9)、ArrayList和LinkedList的区别,各自的适用场景优缺点。

  • 区别
    • ArrayList底层是用数组实现的,可以认为ArrayList是一个可改变大小的数组。随着越来越多的元素被添加到ArrayList中,其规模是动态增加的。
    • LinkedList底层是通过双向链表实现的, LinkedList和ArrayList相比,增删的速度较快。但是查询和修改值的速度较慢。同时,LinkedList还实现了Queue接口,所以他还提供了offer(),
      peek(), poll()等方法。
  • 使用场景
    • LinkedList更适合从中间插入或者删除(链表的特性)。
    • ArrayList更适合检索和在末尾插入或删除(数组的特性)。

(10)、ArrayList在遍历的时候是否能删除元素,需要注意些什么

  • 遍历的时候可以删除元素,但是要注意手动修改一下循环变量(减1),否则会导致中间的某些元素错误地跳过,遍历不到。删除一个元素(n)之后,后边的元素会自动前移,此时第n+1个元素会移动到第n的位置,正常循环会跳过这个元素,所以就需要对下标做-1的操作了。
  • 用迭代器迭代的时候可以删除元素,但是只能通过迭代器来删除,不能直接在数组上删除,否则迭代器会抛出异常。
  • 如果有多个迭代器同时迭代的话不能删除,否则其他迭代器同样会抛出异常

3、其他基础问题(必备基础)

(1)、transient关键字的作用

  • 对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。
  • 然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
  • 总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

(2)、对象序列化操作

(3)、hashCode和equals方法的关系

  • equals相等,hashcode必相等;hashcode相等,equals可能不相等。

(4)、equals和 == 的区别

(5)、Object包含有哪些方法

(6)、垃圾回收机制,如何进行JVM调优。

(7)、如何避免循环依赖

(8)、Lock和Synchronized的区别。

(9)、TCP三次握手四次挥手(必背题)。

(10)、描述一下Http协议从请求到响应的整个过程。

(11)、http和https的区别。


4、数据库基础

(1)、事务的四大特性,详细介绍并举例

(2)、你们用的事务隔离级别是什么

(3)、#和$的区别

(4)、B+树和B树的区别。

(5)、你知道的数据库引擎有哪几个,InnerDB数据库的查询原理。

(6)、分页查询、每页占多大。

(7)、索引的使用、索引机制,最左原理。

(8)、inner join、left join、right join的区别。


5、Redis—非关系型数据库

(1)、你所用的过期机制

(2)、什么是缓存击穿、缓存穿透、缓存雪崩。如何避免?

(3)、Redis存储的类型有哪些。

(4)、什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?

(5)、redis集群了解么,说说你的理解。


6、Linux相关基础和指令

(1)、常用的指令有哪些

(2)、sysctrl指令

(3)、tomcat初始内存,如何调整

(4)、Linux如何查看系统日志、用什么指令。

7、框架:

(1)、说说Spring有哪些优点,解决了哪些问题。

(2)、DI和IOC

(3)、描述一下MVC的运行机制和原理

(4)、Spring常用注解,举一些

(5)、SpringBoot和SpringMVC的区别

(6)、SpringBoot的关键注解是哪个,里面主要包含了哪些东西。

8、前端技术

  • 由于博主简历上还写了了解前端和安卓,有的也问到了前端或者安卓的一些问题,也只小公司会比较喜欢全栈的吧

(1)、vue的生命周期

(2)、v-if和v-show的区别

(3)、vue构造器是什么,有哪几个常用挂载点

  • 这里再分享一下博主之前写的一篇基础面试题。有重复的滤过。

  • 》》》传送门《《《

  • 答案太多了先发这点吧,等我有时间再来继续完善!哈哈,不是我懒,最近快过年了,提前祝大家新年快乐。

9、最后

  • 博主也遇到过好几个,要求现场手撕代码的。当然都是稍大一点的公司。有的也会直接安排一轮笔试。有的会让写表结构、根据需求写代码、或者直接是算法题。所以不仅理论要扎实,还是要会写代码!在这儿也没啥可推荐的,还是建议去牛客网刷一下题。

  • 加油吧,打工人。只有努力提升自己的实力。我又违背了我去年违约时候说过的话了。我还没成为大牛、我也不够努力 !哎~~~~~~~~

  • 最后想说的: 希望大家都能找到心仪的工作,应届生真的千万千万不要去小公司、初创公司。真的无论眼界、接触到的东西、学到的东西、真的很有限很有限。举个简单的例子接触不到高并发的用户、就接触不到性能的瓶颈、更别提对于性能的调优。包括很多情况下的开发工作都没有那么规范、身边缺少优秀的人、缺少可以学习的人。但是去了大的公司、大的平台这些都会有。我也是最近在找工作多次碰壁以后、才深深发现了自己的不足何所欠缺的东西。希望后来者不要走我的老路。当然我也是被迫的~~哎!

  • 写的有点多,如有错误望指正!

更多推荐

2020Java面试题汇总(2020年负重前行的Java码畜社招遇到的Java面试题---亲历总结)