2020年Java基礎高頻面試題彙總(1.4W字詳細解析)

一、 Java語言有哪些特色java

(1)簡單易學、有豐富的類庫mysql

(2)面向對象(Java最重要的特性,讓程序耦合度更低,內聚性更高)程序員

(3)與平臺無關性(JVM是Java跨平臺使用的根本)面試

(4)可靠安全算法

(5)支持多線程spring

二、面向對象和麪向過程的區別sql

面向過程:是分析解決問題的步驟,而後用函數把這些步驟一步一步地實現,而後在使用的時候一一調用則可。性能較高,因此單片機、嵌入式開發等通常採用面向過程開發數據庫

面向對象:是把構成問題的事務分解成各個對象,而創建對象的目的也不是爲了完成一個個步驟,而是爲了描述某個事物在解決整個問題的過程當中所發生的行爲。面向對象有封裝、繼承、多態的特性,因此易維護、易複用、易擴展。能夠設計出低耦合的系統。 可是性能上來講,比面向過程要低。編程

3 、八種基本數據類型的大小,以及他們的封裝類基本類型 大小(字節) 默認值 封裝類設計模式

v2-0220cd2c0104b5ed46b4f30cf075be14_720w.png

注:

1.int是基本數據類型,Integer是int的封裝類,是引用類型。int默認值是0,而Integer默認值是null,因此Integer能區分出0和null的狀況。一旦java看到null,就知道這個引用尚未指向某個對象,

2.基本數據類型在聲明時系統會自動給它分配空間,而引用類型聲明時只是分配了引用空間,必須經過實例化開闢數據空間以後才能夠賦值。數組對象也是一個引用對象,將一個數組賦值給另外一個數組時只是複製了一個引用,因此經過某一個數組所作的修改在另外一個數組中也看的見。

雖然定義了boolean這種數據類型,可是隻對它提供了很是有限的支持。在Java虛擬機中沒有任何供boolean值專用的字節碼指令,Java語言表達式所操做的boolean值,在編譯以後都使用Java虛擬機中的int數據類型來代替,而boolean數組將會被編碼成Java虛擬機的byte數組,每一個元素boolean元素佔8位。這樣咱們能夠得出boolean類型佔了單獨使用是4個字節,在數組中又是1個字節。使用int的緣由是,對於當下32位的處理器(CPU)來講,一次處理數據是32位(這裏不是指的是32/64位系統,而是指CPU硬件層面),具備高效存取的特色。

四、標識符的命名規則。

標識符的含義:

是指在程序中,咱們本身定義的內容,譬如,類的名字,方法名稱以及變量名稱等等,都是標識符。

命名規則:(硬性要求)

標識符能夠包含英文字母,0-9的數字,$以及_

標識符不能以數字開頭

標識符不是關鍵字

命名規範:(非硬性要求)

類名規範:首字符大寫,後面每一個單詞首字母大寫(大駝峯式)。

變量名規範:首字母小寫,後面每一個單詞首字母大寫(小駝峯式)。

方法名規範:同變量名。

五、instanceof 關鍵字的做用

instanceof 嚴格來講是Java中的一個雙目運算符,用來測試一個對象是否爲一個類的實例,用法爲:

Boolean result = obj instanceof Class

其中 obj 爲一個對象,Class 表示一個類或者一個接口,當 obj 爲 Class 的對象,或者是其直接或間接子類,或者是其接口的實現類,結果result 都返回 true,不然返回false。

注意:編譯器會檢查 obj 是否能轉換成右邊的class類型,若是不能轉換則直接報錯,若是不能肯定類型,則經過編譯,具體看運行時定。

int i = 0;System.out.println(i instanceof Integer);//編譯不經過 i必須是引用類型,不能是基本類型System.out.println(i instanceof Object);//編譯不經過Integer integer = new Integer(1);System.out.println(integer instanceof Integer);//true//false ,在 JavaSE規範 中對 instanceof 運算符的規定就是:若是 obj 爲 null,那麼將返回false。

六、Java自動裝箱與拆箱

裝箱就是自動將基本數據類型轉換爲包裝器類型(int-->Integer);調用方法:Integer的valueOf(int) 方法

