天天看點

面試總結之20201101

一、什麼是泛型、為什麼要使用以及泛型擦除

泛型,即“參數化類型”。

建立集合時就指定集合元素的類型,該集合隻能儲存其指定類型的元素,避免使用強制類型轉換。

Java編譯器生成的位元組碼是不包涵泛型資訊的,

泛型類型資訊 将在編譯處理是被擦除,這個過程即類型擦除。泛型擦除可以簡單的了解為将 泛型java代碼

轉換為普通java代碼,隻不過編譯器更直接點,将泛型java代碼直接轉換成普通java位元組碼。

類型擦除的主要過程如下:

1).将所有的泛型參數用其最左邊界(最頂級的父類型)類型替換。

2).移除所有的類型參數。

二、Java中的集合類

List和Set繼承自Collection接口。

Set無序不允許元素重複。HashSet和TreeSet是兩個主要的實作類。

List有序且允許元素重複。ArrayList、LinkedList和Vector是三個主要的實作類。

Map也屬于集合系統,但和Collection接口沒關系。Map是key對value的映射集合,其中key列就是一個集合。key不能重複,但是value可以重複。HashMap、TreeMap和Hashtable是三個主要的實作類。

SortedSet和SortedMap接口對元素按指定規則排序,SortedMap是對key列進行排序。

三、HashMap和HashTable差別

1).HashTable的方法前面都有synchronized來同步,是線程安全的;HashMap未經同步,是非線程安全的。

2).HashTable不允許null值(key和value都不可以) ;HashMap允許null值(key和value都可以)。

3).HashTable有一個contains(Object

value)功能和containsValue(Object

value)功能一樣。

4).HashTable使用Enumeration進行周遊;HashMap使用Iterator進行周遊。

5).HashTable中

hash數組

預設大小是11,增加的方式是old*2+1;HashMap中hash數組的預設大小是16,而且一定是2的指數。

6).

哈希值 的使用不同,HashTable直接使用對象的hashCode; HashMap重新計算 hash值

,而且用與代替求模。

四、ArrayList和vector差別

ArrayList和Vector都實作了List接口,都是通過數組實作的。

Vector是線程安全的,而ArrayList是非線程安全的。

List第一次建立的時候,會有一個初始大小,随着不斷向List中增加元素,當List 認為容量不夠的時候就會進行擴容。Vector預設情況下自動增長原來一倍的

數組長度

,ArrayList增長原來的50%

五、ArrayList和LinkedList差別及使用場景

差別

ArrayList底層是用數組實作的,可以認為ArrayList是一個可改變大小的數組。随着越來越多的元素被添加到ArrayList中,其規模是動态增加的。

LinkedList底層是通過雙向連結清單實作的, LinkedList和ArrayList相比,增删的速度較快。但是查詢和修改值的速度較慢。同時,LinkedList還實作了Queue接口,是以他還提供了offer(),peek(), poll()等方法。使用場景

LinkedList更适合從中間插入或者删除(連結清單的特性)。

ArrayList更适合檢索和在末尾插入或删除(數組的特性)

六、

多線程

的實作方式

繼承Thread類、實作Runnable接口、使用ExecutorService、Callable、Future實作有傳回結果的多線程。

七、線程的狀态轉換

面試總結之20201101

八、synchronized和Lock的差別

主要相同點:Lock能完成synchronized所實作的所有功能主要不同點:Lock有比synchronized更精确的線程語義和更好的性能。Lock的鎖定是通過代碼實作的,而synchronized是在JVM層面上實作的,synchronized會自動釋放鎖,而Lock一定要求程式員手工釋放,并且必須在finally從句中釋放。Lock還有更強大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。Lock鎖的範圍有局限性,塊範圍,而synchronized可以鎖住塊、對象、類。

九、Spring中Bean的

生命周期

