金三銀四立刻要來了,整理了Java一些經典面試題,也給出了答案,但願對你們有幫助,有哪裏你以爲不正確的話,歡迎指出,很是感謝。html
思路:能夠從它們的底層結構、是否容許存儲null,是否線性安全等幾個維度進行描述,最後能夠向面試官描述一下HashMap的死循環問題,以及ConcurrentHashMap爲啥放棄分段鎖。java
HashMap程序員
有關於HashMap死循環,有興趣能夠看看這篇文章,寫得很好: 老生常談,HashMap的死循環面試
有關於HashMap這些常量設計目的,也能夠看我這篇文章: 面試加分項-HashMap源碼中這些常量的設計目的redis
HashTable算法
ConcurrentHashMapspring
思路:從它們的底層數據結構、效率、開銷進行闡述數據庫
String:設計模式
StringBuffer:數組
StringBuilder:
基本類型 | 位數 | 字節 |
---|---|---|
int | 32 | 4 |
short | 16 | 2 |
long | 64 | 8 |
byte | 8 | 1 |
char | 16 | 2 |
float | 32 | 4 |
double | 64 | 8 |
boolean | 1 | 1/8 |
看例子:
public class Test {
public static void main(String[] args) {
System.out.println("Byte bit num: " + Byte.SIZE);
System.out.println("Short bit num : " + Short.SIZE);
System.out.println("Character bit num: " + Character.SIZE);
System.out.println("Integer bit num: " + Integer.SIZE);
System.out.println("Float bit num: " + Float.SIZE);
System.out.println("Long bit num: " + Long.SIZE);
System.out.println("Double bit num: " + Double.SIZE);
}
}
複製代碼
運行結果:
Byte bit num: 8
Short bit num : 16
Character bit num: 16
Integer bit num: 32
Float bit num: 32
Long bit num: 64
Double bit num: 64
複製代碼
String str ="whx";
String newStr =new String ("whx");
複製代碼
String str ="whx"
先在常量池中查找有沒有"whx" 這個對象,若是有,就讓str指向那個"whx".若是沒有,在常量池中新建一個「whx」對象,並讓str指向在常量池中新建的對象"whx"。
String newStr =new String ("whx");
是在堆中創建的對象"whx" ,在棧中建立堆中"whx" 對象的內存地址。
如圖所示:
這篇文章講的挺好的: String和New String()的區別
BIO
就是傳統的 java.io 包,它是基於流模型實現的,交互的方式是同步、阻塞方式,也就是說在讀入輸入流或者輸出流時,在讀寫動做完成以前,線程會一直阻塞在那裏,它們之間的調用時可靠的線性順序。它的有點就是代碼比較簡單、直觀;缺點就是 IO 的效率和擴展性很低,容易成爲應用性能瓶頸。
NIO
是 Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,能夠構建多路複用的、同步非阻塞 IO 程序,同時提供了更接近操做系統底層高性能的數據操做方式。
AIO
是 Java 1.7 以後引入的包,是 NIO 的升級版本,提供了異步非堵塞的 IO 操做方式,因此人們叫它 AIO(Asynchronous IO),異步 IO 是基於事件和回調機制實現的,也就是應用操做以後會直接返回,不會堵塞在那裏,當後臺處理完成,操做系統會通知相應的線程進行後續的操做。
以上內容來自這篇文章,你們能夠看一下,寫得比較詳細
Java反射機制:
Java 的反射機制是指在運行狀態中,對於任意一個類都可以知道這個類全部的屬性和方法; 而且對於任意一個對象,都可以調用它的任意一個方法;這種動態獲取信息以及動態調用對象方法的功能成爲Java語言的反射機制
獲取 Class 類對象三種方式:
能夠看一下我寫的這篇文章: 談談Java反射:從入門到實踐,再到原理
什麼是冪等性?一次和屢次請求某一個資源對於資源自己應該具備一樣的結果。就是說,其任意屢次執行對資源自己所產生的影響均與一次執行的影響相同。
實現冪等通常有如下幾種方式:
能夠看一下這篇文章,寫得不錯: 探討一下實現冪等性的幾種方式
直接看個例子吧:
public class Parent {
{
System.out.println("父類非靜態代碼塊");
}
static {
System.out.println("父類靜態塊");
}
public Parent() {
System.out.println("父類構造器");
}
}
public class Son extends Parent {
public Son() {
System.out.println("子類構造器");
}
static {
System.out.println("子類靜態代碼塊");
}
{
System.out.println("子類非靜態代碼塊");
}
}
public class Test {
public static void main(String[] args) {
Son son = new Son();
}
}
複製代碼
運行結果:
父類靜態塊
子類靜態代碼塊
父類非靜態代碼塊
父類構造器
子類非靜態代碼塊
子類構造器
複製代碼
因此,類實例化順序爲: 父類靜態代碼塊/靜態域->子類靜態代碼塊/靜態域 -> 父類非靜態代碼塊 -> 父類構造器 -> 子類非靜態代碼塊 -> 子類構造器
Class.forName和ClassLoader均可以對類進行加載。它們區別在哪裏呢? ClassLoader負責加載 Java 類的字節代碼到 Java 虛擬機中。Class.forName實際上是調用了ClassLoader,以下:
Class<?> forName(String name, boolean initialize, ClassLoader loader)
方法實現同樣的功能,它的源碼以下:
因此,Class.forName和ClassLoader的區別,就是在類加載的時候,class.forName有參數控制是否對類進行初始化。
這篇文章寫得不錯,描述Java動態代理的幾種實現方式,分別說出相應的優缺點
Error: 表示編譯時或者系統錯誤,如虛擬機相關的錯誤,OutOfMemoryError等,error是沒法處理的。
Exception: 代碼異常,Java程序員關心的基類型一般是Exception。它能被程序自己能夠處理,這也是它跟Error的區別。
它能夠分爲RuntimeException(運行時異常)和CheckedException(可檢查的異常)。 常見的RuntimeException異常:
- NullPointerException 空指針異常
- ArithmeticException 出現異常的運算條件時,拋出此異常
- IndexOutOfBoundsException 數組索引越界異常
- ClassNotFoundException 找不到類異常
- IllegalArgumentException(非法參數異常)
複製代碼
常見的 Checked Exception 異常:
- IOException (操做輸入流和輸出流時可能出現的異常)
- ClassCastException(類型轉換異常類)
複製代碼
有興趣能夠看我以前寫得這篇文章: Java程序員必備:異常的十個關鍵知識點
CAS涉及三個操做數
CAS思想:要進行更新時,認爲位置V上的值仍是跟A值相等,若是是是相等,就認爲它沒有被別的線程更改過,便可更新爲B值。不然,認爲它已經被別的線程修改過,不更新爲B的值,返回當前位置V最新的值。
有興趣的朋友能夠看一下我這篇文章,一次CAS思想解決實際問題: CAS樂觀鎖解決併發問題的一次實踐
複製了對象的引用地址,兩個對象指向同一個內存地址,因此修改其中任意的值,另外一個值都會隨之變化。
將對象及值複製過來,兩個對象修改其中任意的值另外一個值不會改變
這篇文章寫得很好: Java Serializable:明明就一個空的接口嘛
==
equals
AQS原理面試題的核心回答要點
能夠看我這篇文章:AQS解析與實戰
能夠看一下我這篇文章: Synchronized解析——若是你願意一層一層剝開個人心
對於Java線程池,這個流程圖比較重要:
能夠看我這篇文章: 面試必備:Java線程池解析
還有哪些經典Java面試題呢?你也能夠告訴我,哈哈。