拆箱就是自動將包裝器類型轉換爲基本數據類型(Integer-->int)。調用方法:Integer的intValue方法

在Java SE5以前,若是要生成一個數值爲10的Integer對象,必須這樣進行:

Integer i = new Integer(10);

而在從Java SE5開始就提供了自動裝箱的特性,若是要生成一個數值爲10的Integer對象,只須要這

樣就能夠了:

Integer i = 10;

七、 重載和重寫的區別

重寫(Override)

從字面上看,重寫就是 從新寫一遍的意思。其實就是在子類中把父類自己有的方法從新寫一遍。子類繼承了父類原有的方法,但有時子類並不想原封不動的繼承父類中的某個方法,因此在方法名,參數列表,返回類型(除過子類中方法的返回值是父類中方法返回值的子類時)都相同的狀況下, 對方法體進行修改或重寫,這就是重寫。但要注意子類函數的訪問修飾權限不能少於父類的。

public class Father {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Son s = new Son();
		s.sayHello();
	}
	public void sayHello() {
		System.out.println("Hello");
	}
}
class Son extends Father{
	@Override
	public void sayHello() {
		// TODO Auto-generated method stub
		System.out.println("hello by ");
	}
}

重寫 總結:

(1)發生在父類與子類之間

(2)方法名,參數列表,返回類型(除過子類中方法的返回類型是父類中返回類型的子類)必須相同

(3)訪問修飾符的限制必定要大於被重寫方法的訪問修飾符(public>protected>default>private)

(4)重寫方法必定不能拋出新的檢查異常或者比被重寫方法申明更加寬泛的檢查型異常

重載(Overload)

在一個類中,同名的方法若是有不一樣的參數列表(參數類型不一樣、參數個數不一樣甚至是參數順序不一樣

則視爲重載。同時,重載對返回類型沒有要求,能夠相同也能夠不一樣,但不能經過返回類型是否相同來

判斷重載

public static void main(String[] args) {
	// TODO Auto-generated method stub
	Father s = new Father();
	s.sayHello();
	s.sayHello("wintershii");
}
public void sayHello() {
	System.out.println("Hello");
}
public void sayHello(String name) {
	System.out.println("Hello" + " " + name);
}
}

重載 總結:

(1)重載Overload是一個類中多態性的一種表現

(2)重載要求同名方法的參數列表不一樣(參數類型,參數個數甚至是參數順序)

(3)重載的時候,返回值類型能夠相同也能夠不相同。沒法以返回型別做爲重載函數的區分標準

八、 equals與==的區別

== :

== 比較的是變量(棧)內存中存放的對象的(堆)內存地址,用來判斷兩個對象的地址是否相同,便是否是指相同一個對象。比較的是真正意義上的指針操做。

(1)比較的是操做符兩端的操做數是不是同一個對象。

(2)兩邊的操做數必須是同一類型的(能夠是父子類之間)才能編譯經過。

(3)比較的是地址,若是是具體的阿拉伯數字的比較,值相等則爲true,如:

int a=10 與 long b=10L 與 double c=10.0都是相同的(爲true),由於他們都指向地址爲10的堆。

equals

equals用來比較的是兩個對象的內容是否相等,因爲全部的類都是繼承自java.lang.Object類的,因此適用於全部對象,若是沒有對該方法進行覆蓋的話,調用的仍然是Object類中的方法,而Object中的equals方法返回的倒是==的判斷。

總結:

全部比較是否相等時,都是用equals 而且在對常量相比較時,把常量寫在前面,由於使用object的equals object可能爲null 則空指針在阿里的代碼規範中只使用equals ,阿里插件默認會識別,並能夠快速修改,推薦安裝阿里插件來排查老代碼使用「==」,替換成equals

九、 Hashcode的做用

java的集合有兩類,一類是List,還有一類是Set。前者有序可重複,後者無序不重複。當咱們在set中插入的時候怎麼判斷是否已經存在該元素呢,能夠經過equals方法。可是若是元素太多,用這樣的方法就會比較滿。