在傳統的Java應用中,bean的生命周期很簡單,使用Java關鍵字 new 進行Bean 的執行個體化,然後該Bean 就能夠使用了。一旦bean不再被使用,則由Java自動進行垃圾回收。

相比之下,Spring管理Bean的生命周期就複雜多了,正确了解Bean 的生命周期非常重要,因為Spring對Bean的管理可擴充性非常強,下面展示了一個Bean的構造過程

面試總結之20201101
如上圖所示,Bean 的生命周期還是比較複雜的,下面來對上圖每一個步驟做文字描述:

  1. Spring啟動,查找并加載需要被Spring管理的bean,進行Bean的執行個體化
  2. Bean執行個體化後對将Bean的引入和值注入到Bean的屬性中
  3. 如果Bean實作了BeanNameAware接口的話,Spring将Bean的Id傳遞給setBeanName()方法
  4. 如果Bean實作了BeanFactoryAware接口的話,Spring将調用setBeanFactory()方法,将BeanFactory容器執行個體傳入
  5. 如果Bean實作了ApplicationContextAware接口的話,Spring将調用Bean的setApplicationContext()方法,将bean所在應用上下文引用傳入進來。
  6. 如果Bean實作了BeanPostProcessor接口,Spring就将調用他們的postProcessBeforeInitialization()方法。
  7. 如果Bean 實作了InitializingBean接口,Spring将調用他們的afterPropertiesSet()方法。類似的,如果bean使用init-method聲明了初始化方法,該方法也會被調用
  8. 如果Bean 實作了BeanPostProcessor接口,Spring就将調用他們的postProcessAfterInitialization()方法。
  9. 此時,Bean已經準備就緒,可以被 應用程式 使用了。他們将一直駐留在應用上下文中,直到應用上下文被銷毀。
  10. 如果bean實作了DisposableBean接口,Spring将調用它的destory()接口方法,同樣,如果bean使用了 destory-method 聲明銷毀方法,該方法也會被調用。

十、對于Spring AOP 機制的了解

OOP面向對象,允許開發者定義縱向的關系,但并适用于定義橫向的關系,導緻了大量代碼的重複,而不利于各個子產品的重用。

AOP,一般稱為面向切面,作為面向對象的一種補充,用于将那些與業務無關,但卻對多個對象産生影響的公共行為和邏輯,抽取并封裝為一個可重用的子產品,這個子產品被命名為“切面”(Aspect),減少系統中的重複代碼,降低了子產品間的耦合度,同時提高了系統的可維護性。可用于權限認證、日志、事務處理。

AOP實作的關鍵在于 代理模式,AOP代理主要分為靜态代理和動态代理。靜态代理的代表為AspectJ;動态代理則以Spring AOP為代表。

(1)Aspect就是靜态代理的增強,所謂靜态代理,就是AOP架構會在編譯階段生成AOP代理類,是以也稱為編譯時增強,他會在編譯階段将AspectJ(切面)織入到Java位元組碼中,運作的時候就是增強之後的AOP對象。

(2)Spring AOP使用的動态代理,所謂的動态代理就是說AOP架構不會去修改位元組碼,而是每次運作時在記憶體中臨時為方法生成一個AOP對象,這個AOP對象包含了目标對象的全部方法,并且在特定的切點做了增強處理,并回調原對象的方法。

十一、Spring AOP中的動态代理主要有兩種方式,JDK動态代理和CGLIB動态代理:

1、JDK動态代理隻提供接口的代理,不支援類的代理。核心InvocationHandler接口和Proxy類,InvocationHandler 通過invoke()方法反射來調用目标類中的代碼,動态地将橫切邏輯和業務編織在一起;接着,Proxy利用 InvocationHandler動态建立一個符合某一接口的的執行個體, 生成目标類的代理對象。

2、如果代理類沒有實作 InvocationHandler 接口,那麼Spring AOP會選擇使用CGLIB來動态代理目标類。CGLIB(Code Generation Library),是一個代碼生成的類庫,可以在運作時動态的生成指定類的一個

