本文已收錄至個人我的博客,歡迎交流:www.swaggyhang.com/java
封裝數據庫
繼承數組
抽象緩存
多態安全
String是類類型,不是基本數據類型。多線程
基本數據類型有八種:ide
int是基本數據類型,4個字節,32位長度的整數。工具
Integer是類類型,是int的封裝類。oop
int和Integer之間能夠經過自動裝箱/自動拆箱的方式互相轉換。性能
String是immutable(不可變)的,其內容一旦建立好以後,就不能夠發生改變。
StringBuffer 是能夠變長的,內容也能夠發生改變。
運行時異常又叫作非可查異常,在編譯過程當中,不要求必須進行顯示捕捉。
通常異常又叫作可查異常,在編譯過程當中,必須進行處理,要麼捕捉,要麼經過throws拋出去。
ArrayList和Vector
ArrayList和LinkedList
Collection是接口,是List和Set的父接口。
Collections是工具類,提供了排序,混淆等不少實用方法。
&有兩個做用,分別是位與和邏輯與。
&& 就是邏輯與。
做爲邏輯與,&和&&分別表示長路與和短路與。長路與兩側,都會被運算;短路與只要第一個是false,第二個就不進行運算了。
HashMap和Hashtable都實現了Map接口,都是鍵值對保存數據的方式。
區別1:
區別2:
final
final修飾類,方法,基本類型變量,引用的時候分別有不一樣的意思:
修飾類:表示該類不能被繼承。
修飾方法:表示該方法不能被重寫。
修飾基本數據類型變量:表示該變量只能被賦值一次。
修飾引用:表示該引用只有一次指向對象的機會。
finally
finalize
finalize是Object的方法,全部類都繼承了該方法。
當一個對象知足垃圾回收的條件,而且被回收的時候,其finalize()方法就會被調用。
區別:
Overload:方法重載。在同一個類裏面,方法名同樣,可是參數不同。
Override:方法重寫。子類繼承了父類的某個方法後,從新又寫了一遍。
能夠改變返回值的類型。重載本質就是徹底不一樣的方法,只是剛好取了相同的名字。
Error和Exception都實現了Throwable接口。
Error:是JVM層面的錯誤,好比:內存不足OutOfMemoryError。
Exception:是代碼邏輯的異常,好比:下標越界OutOfIndexException。
使用方式:
抽象類只可以經過繼承被使用。
接口必須經過實現被使用。
實現方法:
抽象類不只能夠提供抽象方法,也能夠提供實現方法。
接口只能提供抽象方法,不能提供實現方法。
在 Java 8 版本開始,接口能夠提供實現方法了,前提是要在方法前加一個default修飾符。
存放內容不同:
堆:存放對象。
棧:存放基本數據類型變量、引用(對象地址)、方法調用。
存取方式不同:
堆:自動增長大小,不須要指定大小,存取相對較慢。
棧:固定大小,而且是FILO,先入後出的順序,存取速度比較快。
GC是Garbage Collection的縮寫,即垃圾回收。
這裏所謂的垃圾,指的是那些再也不被使用的對象,JVM的垃圾回收機制使得開發人員從無聊、容易犯錯的手動釋放內存資源的過程當中解放出來。
開發人員能夠更加專一的進行業務功能的開發,而資源回收的工做交由更加專業的垃圾回收機制自動完成。
short s1 = 1; 這一句沒有錯誤,編譯器會自動把1這個整數處理爲short。
s1 = s1 + 1; 右側的表達式會返回一個int類型的整數,再把這個int類型的整數賦給short類型的s1的時候,就會出現強制轉換錯誤。
Math.round()的意思是+0.5取整數。
因此 Math.round(11.5) = 11.5 + 0.5 = 12;Math.round(-11.5) = -11.5 + 0.5 = -11。
首先,構造方法new String("xyz"); 中的"xyz"這自己就是一個字符串對象。
而後,new關鍵字必定會建立一個對象。
因此,總共建立了兩個字符串對象。
能夠,好比:List就繼承了接口Collection。
能夠,好比:MouseAdapter鼠標監聽適配器是一個抽象類,而且實現了MouseListener接口。
能夠,全部抽象類,都繼承了Object。
List和Set繼承了Collection接口。
Map和Collection之間沒有繼承關係。由於一個是鍵值對容器,一個是單值容器,沒法兼容。
都不能。
抽象方法須要子類重寫,而靜態的方法是沒法被重寫的,所以兩者是矛盾的。
本地方法是由本地代碼(如C代碼)實現的方法,而抽象方法是沒有實現的,也是矛盾的。
synchronized和方法的實現細節有關,抽象方法不涉及實現細節,所以也是相互矛盾的。
數組獲取長度的手段是:.length屬性。
字符串獲取長度的手段是:.length()方法。
集合獲取長度的手段是:.size()方法。
文件獲取長度的手段是:.length()方法。
以HashSet爲例,判斷重複的邏輯是:
首先看hashCode()是否相同,若是不一樣,就是不重複的。
若是hashCode()同樣,再比較equals(),若是不一樣,就是不重複的,不然就是重複的。
子類不能繼承父類的構造方法,因此就不存在重寫父類的構造方法。
super()表示子類調用父類的構造方法,這不能被叫作繼承父類的構造方法。
String是final修飾的,因此不可以被繼承。
switch能夠做用在byte、short、int、String、Enum(枚舉)上,可是不能做用在long上面。
switch做用在String上從JDK 1.7開始支持,實質是編譯時將字符串替換爲了其對應的hash值。
* Note that it is generally necessary to override the {@code hashCode}
* method whenever this method is overridden, so as to maintain the
* general contract for the {@code hashCode} method, which states
* that equal objects must have equal hash codes.
複製代碼
一般來說,在重寫這個方法的時候,也須要對hashCode方法進行重寫,以此來保證這兩個方法的一致性,當equals返回true的時候,這兩個對象必定有相同的hashCode。
複製代碼
優勢:
原理:
兩種常見的回收機制:
定時回收
當垃圾佔到某個百分比的時候,進行回收
好比,當垃圾佔到70%的時候,進行回收。
這種機制的弊端是,若是垃圾產生的頻率很快,那麼JVM就必須高頻率的進行垃圾回收。
而在垃圾回收的過程當中,JVM會停頓下來,只作垃圾回收,而影響業務功能的正常運行。
通常說來,JVM會採用兩種機制結合的方式進行垃圾回收。
常見的集合
常見方法:
char是16位的,佔兩個字節。
漢字一般使用GBK或者UNICODE編碼,也是使用兩個字節,因此能夠存放漢字。
主要是兩種:SAX和DOM。
SAX就是逐行讀取,直到找到目標數據爲止。
DOM是先全文檔加載,而後讀取。
throws:用在方法聲明上面,表示該方法有可能拋出某個異常。
throw:拋出一個指定的異常。
try catch:在try中有可能會拋出某個異常,一旦某個異常拋出後,就會在catch中進行捕捉,他倆通常說來都是成對出現的。
finally:表示不管是否捕捉住異常,都會執行。
Java中全部的流都是基於字節流,因此最基本的流是:
輸入輸出字節流
InputStream
OutputStream
在字節流的基礎上,封裝了字符流
Reader
Writer
進一步,又封裝了緩存流
BufferedReader
PrintWriter
以及數據流
DataInputStream
DataOutputStream
對象流
ObjectInputStream
ObjectOutputStream
由於Java是自動進行垃圾回收管理的,因此不存在C語言中同等概念的內存泄漏。
可是,存在Java特點的內存泄漏。
當某些對象不被使用,可是又有非直接引用指向的時候,那麼就不知足垃圾回收的條件,而造成內存泄漏。
好比:代碼中的例子,每一個Object建立的時候,有一個引用o指向,接着就被放進了集合al中。下一個Object建立的時候,上一個Object就沒有引用指向了。這些Object都沒有引用指向,可是卻放在ArrayList中,而這個Arraylist忘記了回收,那麼裏面的全部對象,都會一直存活下去,雖然再也不被使用了。
package j2se;
import java.util.ArrayList;
public class MemoryLeak {
static ArrayList<Object> al = new ArrayList<Object>();
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Object o = new Object();
al.add(o);
}
}
}
複製代碼
類的多態的條件:
父類(接口)引用指向子類對象。
方法有重寫。
靜態變量:直接經過類就能夠訪問,無需實例。
實例變量:經過類的某個具體實例,才能夠訪問。
序列化:指的是把一個Java對象,經過某種介質進行傳輸,好比Socket輸入輸出流,或者保存在一個文件裏。
實現java序列化的手段是讓該類實現接口Serializable,這個接口是一個標識性接口,沒有任何方法,僅用於表示該類能夠序列化。
不行。
由於非static方法須要一個具體的實例才能夠調用,而調用 static方法的時候,不必定存在一個實例。
在外部循環的前一行,加上標籤;
在break的時候使用該標籤。
public class HelloWorld {
public static void main(String[] args) {
//打印單數
outloop: //outloop這個標示是能夠自定義的,好比:outloop1,ol2,out5......
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.println(i+":"+j);
if(0==j%2)
break outloop; //若是是雙數,結束外部循環
}
}
}
}
複製代碼
List:是有順序的,而且能夠重複。
Set:是無序的,不能夠重複。
Map:保存數據的方式是鍵值對。
匿名內部類本質上就是在繼承其餘類,實現其餘接口。
如:
匿名類1,就是繼承了Thread;
匿名類2 ,就是實現了Runnable接口。
package j2se;
public class HelloWorld {
public static void main(String[] args) {
// 匿名類1
new Thread() {
public void run() {
}
};
// 匿名類2
new Runnable() {
public void run() {
}
};
}
}
複製代碼
能夠。
若是是非靜態內部類,可使用外部類的全部成員;若是是靜態內部類,只能使用外部類的靜態成員。
Java建立一個線程有三種方式:
繼承一個Thread類
實現Runnable接口
匿名內部類
首先,sleep()和wait()之間沒有任何關係:
sleep():是Thread類的方法,指的是當前線程暫停。
wait():是Object類的方法,指的佔用當前對象的線程臨時釋放對當前對象的佔用,以使得其餘線程有機會佔用當前對象。因此調用wait方法必定是在synchronized 中進行。
數據庫鏈接池原理:
由於建立鏈接和關閉鏈接的行爲是很是耗時的,會顯著下降軟件的性能表現。
解決辦法就是先建立n條數據庫鏈接Connection,循環使用,可是不進行關閉,這樣再執行SQL語句,就不須要額外建立鏈接了,直接使用現成的鏈接就能夠了,從而節約了建立鏈接和關閉鏈接的時間開銷。
Lock是一個接口,而synchronized是Java中的關鍵字
synchronized是內置的語言實現,Lock是代碼層面的實現。
Lock能夠選擇性的獲取鎖,若是一段時間獲取不到,能夠放棄。synchronized不行,會一根筋一直獲取下去。藉助Lock的這個特性,就可以規避死鎖,synchronized必須經過謹慎和良好的設計,才能減小死鎖的發生。
synchronized在發生異常和同步塊結束的時候,會自動釋放鎖。而Lock必須手動釋放, 因此若是忘記了釋放鎖,同樣會形成死鎖。
Class.forName()常見的場景是在數據庫驅動初始化的時候調用。
自己的意義是加載類到JVM中,一旦一個類被加載到JVM中,它的靜態屬性就會被初始化,在初始化的過程當中就會執行相關代碼,從而達到"加載驅動的效果"。
看狀況而定。
若是該對象的其餘方法也是有synchronized修飾的,那麼其餘線程就會被擋在外面。不然其餘線程就能夠進入其餘方法。
NullPointerException:空指針異常
ArithmeticException:算術異常,好比除數爲零
ClassCastException:類型轉換異常
ConcurrentModificationException:同步修改異常,遍歷一個集合的時候,刪除集合的元素,就會拋出該異常
IndexOutOfBoundsException:數組下標越界異常
NegativeArraySizeException:爲數組分配的空間是負數異常