因而有人發明了哈希算法來提升集合中查找元素的效率。 這種方式將集合分紅若干個存儲區域,每一個對象能夠計算出一個哈希碼,能夠將哈希碼分組,每組分別對應某個存儲區域,根據一個對象的哈希碼就能夠肯定該對象應該存儲的那個區域。

hashCode方法能夠這樣理解:它返回的就是根據對象的內存地址換算出的一個值。這樣一來,當集合要添加新的元素時,先調用這個元素的hashCode方法,就一會兒能定位到它應該放置的物理位置上。若是這個位置上沒有元素,它就能夠直接存儲在這個位置上,不用再進行任何比較了;若是這個位置上已經有元素了,就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址。這樣一來實際調用equals方法的次數就大大下降了,幾乎只須要一兩次。

十、String、String StringBuffer 和 StringBuilder 的區別是什麼?

String是隻讀字符串,它並非基本數據類型,而是一個對象。從底層源碼來看是一個final類型的字符數組,所引用的字符串不能被改變,一經定義,沒法再增刪改。每次對String的操做都會生成新的String對象。

private final char value[];

每次+操做 : 隱式在堆上new了一個跟原字符串相同的StringBuilder對象,再調用append方法 拼接+後面的字符。

StringBuffer和StringBuilder他們兩都繼承了AbstractStringBuilder抽象類,從AbstractStringBuilder抽象類中咱們能夠看到

/**
* The value is used for character storage.
*/
char[] value;

他們的底層都是可變的字符數組,因此在進行頻繁的字符串操做時,建議使用StringBuffer和StringBuilder來進行操做。 另外StringBuffer 對方法加了同步鎖或者對調用的方法加了同步鎖,因此是線程安全的。StringBuilder 並無對方法進行加同步鎖,因此是非線程安全的。

十一、ArrayList和linkedList的區別

Array(數組)是基於索引(index)的數據結構,它使用索引在數組中搜索和讀取數據是很快的。

Array獲取數據的時間複雜度是O(1),可是要刪除數據倒是開銷很大,由於這須要重排數組中的全部數據,(由於刪除數據之後, 須要把後面全部的數據前移)

缺點: 數組初始化必須指定初始化的長度, 不然報錯

例如:

int[] a = new int[4];
//推介使用int[] 這種方式初始化
int c[] = {23,43,56,78};
//長度:4,索引範圍:[0,3]

List—是一個有序的集合,能夠包含重複的元素,提供了按索引訪問的方式,它繼承Collection。

List有兩個重要的實現類:ArrayList和LinkedList

ArrayList: 能夠看做是可以自動增加容量的數組

ArrayList的toArray方法返回一個數組

ArrayList的asList方法返回一個列表

ArrayList底層的實現是Array, 數組擴容實現

LinkList是一個雙鏈表,在添加和刪除元素時具備比ArrayList更好的性能.但在get與set方面弱於

ArrayList.固然,這些對比都是指數據量很大或者操做很頻繁。

十二、 HashMap和HashTable的區別

(1)二者父類不一樣

HashMap是繼承自AbstractMap類,而Hashtable是繼承自Dictionary類。不過它們都實現了同時實現了map、Cloneable(可複製)、Serializable(可序列化)這三個接口。

(2)對外提供的接口不一樣

Hashtable比HashMap多提供了elments() 和contains() 兩個方法。

elments() 方法繼承自Hashtable的父類Dictionnary。elements() 方法用於返回此Hashtable中的value的枚舉。

contains()方法判斷該Hashtable是否包含傳入的value。它的做用與containsValue()一致。事實上,contansValue() 就只是調用了一下contains() 方法。

(3)對null的支持不一樣

Hashtable:key和value都不能爲null。

HashMap:key能夠爲null,可是這樣的key只能有一個,由於必須保證key的惟一性;能夠有多個key值對應的value爲null。

(4)安全性不一樣

HashMap是線程不安全的,在多線程併發的環境下,可能會產生死鎖等問題,所以須要開發人員本身處理多線程的安全問題。

Hashtable是線程安全的,它的每一個方法上都有synchronized 關鍵字,所以可直接用於多線程中。雖然HashMap是線程不安全的,可是它的效率遠遠高於Hashtable,這樣設計是合理的,由於大部分的使用場景都是單線程。當須要多線程操做的時候可使用線程安全的ConcurrentHashMap。

