2019年Java面試題總結(附答案,最後更新:2019-10-20)

不定時更新,離線版本下載:點此下載

1. JAVA中的幾種基本類型,各佔用多少字節?

|--------------±------------±-------±-------±----±-------±-------±------±------------|
| 數據類型 | boolean | byte | short | int | long | char | float | double |
| 佔用字節 |             1 |      1 |        2 |   4 |       8 |      2 |      4 |           8 |
|--------------±------------±-------±-------±----±-------±-------±------±------------|

2. String能被繼承嗎?爲什麼?

不可以,因爲String類有final修飾符.

3. ArrayList 和 LinkedList 有什麼區別?

ArrayList和LinkedList都實現了List接口,有以下的不同點:
ArrayList是數組結構,查找快,增刪慢。
LinkedList是鏈表結構,增刪快,查找慢。
LinkedList比ArrayList更佔內存,因爲LinkedList爲每一個節點存儲了兩個引用。

4. 抽象類和接口的區別?
  1. 抽象類和接口都不能直接實例化
  2. 抽象類要被子類繼承,接口要被類實現。
  3. 接口只能做方法聲明,抽象類中可以做方法聲明,也可以做方法實現。
  4. 接口裏定義的變量只能是公共的靜態的常量,抽象類中的變量是普通變量。
  5. 抽象類裏的抽象方法必須全部被子類所實現,如果子類不能全部實現父類抽象方法,那麼該子類只能是抽象類。
  6. 抽象方法只能聲明,不能實現。
  7. 接口可繼承接口,並可多繼承接口,但類只能單根繼承。
5. 反射的原理,反射創建類實例的三種方式是什麼?

反射是指程序在運行時能夠動態的獲取到一個類的類型信息的一種操作.

1.調用類的Class對象的newInstance方法,該方法會調用對象的默認構造器,如果沒有默認構造器,會調用失敗.

Class<?> classType = ExtendType.class;                                                                                     
Object inst = classType.newInstance();                                                                                     
System.out.println(inst);           

2.調用默認Constructor對象的newInstance方法

Class<?> classType = ExtendType.class;                                                                                     
Constructor<?> constructor1 = classType.getConstructor();                                                                  
Object inst = constructor1.newInstance();                                                                                  
System.out.println(inst);                                                                                                  

3.調用帶參數Constructor對象的newInstance方法

Constructor<?> constructor2 = classType.getDeclaredConstructor(int.class,String.class);                                                                 
Object inst = constructor2.newInstance(1, "123");                                                                          
System.out.println(inst);
6. 寫出三種單例模式的實現。
  1. 懶漢模式,線程不安全
public class Singleton {
    private static Singleton instance;
    private Singleton (){}

    public static synchronized Singleton getInstance() {
	if (instance == null) {
	    instance = new Singleton();
	}
	return instance;
    }
}
  1. 餓漢模式
public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}
  1. 枚舉
public enum Singleton {
    INSTANCE;
    public void whateverMethod() {
    }
}
7. 深拷貝和淺拷貝區別。

淺拷貝只複製指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。
但深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。

8. Error和Exception的區別。

Exception是java程序運行中可預料的異常情況,可以獲取到這種異常,並且對這種異常進行業務外的處理。

Error是java程序運行中不可預料的異常情況,這種異常發生以後,會直接導致JVM不可處理或者不可恢復的情況.

9. CheckedException 和 RuntimeException 的區別。

RuntimeException在默認情況下會得到自動處理。所以通常用不着捕獲RuntimeException,但在自己的封裝裏,也許仍然要選擇拋出一部分RuntimeException。

除了runtimeException以外的異常,都屬於checkedException,它們都在java.lang庫內部定義。Java編譯器要求程序必須捕獲或聲明拋出這種異常。

10. 請列出 5 個運行時異常。
Java.lang.NumberFormatException
Java.lang.IndexOutOfBoundsException
Java.lang.ArrayIndexOutOfBoundsException
Java.lang.NullPointerException
Java.lang.ArrayStoreExcetpion
11. 在什麼場景下需要重新實現hashCode和equals方法?

equals方法比較的是兩個對象是否指向同一個地址,當我們需要適用equals
比較對象的屬性是否相同時,就需要重寫equals方法。