子類對象

,并覆寫其中特定方法并添加增強代碼,進而實作AOP。CGLIB是通過繼承的方式做的動态代理,是以如果某個類被标記為final,那麼它是無法使用CGLIB做動态代理的。

3、靜态代理與動态代理差別在于生成AOP代理對象的時機不同,相對來說AspectJ的靜态代理方式具有更好的性能,但是AspectJ需要特定的編譯器進行處理,而Spring AOP則無需特定的編譯器處理

十二、Spring的IoC了解

(1)IOC就是控制反轉,是指建立對象的控制權的轉移,以前建立對象的主動權和時機是由自己把控的,而現在這種權力轉移到Spring容器中,并由容器根據配置檔案去建立執行個體和管理各個執行個體之間的依賴關系,對象與對象之間松散耦合,也利于功能的複用。DI依賴注入,和控制反轉是同一個概念的不同角度的描述,即 應用程式在運作時依賴IoC容器來動态注入對象需要的外部資源。

(2)最直覺的表達就是,IOC讓對象的建立不用去new了,可以由spring自動生産,使用java的反射機制,根據配置檔案在運作時動态的去建立對象以及管理對象,并調用對象的方法的。

(3)Spring的IOC有三種注入方式 :構造器注入、setter方法注入、根據注解注入。

十三、Spring的自動裝配:

在spring中,對象無需自己查找或建立與其關聯的其他對象,由容器負責把需要互相協作的對象引用賦予各個對象,使用autowire來配置自動裝載模式。

在Spring架構xml配置中共有5種自動裝配:

(1)no:預設的方式是不進行自動裝配的,通過手工設定ref屬性來進行裝配bean。

(2)byName:通過bean的名稱進行自動裝配,如果一個bean的 property 與另一bean 的name 相同,就進行自動裝配。

(3)byType:通過參數的資料類型進行自動裝配。

(4)constructor:利用構造函數進行裝配,并且構造函數的參數通過byType進行裝配。

(5)autodetect:自動探測,如果有構造方法,通過 construct的方式自動裝配,否則使用 byType的方式自動裝配。

基于注解的方式:

使用@Autowired注解來自動裝配指定的bean。在使用@Autowired注解之前需要在Spring配置檔案進行配置,<context:annotation-config />。在啟動spring IoC時,容器自動裝載了一個AutowiredAnnotationBeanPostProcessor後置處理器,當容器掃描到@Autowied、@Resource或@Inject時,就會在IoC容器自動查找需要的bean,并裝配給該對象的屬性。在使用@Autowired時,首先在容器中查詢對應類型的bean:

如果查詢結果剛好為一個,就将該bean裝配給@Autowired指定的資料;

如果查詢的結果不止一個,那麼@Autowired會根據名稱來查找;

如果上述查找的結果為空,那麼會抛出異常。解決方法時,使用

required=false

@Autowired可用于:構造函數、

成員變量

、Setter方法

注:@Autowired和@Resource之間的差別

(1) @Autowired預設是按照類型裝配注入的,預設情況下它要求依賴對象必須存在(可以設定它required屬性為false)。

(2) @Resource預設是按照名稱來裝配注入的,隻有當找不到與名稱比對的bean才會按照類型來裝配注入。

十四、Spring 架構中都用到了哪些設計模式?

(1)

工廠模式

:BeanFactory就是簡單工廠模式的展現,用來建立對象的執行個體;

(2)單例模式:Bean預設為單例模式。

(3)代理模式:Spring的AOP功能用到了JDK的動态代理和CGLIB位元組碼生成技術;

(4)模闆方法:用來解決代碼重複的問題。比如. RestTemplate, JmsTemplate, JpaTemplate。

(5)觀察者模式:定義對象鍵一種一對多的依賴關系,當一個對象的狀态發生改變時,所有依賴于它的對象都會得到通知被制動更新,如Spring中listener的實作--ApplicationListener。