ConcurrentHashMap雖然也是線程安全的,可是它的效率比Hashtable要高好多倍。由於

ConcurrentHashMap使用了分段鎖,並不對整個數據進行鎖定。

(5)計算hash值的方法不一樣

1三、 Collection包結構,與Collections的區別

Collection是集合類的上級接口,子接口有 Set、List、LinkedList、ArrayList、Vector、Stack、Set;Collections是集合類的一個幫助類, 它包含有各類有關集合操做的靜態多態方法,用於實現對各類集合的搜索、排序、線程安全化等操做。此類不能實例化,就像一個工具類,服務於Java的Collection框架。

1四、 Java的四種引用,強弱軟虛

強引用

強引用是日常中使用最多的引用,強引用在程序內存不足(OOM)的時候也不會被回收,使用方式:

String str = new String("str");

軟引用

軟引用在程序內存不足時,會被回收,使用方式:

// 注意:wrf這個引用也是強引用,它是指向SoftReference這個對象的,
// 這裏的軟引用指的是指向new String("str")的引用,也就是SoftReference類中T
SoftReference<String> wrf = new SoftReference<String>(new String("str"));

可用場景: 建立緩存的時候,建立的對象放進緩存中,當內存不足時,JVM就會回收早先建立的對象。

弱引用

弱引用就是隻要JVM垃圾回收器發現了它,就會將之回收,使用方式:

WeakReference<String> wrf = new WeakReference<String>(str);

可用場景: Java源碼中的 java.util.WeakHashMap中的 key就是使用弱引用,個人理解就是,一旦我不須要某個引用,JVM會自動幫我處理它,這樣我就不須要作其它操做。

虛引用

虛引用的回收機制跟弱引用差很少,可是它被回收以前,會被放入 ReferenceQueue中。注意哦,其它引用是被JVM回收後才被傳入 ReferenceQueue中的。因爲這個機制,因此虛引用大多被用於引用銷燬前的處理工做。還有就是,虛引用建立的時候,必須帶有 ReferenceQueue,使用

例子:

PhantomReference<String> prf = new PhantomReference<String>(new
String("str"), new ReferenceQueue<>());

可用場景: 對象銷燬前的一些操做,好比說資源釋放等。** Object.finalize()雖然也能夠作這類動做,可是這個方式即不安全又低效

1五、 泛型經常使用特色 (待補充)

泛型是Java SE 1.5以後的特性, 《Java 核心技術》中對泛型的定義是:

「泛型」 意味着編寫的代碼能夠被不一樣類型的對象所重用。

「泛型」,顧名思義,「泛指的類型」。咱們提供了泛指的概念,但具體執行的時候卻能夠有具體的規則來約束,好比咱們用的很是多的ArrayList就是個泛型類,ArrayList做爲集合能夠存放各類元素,如Integer, String,自定義的各類類型等,但在咱們使用的時候經過具體的規則來約束,如咱們能夠約束集合中只存放Integer類型的元素,如

List<Integer> iniData = new ArrayList<>()

使用泛型的好處?

以集合來舉例,使用泛型的好處是咱們沒必要由於添加元素類型的不一樣而定義不一樣類型的集合,如整型集合類,浮點型集合類,字符串集合類,咱們能夠定義一個集合來存放整型、浮點型,字符串型數據,而這並非最重要的,由於咱們只要把底層存儲設置了Object便可,添加的數據所有均可向上轉型爲Object。 更重要的是咱們能夠經過規則按照本身的想法控制存儲的數據類型。

1六、Java建立對象有幾種方式?

java中提供瞭如下四種建立對象的方式:

(1)new建立新對象

(2)經過反射機制

(3)採用clone機制

(4)經過序列化機制

1七、有沒有可能兩個不相等的對象有相同的hashcode

有可能.在產生hash衝突時,兩個不相等的對象就會有相同的 hashcode 值.當hash衝突產生時,通常有如下幾種方式來處理:

