整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

應各位小伙伴要求,今天抽空來整理整理java開發(fā)面試中的那些事情,幫助那些正在找工作或想跳槽找工作的伙伴們!分享目前Java常見的面試問題以及答案。

本文所有答案相對權(quán)威,有不對之處還請不吝賜教。篇幅較長,后續(xù)還會繼續(xù)更新~

整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

需要這份文檔的小伙伴直接私信【37】就可以無償免費領(lǐng)取,絕不需要關(guān)注什么公眾號!

Spring由哪些模塊組成?

Spring 總共大約有 20 個模塊, 由 1300 多個不同的文件構(gòu)成。 而這些組件被分別整合在一起

核心容器(Core Container) 、 AOP(Aspect Oriented Programming)和設備支持
(Instrmentation)
數(shù)據(jù)訪問與集成(Data Access/Integeration)
Web
消息(Messaging)
Test

等 6 個模塊中。 以下是 spring 5 的模塊結(jié)構(gòu)圖:

整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

  • spring core:提供了框架的基本組成部分,包括控制反轉(zhuǎn)(Inversion of Control,IOC)和依賴
    注入(Dependency Injection,DI)功能。
  • spring beans:提供了beanFactory,是工廠模式的一個經(jīng)典實現(xiàn),Spring將管理對象稱為
    Bean。
  • spring context:構(gòu)建于 core 封裝包基礎上的 context 封裝包,提供了一種框架式的對象訪問方式
    法。
  • spring jdbc:提供了一個JDBC的抽象層,消除了煩瑣的JDBC編碼和數(shù)據(jù)庫廠商特有的錯誤代碼解
    析, 用于簡化JDBC。
  • spring aop:提供了面向切面的編程實現(xiàn),讓你可以自定義攔截器、切點等。
  • spring Web:提供了針對 Web 開發(fā)的集成特性,例如文件上傳,利用 servlet listeners 進行 ioc容器初始化和針對 Web 的 ApplicationContext。
  • spring test:主要為測試提供支持的,支持使用JUnit或TestNG對Spring組件進行單元測試和集成測試

Spring的優(yōu)缺點是什么?

優(yōu)點

  • 方便解耦,簡化開發(fā)
    Spring就是一個大工廠,可以將所有對象的創(chuàng)建和依賴關(guān)系的維護,交給Spring管理。
  • AOP編程的支持
    Spring提供面向切面編程,可以方便的實現(xiàn)對程序進行權(quán)限攔截、運行監(jiān)控等功能。
  • 聲明式事務的支持
    只需要通過配置就可以完成對事務的管理,而無需手動編程。
  • 方便程序的測試
    Spring對Junit4支持,可以通過注解方便的測試Spring程序。
  • 方便集成各種優(yōu)秀框架
    Spring不排斥各種優(yōu)秀的開源框架,其內(nèi)部提供了對各種優(yōu)秀框架的直接支持(如:Struts、HibernateMyBatis等)。
  • 降低JavaEE API的使用難度
    Spring對JavaEE開發(fā)中非常難用的一些API(JDBC、JavaMail、遠程調(diào)用等),都提供了封裝,使這些API應用難度大大降低。

缺點

  • Spring明明一個很輕量級的框架,卻給人感覺大而全
  • Spring依賴反射,反射影響性能
  • 使用門檻升高,入門Spring需要較長時間

Spring 應用程序有哪些不同組件?

Spring 應用一般有以下組件:

  • 作為一個成熟的 Spring Web 應用程序。
  • 作為第三方 Web 框架,使用 Spring Frameworks 中間層。
  • 作為企業(yè)級 Java Bean,它可以包裝現(xiàn)有的 POJO(Plain Old Java Objects)。
    用于遠程使用。

IOC的優(yōu)點是什么?

  • IOC 或 依賴注入把應用的代碼量降到最低。
  • 它使應用容易測試,單元測試不再需要單例和JNDI查找機制。
  • 最小的代價和最小的侵入性使松散耦合得以實現(xiàn)。
  • IOC容器支持加載服務時的餓漢式初始化和懶加載。