如果重寫了equals方法就必須重寫hashCode方法,否則會降低map等集合的
索引速度。

12. 泛型的存在是用來解決什麼問題?

泛型的好處是在編譯的時候檢查類型安全,並且所有的強制轉換都是自動和隱式的,提高代碼的重用率。

13. 什麼情況下會發生棧內存溢出?

如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常。
如果虛擬機在動態擴展棧時無法申請到足夠的內存空間,則拋出OutOfMemoryError異常。

14. 什麼是序列化和反序列化?爲什麼需要序列化和反序列化?

序列化是將對象轉換成字節流的過程。
反序列化是將字節流恢復成對象的過程。
序列化和反序列化主要解決數據的一致性問題。

15. JVM中一次完整的GC流程是怎樣的?
  • 剛開始,對象被分配在eden區,當eden區放不下時,將會觸發minorGC,
    將可達對象移動到s0區,將不可達垃圾對象清理掉,這一輪過後,
    eden就成空的了。

  • 如果eden又滿了,再次觸發minorGC,eden區的存活對象搬到s1區,然後
    將eden和s0區的垃圾清理掉,這一輪過後,eden和s0都變成了空的。

  • 隨着對象的不斷分配,eden 空可能又滿了,這時會重複剛纔的 minor GC 過程,
    不過要注意的是,這時候 s0 是空的,所以s0與s1的角色其實會互換,
    即:存活的對象,會從 eden 和 s1 區,向s0區移動。然後再把 eden 和 s1 區中的垃圾清除,這一輪完成後,eden 與 s1 區變成空的。

  • 對於那些比較“長壽”的對象一直在 s0 與 s1 中挪來挪去,一來很佔地方,而且也會造成一定開銷,降低 gc 效率,於是有了“代齡 (age)”及“晉升”。

  • 對象在年青代的 3 個區 (edge,s0,s1) 之間,每次從 1 個區移到另 1 區,年齡 +1,
    在 young 區達到一定的年齡閾值後,將晉升到老年代。即:挪動 8 次後,如果還活着,下次 minor GC 時,將移動到 Tenured 區。

  • 如果老年代,最終也放滿了,就會發生 major GC(即 Full GC),
    由於老年代的的對象通常會比較多,因爲標記 - 清理 - 整理(壓縮)的耗時通常會比較長,會讓應用出現卡頓的現象,這也是爲什麼很多應用要優化,儘量避免或減少 Full GC 的原因。

16. JVM中經典的垃圾回收器有哪些?
  • Serial收集器
  • ParNews收集器
  • Parallel Scavenge收集器
  • Serial Old收集器
  • Parallel Old收集器
  • CMS收集器
17. JVM常用參數有哪些?

-server
-Xms6000M
-Xmx6000M
-Xmn500M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-XX:SurvivorRatio=65536
-XX:MaxTenuringThreshold=0
-Xnoclassgc
-XX:+DisableExplicitGC
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled
-XX:-CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=90
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps

18. tomcat如何調優?
  • 啓動參數的配置
export JAVA_OPTS="-server -Xms1400M -Xmx1400M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:PermSize=128M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=31 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC  -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m  -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -Djava.awt.headless=true "
  • tomcat容器優化
    修改如下一行:
<Connector port="8080" protocol="HTTP/1.1"/>

修改如下所示:

<Connector port="8080" protocol="HTTP/1.1"
          URIEncoding="UTF-8"  minSpareThreads="25" maxSpareThreads="75"
          enableLookups="false" disableUploadTimeout="true"
          connectionTimeout="20000" acceptCount="300"  maxThreads="300" 
          maxProcessors="1000" minProcessors="5" 
          useURIValidationHack="false" compression="on" 
          compressionMinSize="2048"          	
          compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" redirectPort="8443"
/>