(1)拉鍊法:每一個哈希表節點都有一個next指針,多個哈希表節點能夠用next指針構成一個單向鏈表,被分配到同一個索引上的多個節點能夠用這個單向鏈表進行存儲.

(2)開放定址法:一旦發生了衝突,就去尋找下一個空的散列地址,只要散列表足夠大,空的散列地址總能找到,並將記錄存入

(3)再哈希:又叫雙哈希法,有多個不一樣的Hash函數.當發生衝突時,使用第二個,第三個….等哈希函數計算地址,直到無衝突.

1八、深拷貝和淺拷貝的區別是什麼?

淺拷貝:被複制對象的全部變量都含有與原來的對象相同的值,而全部的對其餘對象的引用仍然指向原來的對象.換言之,淺拷貝僅僅複製所考慮的對象,而不復制它所引用的對象.

深拷貝:被複制對象的全部變量都含有與原來的對象相同的值.而那些引用其餘對象的變量將指向被複制過的新對象.而再也不是原有的那些被引用的對象.換言之.深拷貝把要複製的對象所引用的對象都

1九、final有哪些用法?

final也是不少面試喜歡問的地方,但我以爲這個問題很無聊,一般能回答下如下5點就不錯了:

(1)被final修飾的類不能夠被繼承

(2)被final修飾的方法不能夠被重寫

(3)被final修飾的變量不能夠被改變.若是修飾引用,那麼表示引用不可變,引用指向的內容可變.

(4)被final修飾的方法,JVM會嘗試將其內聯,以提升運行效率

(5)被final修飾的常量,在編譯階段會存入常量池中.

除此以外,編譯器對final域要遵照的兩個重排序規則更好:

在構造函數內對一個final域的寫入,與隨後把這個被構造對象的引用賦值給一個引用變量,這兩個操做之間不能重排序

初次讀一個包含final域的對象的引用,與隨後初次讀這個final域,這兩個操做之間不能重排序.

20、static都有哪些用法?

全部的人都知道static關鍵字這兩個基本的用法:靜態變量和靜態方法.也就是被static所修飾的變量/方法都屬於類的靜態資源,類實例所共享.

除了靜態變量和靜態方法以外,static也用於靜態塊,多用於初始化操做:

public calss PreCache{
	static{
		//執行相關操做
	}
}

此外static也多用於修飾內部類,此時稱之爲靜態內部類.

最後一種用法就是靜態導包,即 import static.import static是在JDK 1.5以後引入的新特性,能夠用來指定導入某個類中的靜態資源,而且不須要使用類名,能夠直接使用資源名,好比:

import static java.lang.Math.*;
public class Test{
	public static void main(String[] args){
		//System.out.println(Math.sin(20));傳統作法
		System.out.println(sin(20));
	}
}

2一、3*0.1 0.3返回值是什麼

false,由於有些浮點數不能徹底精確的表示出來.

2二、a=a+b與a+=b有什麼區別嗎?

操做符會進行隱式自動類型轉換,此處a+=b隱式的將加操做的結果類型強制轉換爲持有結果的類型,

byte a = 127;
byte b = 127;
b = a + b;
// 報編譯錯誤:cannot convert from int to byte
b += a;

如下代碼是否有錯,有的話怎麼改?

short s1= 1;
s1 = s1 + 1;

有錯誤.short類型在進行運算時會自動提高爲int類型,也就是說 s1+1的運算結果是int類型,而s1是short類型,此時編譯器會報錯.

正確寫法:

short s1= 1;
s1 += 1;

+=操做符會對右邊的表達式結果強轉匹配左邊的數據類型,因此沒錯.

2三、try catch finally,try裏有return,finally還執行麼?

執行,而且finally的執行早於try裏面的return

結論:

(1)無論有木有出現異常,finally塊中代碼都會執行;

(2)當try和catch中有return時,finally仍然會執行;

(3)finally是在return後面的表達式運算後執行的(此時並無返回運算後的值,而是先把要返回的值保存起來,管finally中的代碼怎麼樣,返回的值都不會改變,任然是以前保存的值),因此函數返回值是在finally執行前肯定的;

(4)finally中最好不要包含return,不然程序會提早退出,返回值不是try或catch中保存的返回值。