Spring IOC 的實現(xiàn)機制

Spring 中的 IOC 的實現(xiàn)原理就是工廠模式加反射機制。

示例:

interface Fruit {public abstract void eat();}class Apple implements Fruit {public void eat(){System.out.println("Apple");}}class Orange implements Fruit {public void eat(){System.out.println("Orange");}}class Factory {public static Fruit getInstance(String ClassName) {Fruit f=null;try {f=(Fruit)Class.forName(ClassName).newInstance();} catch (Exception e) {e.printStackTrace();}return f;}}class Client {public static void main(String[] a) {Fruit f=Factory.getInstance("io.github.dunwu.spring.Apple");if(f!=null){f.eat();}}}

Spring如何處理線程并發(fā)問題?

  • 在一般情況下,只有無狀態(tài)的Bean才可以在多線程環(huán)境下共享,在Spring中,絕大部分Bean都可以聲明為singleton作用域,因為Spring對一些Bean中非線程安全狀態(tài)采用ThreadLocal進行處理,解決線程安全問題。
  • ThreadLocal和線程同步機制都是為了解決多線程中相同變量的訪問沖突問題。同步機制采用了“時間換空間”的方式,僅提供一份變量,不同的線程在訪問前需要獲取鎖,沒獲得鎖的線程則需要排隊。而ThreadLocal采用了“空間換時間”的方式。
  • ThreadLocal會為每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數(shù)據(jù)的訪問沖突。因為每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。

解釋Spring框架中bean的生命周期

  • 在傳統(tǒng)的Java應用中,bean的生命周期很簡單。使用Java關(guān)鍵字new進行bean實例化,然后該bean就可以使用了。一旦該bean不再被使用,則由Java自動進行垃圾回收。相比之下,Spring容器中的bean的生命周期就顯得相對復雜多了。正確理解Spring bean的生命周期非常重要,因為你或許要利用Spring提供的擴展點來自定義bean的創(chuàng)建過程。下圖展示了bean裝載到Spring應用上
    下文中的一個典型的生命周期過程。

整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

  • bean在Spring容器中從創(chuàng)建到銷毀經(jīng)歷了若干階段,每一階段都可以針對Spring如何管理bean進行個性化定制。
  • 正如你所見,在bean準備就緒之前,bean工廠執(zhí)行了若干啟動步驟。

我們對上圖進行詳細描述:

  • Spring對bean進行實例化;
  • Spring將值和bean的引用注入到bean對應的屬性中;
  • 如果bean實現(xiàn)了BeanNameAware接口,Spring將bean的ID傳遞給setBean-Name()方法;
  • 如果bean實現(xiàn)了BeanFactoryAware接口,Spring將調(diào)用setBeanFactory()方法,將BeanFactory容器實例傳入;
  • 如果bean實現(xiàn)了ApplicationContextAware接口,Spring將調(diào)用setApplicationContext()方法,將bean所在的應用上下文的引用傳入進來;
  • 如果bean實現(xiàn)了BeanPostProcessor接口,Spring將調(diào)用它們的postProcessBeforeInitialization()方法;
  • 如果bean實現(xiàn)了InitializingBean接口,Spring將調(diào)用它們的after-PropertiesSet()方法。類似地,如果bean使用initmethod聲明了初始化方法,該方法也會被調(diào)用;
  • 如果bean實現(xiàn)了BeanPostProcessor接口,Spring將調(diào)用它們的post-ProcessAfterInitialization()方法;
  • 此時,bean已經(jīng)準備就緒,可以被應用程序使用了,它們將一直駐留在應用上下文中,直到該應用上下文被銷毀;
  • 如果bean實現(xiàn)了DisposableBean接口,Spring將調(diào)用它的destroy()接口方法。同樣,如果bean使用destroy-method聲明了銷毀方法,該方法也會被調(diào)用。
    現(xiàn)在你已經(jīng)了解了如何創(chuàng)建和加載一個Spring容器。但是一個空的容器并沒有太大的價值,在你把東西放進去之前,它里面什么都沒有。為了從Spring的DI(依賴注入)中受益,我們必須將應用對象裝配進Spring容器中。