以上配置主要參數解釋:

  • maxSpareThreads :如果空閒狀態的線程數多於設置的數目,則將這些線程中止,減少這個池中的線程總數。
  • minSpareThreads :最小備用線程數,tomcat啓動時的初始化的線程數。
  • maxThreads :可創建的最大的線程數,即最大併發數。
  • acceptCount :當線程數達到maxThreads後,後續請求會被放入一個等待隊列,這個acceptCount是這個隊列的大小,如果這個隊列也滿了,就直接refuse connection.
  • maxProcessors :最大線程數。
  • minProcessors :最小線程數。
  • useURIValidationHack : URI檢查,關閉以節省開銷。
  • enableLookups :DNS查詢,關閉以節省開銷。
  • compression :on/off 開啓關閉gzip壓縮。
  • compressionMinSize:壓縮的輸出內容大小,默認爲2KB。即2048.
  • noCompressionUserAgents:不使用壓縮的瀏覽器。
  • compressableMimeType :壓縮類型。
19. 簡述spring加載流程。
  1. 創建全局上下文環境ServletContext.
  2. 觸發容器初始化contextInitialized方法.
  3. 創建上下文環境WebApplicationContext.
  4. 初始化web.xml配置。
  5. Servlet加載。
  6. 加載配置文件。
  7. 初始化springmvc相關對象(使用springmvc的情況下)。
20. spring的事務傳播行爲有哪些?
  • TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。
  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:創建一個新的事務,如果當前存在事務,則把當前事務掛起。
  • TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。
  • TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。
  • TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
  • TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則創建一個事務作爲當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價於 TransactionDefinition.PROPAGATION_REQUIRED。
21. spring事務配置示例。

關鍵元素有3個:

<!-- 事務管理器 -->
<bean id="transactionManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 事務Advice增強配置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="get*" read-only="true" />
		<tx:method name="*" propagation="REQUIRED"/>
	</tx:attributes>
</tx:advice>

<!-- 配置事務aop -->
<aop:config>
	<aop:pointcut id="userPointcut"
		expression="execution(* com.lcifn.spring.transaction.manager.UserManager.*(..))" />
	<aop:advisor advice-ref="txAdvice" pointcut-ref="userPointcut" />
</aop:config>
22. 創建對象有那幾種方式?
  1. new Object();
  2. 反射(newInstance())
  3. clone()
  4. 反序列化
23. 如何退出多重循環?

使用break.

here:
for(){
  for(){
    for(){
      break here;
    }
  }
}
24. String,StringBuffer,StringBuilder的區別?
  1. 運行速度:StringBuilder > StringBuffer > String。
  2. StringBuilder是線程不安全的,而StringBuffer是線程安全的。
  3. String是有final修飾符的,每次改變都會創建新的對象。效率很慢,適用於少量操作。
25. 創建線程有幾種方式?有什麼區別?
  1. 繼承Thead類
  2. 實現Runable接口
    第二種方法實現接口的同時可以繼承其它類,相對靈活。
26. Thead類的start()和run()有什麼區別?

調用start方法方可啓動線程,而run方法只是thread的一個普通方法調用,還是在主線程裏執行。

27. ArrayList和Array的區別?
  1. 數組效率高,但容量固定且無法動態改變。
  2. ArrayList: 容量可動態增長,但效率相對低些。底層採用的依舊是數組。
28. Java集合類框架的基礎接口有哪些?

ArrayList,LinkedList,HashSet,TreeSet,HashMap,TreeMap

29. 如何格式化時間?
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
30. 什麼條件下會出現死鎖?

死鎖產生的4個必要條件:

  • 互斥條件:進程要求對所分配的資源(如打印機)進行排他性控制,即在一段時間內某 資源僅爲一個進程所佔有。此時若有其他進程請求該資源,則請求進程只能等待。
  • 不剝奪條件:進程所獲得的資源在未使用完畢之前,不能被其他進程強行奪走,即只能 由獲得該資源的進程自己來釋放(只能是主動釋放)。
  • 請求和保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其他進程佔有,此時請求進程被阻塞,但對自己已獲得的資源保持不放。
  • 循環等待條件:存在一種進程資源的循環等待鏈,鏈中每一個進程已獲得的資源同時被 鏈中下一個進程所請求。
31. JVM特性有那些?
  1. 可移植性
  2. 成熟(超過15年的歷史)
  3. 覆蓋面
32. union 和 union all的區別.

union 結果集不包含重複數據,但效率低。
union all結果集包含重複數據,效率高。

33. left join和right join的區別?
  1. left join 返回包括左表中的所有記錄和右表中聯結字段相等的記錄
  2. right join 返回包括右表中的所有記錄和左表中聯結字段相等的記錄
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章