2四、 Excption與Error包結構

Java可拋出(Throwable)的結構分爲三種類型:被檢查的異常(CheckedException),運行時異常(RuntimeException),錯誤(Error)。

運行時異常

定義:RuntimeException及其子類都被稱爲運行時異常。

特色:Java編譯器不會檢查它。也就是說,當程序中可能出現這類異常時,假若既"沒有經過throws聲明拋出它",也"沒有用try-catch語句捕獲它",仍是會編譯經過。例如,除數爲零時產生的ArithmeticException異常,數組越界時產生的IndexOutOfBoundsException異常,fail-fast機制產生的ConcurrentModificationException異常(java.util包下面的全部的集合類都是快速失敗的,「快速失敗」也就是fail-fast,它是Java集合的一種錯誤檢測機制。當多個線程對集合進行結構上的改變的操做時,有可能會產生fail-fast機制。記住是有可能,而不是必定。例如:假設存在兩個線程(線程一、線程2),線程1經過Iterator在遍歷集合A中的元素,在某個時候線程2修改了集合A的結構(是結構上面的ConcurrentModificationException 異常,從而產生fail-fast機制,這個錯叫併發修改異常。Fail-safe,java.util.concurrent包下面的全部的類都是安全失敗的,在遍歷過程當中,若是已經遍歷的數組上的內容變化了,迭代器不會拋出ConcurrentModificationException異常。若是未遍歷的數組上的內容發生了變化,則有可能反映到迭代過程當中。這就是ConcurrentHashMap迭代器弱一致的表現。ConcurrentHashMap的弱一致性主要是爲了提高效率,是一致性與效率之間的一種權衡。要成爲強一致性,就獲得處使用鎖,甚至是全局鎖,這就與Hashtable和同步的HashMap同樣了。)等,都屬於運行時異常。

常見的五種運行時異常:

(1)ClassCastException(類轉換異常)

(2)IndexOutOfBoundsException(數組越界)

(3)NullPointerException(空指針異常)

(4)ArrayStoreException(數據存儲異常,操做數組是類型不一致)

(5)BufferOverflowException

被檢查異常

定義:Exception類自己,以及Exception的子類中除了"運行時異常"以外的其它子類都屬於被檢查異常。

特色 : Java編譯器會檢查它。 此類異常,要麼經過throws進行聲明拋出,要麼經過try-catch進行捕獲處理,不然不能經過編譯。例如,CloneNotSupportedException就屬於被檢查異常。當經過clone()接口去克隆一個對象,而該對象對應的類沒有實現Cloneable接口,就會拋出CloneNotSupportedException異常。被檢查異常一般都是能夠恢復的。

如:

IOException

FileNotFoundException

SQLException

被檢查的異常適用於那些不是因程序引發的錯誤狀況,好比:讀取文件時文件不存在引起的

FileNotFoundException 。然而,不被檢查的異常一般都是因爲糟糕的編程引發的,好比:在對象引

用時沒有確保對象非空而引發的 NullPointerException 。

錯誤

定義 : Error類及其子類。

特色 : 和運行時異常同樣,編譯器也不會對錯誤進行檢查。

當資源不足、約束失敗、或是其它程序沒法繼續運行的條件發生時,就產生錯誤。程序自己沒法修復這些錯誤的。例如,VirtualMachineError就屬於錯誤。出現這種錯誤會致使程序終止運行。OutOfMemoryError、ThreadDeath。

Java虛擬機規範規定JVM的內存分爲了好幾塊,好比堆,棧,程序計數器,方法區等

2五、OOM你遇到過哪些狀況,SOF你遇到過哪些狀況

OOM

(1)OutOfMemoryError異常

Java Heap 溢出:

通常的異常信息:java.lang.OutOfMemoryError:Java heap spacess。

java堆用於存儲對象實例,咱們只要不斷的建立對象,而且保證GC Roots到對象之間有可達路徑來避免垃圾回收機制清除這些對象,就會在對象數量達到最大堆容量限制後產生內存溢出異常。

出現這種異常,通常手段是先經過內存映像分析的工具(如Eclipse Memory Analyzer)對dump出來的堆轉存快照進行分析,重點是確認內存中的對象是不是必要的,先分清是由於內存泄漏(Memory Leak)仍是內存溢出(Memory Overflow)。

若是是內存泄漏,可進一步經過工具查看泄漏對象到GCRoots的引用鏈。因而就能找到泄漏對象是經過怎樣的路徑與GC Roots相關聯並致使垃圾收集器沒法自動回收。

若是不存在泄漏,那就應該檢查虛擬機的參數(-Xmx與-Xms)的設置是否適當。

(2)虛擬機棧和本地方法棧溢出

若是線程請求的棧深度大於虛擬機所容許的最大深度,將拋出StackOverflowError異常。

若是虛擬機在擴展棧時沒法申請到足夠的內存空間,則拋出OutOfMemoryError異常

這裏須要注意當棧的大小越大可分配的線程數就越少。

(3)運行時常量池溢出

異常信息:java.lang.OutOfMemoryError:PermGenspace

若是要向運行時常量池中添加內容,最簡單的作法就是使用String.intern()這個Native方法。該方法的做用是:若是池中已經包含一個等於此String的字符串,則返回表明池中這個字符串的String對象;不然,將此String對象包含的字符串添加到常量池中,而且返回此String對象的引用。因爲常量池分配在方法區內,咱們能夠經過-XX:PermSize和-XX:MaxPermSize限制方法區的大小,從而間接限制其中常量池的容量。

(4)方法區溢出

方法區用於存放Class的相關信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。也有多是方法區中保存的class對象沒有被及時回收掉或者class信息佔用的內存超過了咱們配置。

異常信息:java.lang.OutOfMemoryError:PermGenspace

方法區溢出也是一種常見的內存溢出異常,一個類若是要被垃圾收集器回收,斷定條件是很苛刻的。在常常動態生成大量Class的應用中,要特別注意這點。

SOF(堆棧溢出StackOverflow):

StackOverflowError 的定義:當應用程序遞歸太深而發生堆棧溢出時,拋出該錯誤。

由於棧通常默認爲1-2m,一旦出現死循環或者是大量的遞歸調用,在不斷的壓棧過程當中,形成棧容量超過1m而致使溢出。

棧溢出的緣由:遞歸調用,大量循環或死循環,全局變量是否過多,數組、List、map數據過大。

2六、 簡述線程、程序、進程的基本概念。以及他們之間關係是什麼?

線程與進程類似,但線程是一個比進程更小的執行單位。一個進程在其執行的過程當中能夠產生多個線程。與進程不一樣的是同類的多個線程共享同一塊內存空間和一組系統資源,因此係統在產生一個線程,或是在各個線程之間做切換工做時,負擔要比進程小得多,也正由於如此,線程也被稱爲輕量級進程。程序是含有指令和數據的文件,被存儲在磁盤或其餘的數據存儲設備中,也就是說程序是靜態的代碼。

進程是程序的一次執行過程,是系統運行程序的基本單位,所以進程是動態的。系統運行一個程序便是一個進程從建立,運行到消亡的過程。簡單來講,一個進程就是一個執行中的程序,它在計算機中一個指令接着一個指令地執行着,同時,每一個進程還佔有某些系統資源如 CPU 時間,內存空間,文件,輸入輸出設備的使用權等等。換句話說,當程序在執行時,將會被操做系統載入內存中。 線程是進程劃分紅的更小的運行單位。線程和進程最大的不一樣在於基本上各進程是獨立的,而各線程則不必定,由於同一進程中的線程極有可能會相互影響。從另外一角度來講,進程屬於操做系統的範疇,主要是同一段時間內,能夠同時執行一個以上的程序,而線程則是在同一程序內幾乎同時執行一個以上的程序段。

2七、線程有哪些基本狀態?(補充)

Java 線程在運行的生命週期中的指定時刻只可能處於下面 6 種不一樣狀態的其中一個狀態(圖源《Java併發編程藝術》4.1.4 節)。

2八、Java 序列化中若是有些字段不想進行序列化,怎麼辦?

對於不想進行序列化的變量,使用 transient 關鍵字修飾。

transient 關鍵字的做用是:阻止實例中那些用此關鍵字修飾的的變量序列化;當對象被反序列化時,被 transient 修飾的變量值不會被持久化和恢復。transient 只能修飾變量,不能修飾類和方法。

2九、Java 中 IO 流

Java 中 IO 流分爲幾種?

(1)按照流的流向分,能夠分爲輸入流和輸出流;

(2)按照操做單元劃分,能夠劃分爲字節流和字符流;

(3)按照流的角色劃分爲節點流和處理流。

Java Io 流共涉及 40 多個類,這些類看上去很雜亂,但實際上頗有規則,並且彼此之間存在很是緊密的聯繫, Java I0 流的 40 多個類都是從以下 4 個抽象類基類中派生出來的。

InputStream/Reader: 全部的輸入流的基類,前者是字節輸入流,後者是字符輸入流。

OutputStream/Writer: 全部輸出流的基類,前者是字節輸出流,後者是字符輸出流。

按操做方式分類結構圖:

v2-f01c22b0348912e8f8307299a81050f7_720w.png

按操做對象分類結構圖:

v2-da07bb3b1f5176c25b3cd7377821e3b3_720w.png

30、 Java IO與 NIO的區別(補充)

NIO即New IO,這個庫是在JDK1.4中才引入的。NIO和IO有相同的做用和目的,但實現方式不一樣,NIO主要用到的是塊,因此NIO的效率要比IO高不少。在Java API中提供了兩套NIO,一套是針對標準輸入輸出NIO,另外一套就是網絡編程NIO。

3一、java反射的做用於原理

(1)定義:

反射機制是在運行時,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意個對象,都可以調用它的任意一個方法。在java中,只要給定類的名字,就能夠經過反射機制來得到類的全部信息。

這種動態獲取的信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。

(2)哪裏會用到反射機制?

jdbc就是典型的反射

Class.forName('com.mysql.jdbc.Driver.class');
//加載MySQL的驅動類

這就是反射。如hibernate,struts等框架使用反射實現的。

第一步:獲取Class對象,有4中方法:

1)Class.forName(「類的路徑」);