什么是基于Java的Spring注解配置? 給一些注解的例子

  • 基于Java的配置,允許你在少量的Java注解的幫助下,進行你的大部分Spring配置而非通過XML文件。
  • 以@Configuration 注解為例,它用來標記類可以當做一個bean的定義,被Spring IOC容器使用。
  • 另一個例子是@Bean注解,它表示此方法將要返回一個對象,作為一個bean注冊進Spring應用上下文。

@Configurationpublic class StudentConfig {@Beanpublic StudentBean myStudent() {return new StudentBean();}}

MySQL由哪些部分組成, 分別用來做什么

1. Server

  • 連接器: 管理連接, 權(quán)限驗證.
  • 分析器: 詞法分析, 語法分析.
  • 優(yōu)化器: 執(zhí)行計劃生成, 索引的選擇.
  • 執(zhí)行器: 操作存儲引擎, 返回執(zhí)行結(jié)果.

2. 存儲引擎: 存儲數(shù)據(jù), 提供讀寫接口.

MySQL怎么恢復半個月前的數(shù)據(jù)

通過整庫備份 binlog進行恢復. 前提是要有定期整庫備份且保存了binlog日志.

一千萬條數(shù)據(jù)的表, 如何分頁查詢

數(shù)據(jù)量過大的情況下, limit offset 分頁會由于掃描數(shù)據(jù)太多而越往后查詢越慢. 可以配合當前頁最后一條ID進行查詢, SELECT * FROM T WHERE id > #{ID} LIMIT #{LIMIT} . 當然, 這種情況下ID必須是有序的, 這也是有序ID的好處之一

SQL 語言包括哪幾部分?每部分都有哪些操作關(guān)鍵字?

SQL 語言包括數(shù)據(jù)定義(DDL)、數(shù)據(jù)操縱(DML),數(shù)據(jù)控制(DCL)和數(shù)據(jù)查詢( DQL) 四個部分。
數(shù)據(jù)定義: Create Table,Alter Table,Drop Table, Craete/Drop Index 等數(shù)據(jù)操縱: Select
,insert,update,delete,數(shù)據(jù)控制: grant,revoke 數(shù)據(jù)查詢: select

簡單 Linux 文件系統(tǒng)?

在 Linux 操作系統(tǒng)中,所有被操作系統(tǒng)管理的資源,例如網(wǎng)絡接口卡、磁盤驅(qū)動器、打印機、輸入輸出設備、普通文件或是目錄都被看作是一個文件。

  • 也就是說在 Linux 系統(tǒng)中有一個重要的概念:一切都是文件。其實這是 Unix 哲學的一個體現(xiàn),而Linux 是重寫 Unix 而來,所以這個概念也就傳承了下來。在 Unix 系統(tǒng)中,把一切資源都看作是文件,包括硬件設備。UNIX系統(tǒng)把每個硬件都看成是一個文件,通常稱為設備文件,這樣用戶就可以用讀寫文件的方式實現(xiàn)對硬件的訪問。
  • Linux 支持 5 種文件類型,如下圖所示:

整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

Linux 的目錄結(jié)構(gòu)是怎樣的?

這個問題,一般不會問。更多是實際使用時,需要知道。

  • Linux 文件系統(tǒng)的結(jié)構(gòu)層次鮮明,就像一棵倒立的樹,最頂層是其根目錄:

整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

Unix和Linux有什么區(qū)別?