2)類名.class

3)對象名.getClass()

4)基本類型的包裝類,能夠調用包裝類的Type屬性來得到該包裝類的Class對象

(3)實現Java反射的類:

1)Class:表示正在運行的Java應用程序中的類和接口

注意: 全部獲取對象的信息都須要Class類來實現。

2)Field:提供有關類和接口的屬性信息,以及對它的動態訪問權限。

3)Constructor:提供關於類的單個構造方法的信息以及它的訪問權限

4)Method:提供類或接口中某個方法的信息

(4)反射機制的優缺點:

優勢:

1)可以運行時動態獲取類的實例,提升靈活性;

2)與動態編譯結合

缺點:

1)使用反射性能較低,須要解析字節碼,將內存中的對象進行解析。

解決方案:

一、經過setAccessible(true)關閉JDK的安全檢查來提高反射速度;

二、屢次建立一個類的實例時,有緩存會快不少

三、ReflectASM工具類,經過字節碼生成的方式加快反射速度

2)相對不安全,破壞了封裝性(由於經過反射能夠得到私有方法和屬性)

3二、說說List,Set,Map三者的區別?

List(對付順序的好幫手): List接口存儲一組不惟一(能夠有多個元素引用相同的對象),有序的對象

Set(注重獨一無二的性質): 不容許重複的集合。不會有多個元素引用相同的對象。

Map(用Key來搜索的專家): 使用鍵值對存儲。Map會維護與Key有關聯的值。兩個Key能夠引用相同的對象,但Key不能重複,典型的Key是String類型,但也能夠是任何對象。


最後

歡迎關注公衆號:程序員追風,回覆66  ,領取一份300頁pdf文檔的Java核心知識點總結!

這些資料的內容都是面試時面試官必問的知識點,篇章包括了不少知識點,其中包括了有基礎知識、Java集合、JVM、多線程併發、spring原理、微服務、Netty 與RPC 、Kafka、日記、設計模式、Java算法、數據庫、Zookeeper、分佈式緩存、數據結構等等。

相關文章
相關標籤/搜索