Linux和Unix都是功能強大的操作系統(tǒng),都是應用廣泛的服務器操作系統(tǒng),有很多相似之處,甚至有一部分人錯誤地認為Unix和Linux操作系統(tǒng)是一樣的,然而,事實并非如此,以下是兩者的區(qū)別。

  1. 開源性
    Linux是一款開源操作系統(tǒng),不需要付費,即可使用;Unix是一款對源碼實行知識產(chǎn)權(quán)保護的傳統(tǒng)商業(yè)軟件,使用需要付費授權(quán)使用。
  2. 跨平臺性
    Linux操作系統(tǒng)具有良好的跨平臺性能,可運行在多種硬件平臺上;Unix操作系統(tǒng)跨平臺性能較弱,大多需與硬件配套使用。
  3. 可視化界面
    Linux除了進行命令行操作,還有窗體管理系統(tǒng);Unix只是命令行下的系統(tǒng)。
  4. 硬件環(huán)境
    Linux操作系統(tǒng)對硬件的要求較低,安裝方法更易掌握;Unix對硬件要求比較苛刻,按照難度較大。
  5. 用戶群體
    Linux的用戶群體很廣泛,個人和企業(yè)均可使用;Unix的用戶群體比較窄,多是安全性要求高
    的大型企業(yè)使用,如銀行、電信部門等,或者Unix硬件廠商使用,如Sun等。
    相比于Unix操作系統(tǒng),Linux操作系統(tǒng)更受廣大計算機愛好者的喜愛,主要原因是Linux操作系統(tǒng)具有Unix操作系統(tǒng)的全部功能,并且能夠在普通PC計算機上實現(xiàn)全部的Unix特性,開源免費的特性,更容易普及使用!

什么是 Linux 內(nèi)核?

  • Linux 系統(tǒng)的核心是內(nèi)核。內(nèi)核控制著計算機系統(tǒng)上的所有硬件和軟件,在必要時分配硬件,并根據(jù)需要執(zhí)行軟件。
  1. 系統(tǒng)內(nèi)存管理
  2. 應用程序管理
  3. 硬件設備管理
  4. 文件系統(tǒng)管理

Linux 的體系結(jié)構(gòu)

  • 從大的方面講,Linux 體系結(jié)構(gòu)可以分為兩塊:

整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

  • 用戶空間(User Space) :用戶空間又包括用戶的應用程序(User Applications)、C 庫(C Library) 。
  • 內(nèi)核空間(Kernel Space) :內(nèi)核空間又包括系統(tǒng)調(diào)用接口(System Call Interface)、內(nèi)核(Kernel)、平臺架構(gòu)相關(guān)的代碼(Architecture-Dependent Kernel Code) 。

為什么 Linux 體系結(jié)構(gòu)要分為用戶空間和內(nèi)核空間的原因?

1、現(xiàn)代 CPU 實現(xiàn)了不同的工作模式,不同模式下 CPU 可以執(zhí)行的指令和訪問的寄存器不同。
2、Linux 從 CPU 的角度出發(fā),為了保護內(nèi)核的安全,把系統(tǒng)分成了兩部分。
用戶空間和內(nèi)核空間是程序執(zhí)行的兩種不同的狀態(tài),我們可以通過兩種方式完成用戶空間到內(nèi)核空
間的轉(zhuǎn)移:

  • 系統(tǒng)調(diào)用;
  • 硬件中斷。

JVM內(nèi)存模型的相關(guān)知識了解多少,比如重排序,內(nèi)存屏障,happen-before,主內(nèi)存,工作內(nèi)存。

思路: 先畫出Java內(nèi)存模型圖,結(jié)合例子volatile ,說明什么是重排序,內(nèi)存屏障,最好能給面試官寫以下demo說明。

1)Java內(nèi)存模型圖:

整整7天,梳理 Java開發(fā)2022年(圖文+代碼)面試題及答案

Java內(nèi)存模型規(guī)定了所有的變量都存儲在主內(nèi)存中,每條線程還有自己的工作內(nèi)存,線程的工作內(nèi)存中保存了該線程中是用到的變量的主內(nèi)存副本拷貝,線程對變量的所有操作都必須在工作內(nèi)存中進行,而不能直接讀寫主內(nèi)存。不同的線程之間也無法直接訪問對方工作內(nèi)存中的變量,線程間變量的傳遞均需要自己的工作內(nèi)存和主存之間進行數(shù)據(jù)同步進行。

2)指令重排序。

在這里,先看一段代碼

public class PossibleReordering {static int x = 0, y = 0;static int a = 0, b = 0;public static void main(String[] args) throws InterruptedException {Thread one = new Thread(new Runnable() { public void run() { a = 1; x = b; }});Thread other = new Thread(new Runnable() { public void run() { b = 1; y = a; }}); one.start();other.start(); one.join();other.join(); System.out.println(“(” x “,” y “)”);}

運行結(jié)果可能為(1,0)、(0,1)或(1,1),也可能是(0,0)。因為,在實際運行時,代碼指令可能并不是嚴格按照代碼語句順序執(zhí)行的。大多數(shù)現(xiàn)代微處理器都會采用將指令亂序執(zhí)行(out-of-order execution,簡稱OoOE或OOE)的方法,在條件允許的情況下,直接運行當前有能力立即執(zhí)行的后續(xù)指令,避開獲取下一條指令所需數(shù)據(jù)時造成的等待3。通過亂序執(zhí)行的技術(shù),處理器可以大大提高執(zhí)行效率。而這就是指令重排。

3)內(nèi)存屏障

內(nèi)存屏障,也叫內(nèi)存柵欄,是一種CPU指令,用于控制特定條件下的重排序和內(nèi)存可見性問題。

  • LoadLoad屏障:對于這樣的語句Load1; LoadLoad; Load2,在Load2及后續(xù)讀取操作要讀取的數(shù)據(jù)被訪問前,保證Load1要讀取的數(shù)據(jù)被讀取完畢。
  • StoreStore屏障:對于這樣的語句Store1; StoreStore; Store2,在Store2及后續(xù)寫入操作執(zhí)行前,保證Store1的寫入操作對其它處理器可見。
  • LoadStore屏障:對于這樣的語句Load1; LoadStore; Store2,在Store2及后續(xù)寫入操作被刷出前,保證Load1要讀取的數(shù)據(jù)被讀取完畢。
  • StoreLoad屏障:對于這樣的語句Store1; StoreLoad; Load2,在Load2及后續(xù)所有讀取操作執(zhí)行
    前,保證Store1的寫入對所有處理器可見。它的開銷是四種屏障中最大的。 在大多數(shù)處理器的實現(xiàn)中,這個屏障是個萬能屏障,兼具其它三種內(nèi)存屏障的功能。

4)happen-before原則

  • 單線程happen-before原則:在同一個線程中,書寫在前面的操作happen-before后面的操作。鎖的happen-before原則:同一個鎖的unlock操作happen-before此鎖的lock操作。
  • volatile的happen-before原則:對一個volatile變量的寫操作happen-before對此變量的任意操作(當然也包括寫操作了)。
  • happen-before的傳遞性原則:如果A操作 happen-before B操作,B操作happen-before C操作,那么A操作happen-before C操作。
  • 線程啟動的happen-before原則:同一個線程的start方法happen-before此線程的其它方法。
  • 線程中斷的happen-before原則 :對線程interrupt方法的調(diào)用happen-before被中斷線程的檢測到中斷發(fā)送的代碼。
  • 線程終結(jié)的happen-before原則: 線程中的所有操作都happen-before線程的終止檢測。
  • 對象創(chuàng)建的happen-before原則: 一個對象的初始化完成先于他的finalize方法調(diào)用。

怎么打出線程棧信息

思路: 可以說一下jps,top ,jstack這幾個命令,再配合一次排查線上問題進行解答。

  • 輸入jps,獲得進程號。
  • top -Hp pid 獲取本進程中所有線程的CPU耗時性能
  • jstack pid命令查看當前java進程的堆棧狀態(tài)
  • 或者 jstack -l > /tmp/output.txt 把堆棧信息打到一個txt文件。
  • 可以使用fastthread 堆棧定位,fastthread.io/

相關(guān)新聞

聯(lián)系我們
聯(lián)系我們
公眾號
公眾號
在線咨詢
分享本頁
返回頂部