Java基礎-基於《Thinking In Java》

摘要

本文是對一些java基礎知識的整理,把以前印象筆記裏面的所有慢慢搬到這個blog來html

爲了方便就按照《Thinking In Java》的目錄來編輯。java

這裏面的內容均爲面試題相關,可能的考點等android

這本書裏面有些翻譯不是很好,建議和英文版對照。程序員


Chapter1-Introduction to Objects

特性

抽象、封裝、繼承、多態web

面向對象設計方法主要特徵:繼承、封裝、多態。面試

延伸點:反射會破壞代碼的封裝性(mock等)正則表達式


Chapter2-Everything Is an Object

Object方法

return method 解釋
protected Object clone() 建立並返回此對象的一個副本。
protected void finalize() 當垃圾回收器肯定不存在對該對象的更多引用時,由對象的垃圾回收器調用此方法。
void notify() 喚醒在此對象監視器上等待的單個線程。
void notifyAll() 喚醒在此對象監視器上等待的全部線程。
void wait() 在其餘線程調用此對象的 notify()方法或 notifyAll()方法前,致使當前線程等待。
void wait(long timeout) 在其餘線程調用此對象的 notify()方法或 notifyAll()方法,或者超過指定的時間量前,致使當前線程等待。
void wait(long timeout, int nanos) 在其餘線程調用此對象的 notify()方法或 notifyAll()方法,或者其餘某個線程中斷當前線程,或者已超過某個實際時間量前,致使當前線程等待。

方法屬於對象的成員,靜態方法屬於類的成員算法

Q:爲何 wait, notify 和 notifyAll 這些方法不在 thread 類裏面?編程

一個很明顯的緣由是 JAVA 提供的鎖是「對象級」 的而不是「線程級」的,每一個對象都有鎖,經過線程得到。若是線程須要等待某些鎖那麼調用對象中的 wait()方法就有意義了。api

若是 wait()方法定義在 Thread 類中,線程正在等待的是哪一個鎖就不明顯了。

簡單的說,因爲 wait,notify 和 notifyAll 都是鎖級別的操做,因此把他們定義在 Object 類中由於鎖屬於對象。

拓展:
在 Java 中,每一個對象都有兩個池,鎖(monitor)池和等待池

  1. 鎖池:假設線程A已經擁有了某個對象(注意:不是類)的鎖,而其它的線程想要調用這個對象的某個synchronized 方法(或者 synchronized 塊),因爲這些線程在進入對象的 synchronized 方法以前必須先得到該對象的鎖的擁有權,可是該對象的鎖目前正被線程A擁有,因此這些線程就進入了該對象的鎖池中。

  2. 等待池:假設一個線程A調用了某個對象的 wait()方法,線程A就會釋放該對象的鎖(由於wait()方法必須出如今 synchronized 中,這樣天然在執行 wait()方法以前線程A就已經擁有了該對象的鎖),同時線程A就進入到了該對象的等待池中。

若是另外的一個線程調用了相同對象的 notifyAll()方法,那麼處於該對象的等待池中的線程就會所有進入該對象的鎖池中,準備爭奪鎖的擁有權。若是另外的一個線程調用了相同對象的 notify()方法,那麼僅僅有一個處於該對象的等待池中的線程(隨機)會進入該對象的鎖池.


Q:爲何 wait 和 notify 方法要在同步塊中調用?

  1. 避免 IllegalMonitorStateException
  2. 避免任何在 wait 和 notify 之間潛在的競態條件

參考資料:併發編程之 wait notify 方法剖析

基本數據類型

Integer,Float,Double等都繼承自Number類

名稱 包裝類型 初始化 其餘
boolean Boolean false 1位
byte(1字節) Byte (byte)0 ASCII碼:空格:32;數字0到9:48到57,後面爲大小寫字母; byte 類型用在大型數組中節約空間,主要代替整數,由於 佔用的空間只有 int 類型的四分之一
short(2字節) Short (short)0 Short 數據類型也能夠像 byte 那樣節省空間。一個short變量是int型變量所佔空間的二分之一;
char(2字節) Character '\u0000'(null) 單一的 16 位 Unicode 字符;
int(4字節) Integer 0
float(4字節) Float 0.0f 精確到小數點後6位,在儲存大型浮點數組的時候可節省內存空間;
long(8字節) Long 0L
double(8字節) Double 0.0d 精確到小數點後15位(默認的小數類型)

BigInteger 任意精度的整數,不可變

BigDecimal 任何精度的定點數(商業計算),不可變,一般建議優先使用String構造方法

參考:Java BigDecimal詳解

延伸點:爲何int整型(32位)的範圍是-32768到32767?

parseInt()是把String變成int的基礎數據類型;

類型轉換

byte,short,char-> int -> long -> float -> double 不一樣類型運算結果類型向右邊靠齊。

浮點數到整數的轉換是經過捨棄小數獲得,而不是四捨五入


拆箱和裝箱

裝箱過程是經過調用包裝器的valueOf方法實現的,而拆箱過程是經過調用包裝器的 xxxValue方法實現的

大多數狀況下二者相同,java.io.file,java.util.Date,java.lang.string,包裝類(Integer,Double等)等實現了本身的equals,比較規則爲:若是兩個對象的類型一致,而且內容一致,則返回true。

valueOf() 方法的實現比較簡單,就是先判斷值是否在緩存池中,若是在的話就直接返回緩存池的內容。

在 Java 8 中,Integer 緩存池的大小默認爲 -128~127,因此除非用 new Integer() 顯式的建立對象,不然都是同一個對象(-128~127)

比較符號 比較對象 數據轉型
== 同一個對象 有表達式會觸發
equals 同一個類型和內容 不觸發

通常會考你「==」和equals的區別,數據轉型,拆箱裝箱

「==」和equals記住,前者相同,後者相等。前者會觸發數據轉型。

new Integer()新建對象

valueof裝箱,xxxValue拆箱

Math類

方法 功能 返回值
ceil() 向上取整 double
floor() 向下取整 double
round() 原來的數字加上0.5後再向下取整 int

變量名

三種元素構成:數字+字符+$+下劃線。

不能以數字開頭+不能是關鍵字.

類名

一個文件中能夠有多個類,若是沒有public類,則能夠與任意類名相同,若是有public類則文件名必須與此類名相同,由於一個文件中只能有一個public類。若是文件中只有一個類,則文件名必須與類名相同

註釋

名稱 功能
Override 標識當前的方法,是否覆蓋了它的父類中的方法
Deprecated 已通過期或者即將過時的方法,不推薦咱們使用
SuppressWarning 屏蔽相應的警告

Chapter3-Operators

運算符 結合性 其餘
() [] . 從左到右
! +(正) -(負) ~ ++ -- 從右向左 ~n=-n-1
* / % 從左向右 %取餘操做,只適用於整型
+(加) -(減) 同上
<< >> >>> 同上 按位左(右)移運算符, 按位右移運補零運算符。
< <= > >= instanceof 同上
== != 同上
& 同上 相對應位都是1,則結果爲1,不然爲0
^ 同上 相對應位值相同,則結果爲0,不然爲1
同上 相對應位都是0,則結果爲0,不然爲1
&& 同上 邏輯與(前面表達式爲false,後面不計算)
邏輯或 同上 邏輯或(前面表達式爲true,後面不計算)

Chapter4-Controlling Execution

break continue return

  1. break 中斷並跳出當前循環。直接跳出當前的循環,從當前循環外面開始執行,忽略循環體中任何其餘語句和循環條件測試。他只能跳出一層循環,若是你的循環是嵌套循環,那麼你須要按照你嵌套的層次,逐步使用break來跳出.

  2. continue 終止當前的循環過程,但他並不跳出循環,而是繼續往下判斷循環條件執行語句.他只能結束循環中的一次過程,但不能終止循環繼續進行.
  3. return 致使當前的方法退出,並返回那個值。

switch

選擇因子:整數類型(long除外),enum(jdk1.5後),String(jdk1.7後)

字符串的switch是經過equals()和hashCode()方法來實現的。

注意break


Chapter5-Initialization & Cleanup

類的加載包括:加載,驗證,準備,解析,初始化

構造方法內能夠用this調用另外一個構造方法

重載與重寫

同名不一樣參數爲重載與返回值類型無關;(好比你調用這個方法的時候java怎麼根據返回值來區分你實際調用的方法)與訪問修飾符無關

子類覆寫父類的方法爲重寫

方法重寫應遵循「三同一小一大」原則:

  1. ​ 「三同」:即方法名相同,形參列表相同,返回值類型相同;
  2. ​ 「一小」:子類方法聲明拋出的異常比父類方法聲明拋出的異常更小或者相等;
  3. ​ 「一大」:子類方法的訪問修飾符應比父類方法更大或相等。

題型:怎麼算重載和重寫,重寫的修飾符範圍

final不能重寫


Chapter6-access control

訪問控制符

名稱 功能
包訪問權限 不提供任何權限修飾詞狀況下;默認包:處於同一個文件目錄下
public 均可用
protected 修飾方法和成員變量,處理繼承的概念,保證了僅有繼承的類才能訪問這個成員。同時具備包訪問權限
private 僅在被包含的類裏面可用,類的變量一般聲明爲private

❤class編寫順序可按照:public👉protected👉private

類:❌(private & protected),⭕️(包訪問權限 or public)

靜態變量會默認賦初值,局部變量和final聲明的變量必須手動賦初值


Chapter7-ReusingClasses

組合

將對象置於新類中便可

想在新類中使用現有類的功能而非它的接口

繼承

構造函數不繼承,只能顯式(super)或者隱式的調用,導出類的構造器會插入對基類構造器的調用

方法(包括私有)均繼承,可是不能直接調用私有方法。

ps:也可使用super訪問父類被子類隱藏的變量或覆蓋的方法。

代理

將一個成員對象置於構造的類中,同時在新類中暴露了該成員的全部方法。

例:代理類中建立原類的對象,代理類的方法中調用此對象的方法。(其實就是套個殼,間接調用原類的方法)

初始化:一、定義的時候初始化

​ 二、構造器初始化

​ 三、惰性初始化(在使用這些對象以前)

​ 四、實例初始化

只有命令行調用的main方法會被調用

確保正確清理:使用finally語句保證清理/執行類的全部特定清理動做,其順序同生成順序相反/不要使用finalize()

延伸點:Java將棄用finalize()方法?

組合和繼承(has a & is a ):

組合一般適用於在新類中使用現有類的功能而非接口,即在新類中嵌入一個現有類的private對象。

繼承一般用於,使用某個類,並開發一個它的特殊版本。是否須要重新類向基類進行向上轉型

final

數據(數值不變)

引用(引用不變可是對象自身能夠改變)

❌數組中的數據沒法被修飾爲不可更改

空白final:被聲明爲final可是沒有給定初始值的域,容許可是必須在域的定義處或者每一個構造器中對final賦值

final 的方法不能被修改(繼承類中不能覆蓋),final類不能繼承(裏面的方法也是final的,數值不受影響)

private final = private修飾的方法,繼承類中能覆蓋(由於方法爲private 的時候,它就不是接口的一部分,導出類中相同名稱的方法並非覆蓋而是從新生成了一個新的方法);

static

用來修飾成員變量和成員方法,也能夠造成靜態static代碼塊。不能在方法中定義

static變量在第一次使用的時候初始化,只會有一份成員對象。

初始化順序

總結:(靜態變量、靜態初始化塊)>(變量、初始化塊)>構造器


Chapter8-Polymorphism

向上轉型

針對非靜態方法是編譯看左,運行看右,可是對於成員變量,都是看左,也就是父類

它一般只是爲了方便輸出,好比System.out.println(xx),括號裏面的「xx」若是不是String類型的話,就自動調用xx的toString()方法

Java中除了static和final方法之外,其餘方法都是後期綁定(動態綁定)實現多態

動態綁定僅僅針對類的方法


Chapter9-Interfaces

抽象類:abstract

一、抽象的方法沒有body

二、含有抽象方法的類就是抽象類

三、不能建立實例

ps:抽象類的繼承類,若是沒有爲全部方法提供方法體,編譯器會強制用abstract來修飾這個類。

jdk1.8更新

JDK 1.8之前,抽象類的方法默認訪問權限爲protected

JDK 1.8時,抽象類的方法默認訪問權限變爲default


接口:interface

  1. 只有public、static、final變量和抽象方法

  2. 能夠在此以前加public,implements關鍵字,必須實現全部方法

  3. 先繼承再實現
  4. 不能建立實例

jdk1.8更新

在jdk1.8以前,interface之中能夠定義常量和方法,常量必須是public、static、final的,方法必須是public、abstract的。因爲這些修飾符都是默認的

JDK8及之後,容許咱們在接口中定義static方法和default方法,有方法體

靜態方法,只能經過接口名調用,不能夠經過實現類的類名或者實現類的對象調用。

default方法,只能經過接口實現類的對象來調用。能夠被覆寫,可是不能再加default修飾符。

JDK 1.9時,接口中的方法能夠是private的

接口的修飾符,有無body,接口和抽象類的區別等


Chapter10-Inner Classes

匿名內部類:

一、不能有static變量和字段

二、尾部有分號

三、傳入的參數是final

四、不含命名構造器,實例初始化的實際效果就是構造器

五、只能實現一個接口,且不能同時繼承和實現接口

局部內部類:在方法體裏面建立

須要不止一個該內部類的時候使用。局部內部類含有構造器,匿名內部類只能用於實例初始化

內部類:

一、不能有static變量和字段

二、構造器必須鏈接到指向其外圍對象的引用

三、外圍類繼承的時候,內部類並無被繼承。即便基類和導出類的內部類名稱相同也是不一樣且獨立的類。

經常使用:外部類有個方法指向內部類的引用(匿名類把內部類直接放到方法裏面)

內部類對外部類引用:外部類.this(嵌套類沒有)

建立內部類的對象:外部類對象.new 內部類名()

嵌套類:

static的內部類

能夠做爲接口的一部分

靜態內部類能夠訪問外圍類的靜態數據,包括私有數據,但不能訪問非靜態數據;

非靜態內部類能夠直接訪問外圍類的數據,包括私有數據


Chapter11-Holding YourObjects

Collection

方法 功能
Collections.synchronizedXxx() 將指定的集合包裝成線程同步的集合
collection1.containsAll(Collection2) 合併兩個collection
Collection.addAll(collection,11,12,13,14) 接受一個collection對象,以及一個數組或者是用逗號分割的列表
Collections.sort(list); 根據元素的天然順序 對指定列表按升序進行排序。
Collections.shuffle(List<?> list, Random rand); 打亂

arrays.aslist()接受一個逗號分隔的元素列表(可變參數)或者數組,並轉換爲一個list對象

ddd

List

ArrayList() :

表明長度能夠改變得數組。能夠對元素進行隨機的訪問,插入與與刪除元素的速度慢。

默認大小爲10,不夠再以1.5倍擴容新數組,拷貝數據到新數組中

LinkedList()

在實現中採用鏈表數據結構。插入和刪除速度快,隨機訪問速度慢。

method 解釋
subList(List2) 建立片斷
indexOf(object) 獲取索引編號
containsAll(List2) 是否包含,無視順序
addFirst/add/addLast 添加單個元素
remove/removeFirst/poll/移除並返回列表頭 removeLast 移除並返回列表尾
getFirst/element/peek
peek/poll 列表空返回null

詳細參考:LinkedList基本用法

一個是數組,一個是鏈表,二者的讀寫屬性基本相反。

延伸點:java中 CopyOnWriteArrayList 的使用


Iterator

單向移動:

  1. 使用方法iterator()要求容器返回一個Iterator。第一次調用Iterator的next()方法時,它返回序列的第一個元素。注意:iterator()方法是java.lang.Iterable接口,被Collection繼承。
  2. 使用next()得到序列中的下一個元素。
  3. 使用hasNext()檢查序列中是否還有元素。
  4. 使用remove()將迭代器新返回的元素刪除。
while(it.hasNext())
    {
        Pet p = it.next();
        print(p);
    }

延伸點:可能會引發ConcurrentModificationException 異常

ListIterator:雙向移動

method 解釋
nextIndex() 返回列表中ListIterator所需位置後面元素的索引
previousIndex()
previous()
next()
listIterator(n) 一開始就指向列表索引爲n處的ListIterator,空則指向開始處
remove() 對迭代器使用hasNext()方法時,刪除ListIterator指向位置後面的元素;當對迭代器使用hasPrevious()方法時,刪除ListIterator指向位置前面的元素

延伸:JAVA中ListIterator和Iterator詳解與辨析


Set:

不重複,測試歸屬性(查找是否存在set中)

和collection接口相同


Map:

Map沒有繼承於Collection接口

Map集合中的鍵對象不容許重複,也就說,任意兩個鍵對象經過equals()方法比較的結果都是false,可是能夠將任意多個鍵獨享映射到同一個值對象上。

Object put(Object key, Object value):

Object remove(Object key)

void putAll(Map t): 未來自特定映像的全部元素添加給該映像

void clear(): 從映像中刪除全部映射

Object get(Object key): 得到與關鍵字key相關的值

containsKey()和containsValue()測試Map中是否包含某個「鍵」或「值」。

名稱 線程安全 功能
HashMap 不安全 基於散列表的實現。插入和查詢「鍵值對」的開銷是固定的。能夠經過構造器設置容量capacity和負載因子load factor,以調整容器的性能。
LinkedHashMap 不安全 相似於HashMap,可是迭代遍歷它時,取得「鍵值對」的順序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一點。而在迭代訪問時發而更快,由於它使用鏈表維護內部次序。
TreeMap 不安全 基於紅黑樹數據結構的實現。查看「鍵」或「鍵值對」時,它們會被排序(次序由Comparabel或Comparator決定)。TreeMap的特色在於,你獲得的結果是通過排序的。TreeMap是惟一的帶有subMap()方法的Map,它能夠返回一個子樹。
WeakHashMap 不安全 弱鍵(weak key)Map,Map中使用的對象也被容許釋放: 這是爲解決特殊問題設計的。若是沒有map以外的引用指向某個「鍵」,則此「鍵」能夠被垃圾收集器回收。
IdentifyHashMap 不安全 使用==代替equals()對「鍵」做比較的hash map。專爲解決特殊問題而設計。
ConcurrentHashMap 安全 將Hash表分爲16segment,每次只須要的segment進行加鎖

HashMap

它根據鍵的hashCode值存儲數據,大多數狀況下能夠直接定位到它的值,於是具備很快的訪問速度,但遍歷順序倒是不肯定的。

HashMap 大概具備如下特色:

  • 底層實現是 鏈表數組,JDK 8 後又加了 紅黑樹
  • 實現了 Map 所有的方法
  • key 用 Set 存放,因此想作到 key 不容許重複,key 對應的類須要重寫 hashCode 和 equals 方法
  • 容許空鍵和空值(但空鍵只有一個,且放在第一位)
  • 元素是無序的,並且順序會不定時改變
  • 插入、獲取的時間複雜度基本是 O(1)(前提是有適當的哈希函數,讓元素分佈在均勻的位置)
  • 遍歷整個 Map 須要的時間與 桶(數組) 的長度成正比(所以初始化時 HashMap 的容量不宜太大)
  • 兩個關鍵因子:初始容量、加載因子

除了不容許 null 而且同步,Hashtable 幾乎和他同樣。

HashMap內部結構

JDK1.7 中hashmap 是經過 桶(數組)加鏈表的數據結構來實現的。當發生hash碰撞的時候,以鏈表的形式進行存儲。

JDK1.8 中hashmap 增長了在原有桶(數組) + 鏈表的基礎上增長了黑紅樹的使用。當一個hash碰撞的數量超過指定次數(TREEIFY_THRESHOLD)的時候,鏈表將轉化爲紅黑樹結構。

負載因子

默認爲0.75。通常不建議修改,

  • 加載因子太大的話發生衝突的可能就會大,查找的效率反而變低,若是內存空間緊張而對時間效率要求不高可增長。
  • 過小的話頻繁 rehash,致使性能下降,若是內存空間不少而又對時間效率要求很高可
容量

桶數默認爲16,很是規設計(通常採用素數),主要是爲了在取模和擴容時作優化,同時爲了減小衝突。

關於桶數,在構造hashmap時,若是你傳入的是一個本身設定的數字,它會調用tableSizeFor幫你轉換成一個比傳入容量參數值大的最小的2的n次方(因此無論你傳入什麼數字最終仍是2的冪)。

這裏tableSizeFor若是你看過源代碼的話,會發現用的是挺晦澀的位運算(強烈吐槽),那一大堆的運算你能夠理解爲把這個數字的全部位都變爲1,再加上1,就能獲得比傳入容量參數值大的最小的2的n次方

默認值爲16應該是

hash

HashMap 中經過將傳入鍵的 hashCode此值按位右移 16 位補零後的值進行按位異或,獲得這個鍵的哈希值。

(h = key.hashCode()) ^ (h >>> 16);

這裏是因爲,因爲哈希表的容量都是 2 的 N 次方(最大2^30),在當前,元素的 hashCode() 在不少時候下低位是相同的,這將致使衝突(碰撞),所以 1.8 之後作了個移位操做:將元素的 hashCode() 和本身右移 16 位後的結果求異或。

因爲 int 只有 32 位(4*8),無符號右移 16 位至關於把高位的一半移到低位:

ConcurrentHashMap

使用segment來分段和管理鎖,segment繼承自ReentrantLock,所以ConcurrentHashMap使用ReentrantLock來保證線程安全。

JDK1.8以前採用分段鎖,核心就是一句話:儘可能下降同步鎖的粒度。

JDK1.8以後使用CAS思想代替冗雜的分段鎖實現。

不出意料,面試者答出CAS以後一定會被追問其思想以及應用,換作我本身的話會有以下思路做答:CAS採用樂觀鎖思想達到lock free,提一下sun.misc.Unsafe中的native方法,至於CAS的其餘應用能夠聊一聊Atomic原子類和一些無鎖併發框架(如Amino),提到ABA問題加分。

Hashtable

都實現了Map接口,主要的區別有:

  1. HashMap是非synchronized的,接受null而。
  2. 另外一個區別是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。因此當有其它線程改變了HashMap的結構(增長或者移除元素),將會拋出ConcurrentModificationException,但迭代器自己的remove()方法移除元素則不會拋出ConcurrentModificationException異常。但這並非一個必定發生的行爲,要看JVM。這條一樣也是Enumeration和Iterator的區別。
  3. Hashtable在單線程環境下比HashMap要慢。
  4. HashMap不能保證隨着時間的推移Map中的元素次序是不變的。

Queue:

先進先出


線程安全

喂(Vector) S(Stack) H(hashtable) E(enumeration)


Chapter12-Error Handling with Exceptions

拋InterruptedException的表明方法有:

  • java.lang.Object 類的 wait 方法
  • java.lang.Thread 類的 sleep、join方法

dd

  1. 受檢查的異常(checked exceptions),其必須被 try{}catch語句塊所捕獲,或者在方法簽名裏經過throws子句聲明.受檢查的異常必須在編譯時被捕捉處理,命名爲 Checked Exception 是由於Java編譯器要進行檢查,Java虛擬機也要進行檢查,以確保這個規則獲得遵照.
  2. 運行時異常(runtime exceptions),須要程序員本身分析代碼決定是否捕獲和處理,好比 空指針,被0除...
  3. 而聲明爲Error的,則屬於嚴重錯誤,如系統崩潰、虛擬機錯誤、動態連接失敗等,這些錯誤沒法恢復或者不可能捕捉,將致使應用程序中斷,Error不須要捕捉。

Java ConcurrentModificationException 異常分析與解決方案

捕獲異常

catch匹配到第一個符合的處理程序就結束

自定義異常

能夠重寫構造器,傳入一個字符串

調用printStackTrace()能夠打印出異常

異常的限制:

構造器:派生類構造器不能捕獲基類構造器拋出的異常/派生類構造器的異常說明必須包含基類構造器的異常說明。

若是基類構造器沒有異常說明,派生類能有。

方法:派生類方法遵照基類方法的異常說明,可是也能夠不拋出異常。

若是基類方法沒有異常說明,派生類也不能有。

對象:派生類的對象只被要求捕獲這個類所拋出的異常/基類的對象只被要求捕獲基類所拋出的異常

異常匹配:拋出的異常能夠被此異常的基類catch


使用finally

  1. try、catch、finally語句中,在若是try語句有return語句,則返回的以後當前try中變量此時對應的值,此後對變量作任何的修改,都不影響try中return的返回值
  2. 若是finally塊中有return 語句,則返回try或catch中的返回語句忽略。
  3. 若是finally塊中拋出異常,則整個try、catch、finally塊中拋出異常

因此使用try、catch、finally語句塊中須要注意的是

  1. 儘可能在try或者catch中使用return語句。經過finally塊中達到對try或者catch返回值修改是不可行的。
  2. finally塊中避免使用return語句,由於finally塊中若是使用return語句,會顯示的消化掉try、catch塊中的異常信息,屏蔽了錯誤的發生
  3. finally塊中避免再次拋出異常,不然整個包含try語句塊的方法回拋出異常,而且會消化掉try、catch塊中的異常

Chapter13-Strings

String對象是不可變的(只讀),內部使用 char 數組存儲數據,該數組被聲明爲 final 。

方法 功能
substring 左閉右開,只有一個數值則右邊到底
int indexOf(String str) 可用於判斷子字符串是否存在

StringBuilder(線程不安全)

Java 5提出,因爲String的鏈接(+)實際上是調用了StringBuilder.append,因此,建議在for循環內使用StringBuilder來進行字符串的拼接。

StringBuffer(線程安全)

和StringBuilder相似

若是程序是在單線程下運行,或者是沒必要考慮到線程同步問題,咱們應該優先使用StringBuilder類;若是要保證線程安全,天然是StringBuffer。

優先StringBuilder,爲了線程安全用StringBuffer


正則表達式

String正則表達式相關的method

method 解釋
matches(String regex)
split(String regex)
split(String regex, int limit) 限制分割次數,最終數組數爲limit
replaceFirst(),replaceAll()

貪婪匹配和非貪婪匹配

如:String str="abcaxc"; Patter p="ab*c";

貪婪匹配:正則表達式通常趨向於最大長度匹配,也就是所謂的貪婪匹配。如上面使用模式p匹配字符串str,結果就是匹配到:abcaxc(ab*c)。

非貪婪匹配:就是匹配到結果就好,就少的匹配字符。如上面使用模式p匹配字符串str,結果就是匹配到:abc(ab*c)。


Pattern和Matcher

Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(String args);
method 解釋
matches() 是否匹配
lookingAt() 該字符串的起始部分是否匹配
find()

Compare to

返回參與比較的先後兩個字符串的asc碼的差值,

若是兩個字符串首字母不一樣,則該方法返回首字母的asc碼的差值;

若是參與比較的兩個字符串若是首字符相同,則比較下一個字符,直到有不一樣的爲止,返回該不一樣的字符的asc碼差值,若是兩個字符串不同長,能夠參與比較的字符又徹底同樣,則返回兩個字符串的長度差值


Chapter14-Type Information

RTTI:runtime type information

Class對象

延伸點:類的加載

全部的類都是在第一次使用時,動態加載到JVM中的。

構造器也是static

Class.forName(目標類全限定名的String),返回class引用,若是沒有加載就加載它

Object.getClass。返回該對象的實際類型的Class引用

Class.getInterfaces

Class.getSuperclass

Class.newInstance:


Chapter15-Generics

一般狀況下,一個編譯器處理泛型有兩種方式:Code specializationCode sharing。C++和C#是使用Code specialization的處理機制,而Java使用的是Code sharing的機制。

Code sharing方式爲每一個泛型類型建立惟一的字節碼錶示,而且將該泛型類型的實例都映射到這個惟一的字節碼錶示上。將多種泛型類形實例映射到惟一的字節碼錶示是經過類型擦除(type erasue)實現的。

也就是說,對於Java虛擬機來講,他根本不認識Map<String, String> map這樣的語法。須要在編譯階段經過類型擦除的方式進行解語法糖。

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

  1. 將全部的泛型參數用其最左邊界(最頂級的父類型)類型替換。
  2. 移除全部的類型參數。

虛擬機中沒有泛型,只有普通類和普通方法,全部泛型類的類型參數在編譯時都會被擦除,泛型類並無本身獨有的Class類對象。好比並不存在List<String>.class或是List<Integer>.class,而只有List.class

泛型接口:

生成器(generator)專門負責創造對象的類;

通常一個生成器只定義一個方法:用以產生新的對象;

基本類型沒法做爲類型參數

泛型方法:將泛型參數列表置於返回值以前

泛型方法所在的類能夠不是泛型類,若是static方法須要使用泛型能力,就必須使其成爲泛型方法

使用泛型類,必須在建立對象的時候指定類型參數的值,泛型方法不用

類型推斷避免重複的泛型參數列表,可是隻對賦值有效:

e.g:Map<Person,List<? extends Pet>> petPeople = New.Map()

反射

反射能夠用於判斷任意對象所屬的類,得到Class對象,構造任意一個對象以及調用一個對象

詳見:java中的反射機制

//獲取類型
Class c1 = Class.forName("Employee"); 
Class c2 = Employee.class;  
Employee e = new Employee(); 
Class c3 = e.getClass();
//建立對象
Objecto = c1.newInstance(); //調用了Employee的無參數構造方法.  
//獲取屬性
Field[] fs = c.getDeclaredFields();  
getDeclaredMethods()//獲取全部的方法
getReturnType() //得到方法的放回類型
getParameterTypes() //得到方法的傳入參數類型
getDeclaredMethod("方法名",參數類型.class,……)//得到特定的方法
getDeclaredConstructors()//獲取全部的構造方法
getDeclaredConstructor(參數類型.class,……) //獲取特定的構造方法
getSuperclass()//獲取某類的父類
getInterfaces()//獲取某類實現的接口

使用案例如Hibernate,BeanUtils。


動態代理

在程序運行時,運用反射機制動態建立而成。

動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。

java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力。

代理類每每會在代理對象業務邏輯先後增長一些功能性的行爲,如使用事務或者打印日誌。

jdk動態代理

必須實現InvocationHandler接口,並在該類中定義代理行爲。

cglib動態代理

依賴於字節碼技術

cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現加強,但由於採用的是繼承,因此不能對final修飾的類進行代理。


Chapter16-Arrays

數組命名時名稱與[]能夠隨意排列

粗糙數組:構成矩陣的每一個向量均可以具備任意的長度

不能實例化具備參數化類型的數組

建立測試數據:

Arrays.asList()返回的是一個List (List是一個接口,返回List實際是返回List接口的一個實現),這個List在底層是有數組實現的,因此size是fixed的

Arrays.fill(Arrays,parameters):用同一個parameter填充整個數組(引用)

Arrays實用功能:

System.arraycopy(源數組,偏移量,目標組,複製偏移量,複製個數)


Chapter17-Containers in Depth


Chapter18-I/O

推薦資料:java回憶錄—輸入輸出流詳細講解(入門經典)

11

File類(處理文件目錄問題)

file既能夠表明一個文件名,也能夠表明一個文件夾的名字

延伸點:java.io.File類中mkdir()與mkdirs()區別

File類(操做文件)

bio,nio區別要熟知,瞭解nio中的ByteBuffer,Selector,Channel能夠幫助面試者度過很多難關。幾乎提到nio一定會問netty,其實我分析了一下,問這個的面試官本身也不必定會,但就是有人喜歡問,因此我們適當應付一下就好:一個封裝很好擴展很好的nio框架,經常使用於RPC框架之間的傳輸層通訊。


後綴是stream的都是字節流,其餘的都是字符流

聲明爲static和transient類型的成員數據不能被串行化。由於static表明類的狀態, transient表明對象的臨時數據。

inputstream的close方法用來關閉流

skip()用來跳過一些字節

mark()用來標記流

reset()復位流

I/O的典型使用方法

一、緩衝輸入文件

緩衝區的做用的主要目的是:避免每次和硬盤打交道,提升數據訪問的效率。

public class BufferedInputFile {
  public static String read(String filename) throws IOException {
    BufferedReader in = new BufferedReader(new FileReader(filename));
    String s;
    StringBuilder sb = new StringBuilder();
    while((s = in.readLine())!= null)
      sb.append(s + "\n");
    in.close();
    return sb.toString();
  }
  public static void main(String[] args)throws IOException {
    System.out.print(read("BufferedInputFile.java"));
  }
}

二、從內存輸入

public class MemoryInput {
  public static void main(String[] args)throws IOException {
    StringReader in = new StringReader(BufferedInputFile.read("MemoryInput.java"));
    int c;
    //read()是以int形式返回下一字節,必須轉爲char才能正確打印
    while((c = in.read()) != -1)
      System.out.print((char)c);
  }
}

三、格式化的內存輸入

public class FormattedMemoryInput {
  public static void main(String[] args)
  throws IOException {
    try {
      DataInputStream in = new DataInputStream(new ByteArrayInputStream(
         BufferedInputFile.read("FormattedMemoryInput.java").getBytes()));
      while(true)
        System.out.print((char)in.readByte());
    } catch(EOFException e) {
      System.err.println("End of stream");
    }
  }
}

四、基本的文件輸出

public class BasicFileOutput {
  static String file = "BasicFileOutput.out";
  public static void main(String[] args)throws IOException {
    BufferedReader in = new BufferedReader(
      new StringReader(BufferedInputFile.read("BasicFileOutput.java")));
    PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
    int lineCount = 1;
    String s;
    while((s = in.readLine()) != null )
      out.println(lineCount++ + ": " + s);
    out.close();
    // Show the stored file:
    System.out.println(BufferedInputFile.read(file));
  }
}

爲了提升讀寫性能,能夠採用什麼流

Java中有幾種類型的流

JDK 爲每種類型的流提供了一些抽象類以供繼承,分別是哪些類

對文本文件操做用什麼I/O流

對各類基本數據類型和String類型的讀寫,採用什麼流

能指定字符編碼的 I/O 流類型是什麼

延伸點:裝飾者模式

BIO:同步阻塞式IO,簡單理解:一個鏈接一個線程;Apache,Tomcat。主要是併發量要求不高的場景
NIO:同步非阻塞IO,簡單理解:一個請求一個線程;Nginx,Netty。主要是高併發量要求的場景
AIO:異步非阻塞IO,簡單理解:一個有效請求一個線程;還不是特別成熟,底層也基本是多線程模擬,因此應用場景很少,Netty曾經用了,但又放棄了。


序列化

什麼是序列化?如何實現 Java 序列化及注意事項

Serializable 與 Externalizable 的區別

Socket

    • socket 選項 TCP NO DELAY 是指什麼
    • Socket 工做在 TCP/IP 協議棧是哪一層
    • TCP、UDP 區別及 Java 實現方式
  • 說幾點 IO 的最佳實踐
  • 直接緩衝區與非直接緩衝器有什麼區別?
  • 怎麼讀寫 ByteBuffer?ByteBuffer 中的字節序是什麼
  • 當用System.in.read(buffer)從鍵盤輸入一行n個字符後,存儲在緩衝區buffer中的字節數是多少
  • 如何使用掃描器類(Scanner Class)令牌化

Chapter19-Enumerated Types

方法

方法 功能 返回值
values() 返回enum實例的數組 T[]
compareTo(E o) 順序比較,若是該枚舉對象位於指定枚舉對象以後,則返回正整數;反之返回負整數;不然返回零; int
name() 返回此枚舉實例的名稱
getDeclaringClass() 返回實例所屬於的enum類 T
ordinal() 返回實例聲明時候的順序 int

添加方法

定義實例方法必須在任何方法或者屬性前

定義實例方法後面加上「;」,而後開始寫方法


Chapter21-併發

線程安全與鎖

當多個線程訪問某個類時,無論運行時環境採用何種調度方式或者這些線程將如何交替進行,而且在主調代碼中不須要任何額外的同步或協同,這個類都能表現出正確的行爲,那麼稱這個類是線程安全的

一般與鎖一塊兒出現:除了synchronized以外,還常常被問起的是juc中的Lock接口,其具體實現主要有兩種:可重入鎖,讀寫鎖。這些都沒問題的話,還會被詢問到分佈式下的同步鎖,通常藉助於中間件實現,如Redis,Zookeeper等,開源的Redis分佈式鎖實現有Redisson,回答注意點有兩點:一是注意鎖的可重入性(藉助於線程編號),二是鎖的粒度問題。除此以外就是一些juc的經常使用工具類如:CountdownLatch,CyclicBarrir,信號量

線程

建立線程

  1. 繼承Thread,重寫run方法,建立實例並調用start方法
  2. 實現runnable接口,編寫run方法,傳入Thread。e.g: Thread t = new Thread(new Runnable())
  3. 實現Callable接口,重寫call方法,線程結束後能夠有返回值,可是該方式是依賴於線程池的,必須調用exec.submit(new Callable());
使用Executor
ExecutorService exec = Executors.newCacheThreadPool();
for(int i ; i <5 ; i++)
//Liftoff實現了runnable接口
    exec.execute(new Liftoff());
//防止新任務提交給這個executor
exec.shutdown();

newFixedThreadPool(int number);一次性預先執行高代價的線程分配

newSingleThreadExecutor; 相似於newFixedThreadPool(1),會序列化全部提交給它的任務。

Thread的方法

method 解釋
run() 執行線程體中具體的內容,若是直接調用run方法,其實仍是單線程
start() 啓動線程對象,使其進入就緒狀態
sleep() 佔着CPU不工做。能夠拋出interruptException,可是異常拋出的時候回清理這個標誌,致使在catch裏面調用isInterrupt(),總爲false。TimeUnit.SECONDS.sleep(1):可讀性更高
suspend() 使線程掛起,要經過resume()方法使其從新啓動
join() 等待該線程終止;在父線程中,子線程調用join,父線程被掛起,等待子線程結束纔回復。
yield() 當前線程放棄CPU,全部線程(包括當前線程)共同競爭CPU。
setDeamon(true) 設置爲後臺線程,必須在線程start以前調用。
getName() 有一構造函數參數爲String name;獲取線程的name。
isAlive() 判斷是否被掛起
holdsLock() 返回true若是當且僅當當前線程擁有某個具體對象的鎖。
wait 和 sleep的區別

wait:等待使用CPU
sleep:佔着CPU不工做

線程轉換

fff

結束線程

  1. run方法執行完成,線程正常結束
  2. 線程拋出一個未捕獲的Exception或者Error
  3. 直接調用該線程的Stop方法結束線程(不建議使用,容易致使死鎖)
  4. 使用interrupt方法中斷線程。可使一個被阻塞的線程拋出一箇中斷異常,從而使線程提早結束阻塞狀態,退出堵塞代碼。

延伸點:注意interrupted()會清楚中斷狀態

參考連接:如何正確地中止一個線程?


優先級

調度器傾向於讓優先級最高的線程先執行,一般在run的開頭部分設定

getPriority():讀取現有線程的優先級

setPriority():修改線程優先級。


LocalThread

每一個線程都有一個ThreadLocal就是每一個線程都擁有了本身獨立的一個變量,競爭條件被完全消除了。

它是爲建立代價高昂的對象獲取線程安全的好方法,好比你能夠用ThreadLocal讓SimpleDateFormat變成線程安全的,由於那個類建立代價高昂且每次調用都須要建立不一樣的實例因此不值得在局部範圍使用它,若是爲每一個線程提供一個本身獨有的變量拷貝,將大大提升效率。

首先,經過複用減小了代價高昂的對象的建立個數。其次,你在沒有使用高代價的同步或者不變性的狀況下得到了線程安全。線程局部變量的另外一個不錯的例子是ThreadLocalRandom類,它在多線程環境中減小了建立代價高昂的Random對象的個數。

參考資料:深刻分析 ThreadLocal 內存泄漏問題


粒度


樂觀鎖和悲觀鎖

悲觀鎖是獨佔鎖,阻塞鎖,寫入頻繁使用悲觀鎖

樂觀鎖是非獨佔鎖,非阻塞鎖。讀取頻繁使用樂觀鎖。

樂觀鎖( Optimistic Locking)實際上是一種思想。相對悲觀鎖而言,樂觀鎖假設認爲數據通常狀況下不會形成衝突,因此在數據進行提交更新的時候,纔會正式對數據的衝突與否進行檢測,若是發現衝突了,則讓返回用戶錯誤的信息,讓用戶決定如何去作。

有一種樂觀鎖的實現方式就是CAS ,這種算法在JDK 1.5中引入的java.util.concurrent(J.U.C)中有普遍應用。可是值得注意的是這種算法會存在ABA問題(部分經過版本號來解決)

這裏就是悲觀鎖樂觀鎖的應用處理併發問題

參考資料:樂觀鎖的一種實現方式——CAS


死鎖

死鎖是指兩個或兩個以上的進程在執行過程當中,因爭奪資源而形成的一種互相等待的現象,若無外力做用,它們都將沒法推動下去。這是一個嚴重的問題,由於死鎖會讓你的程序掛起沒法完成任務。

死鎖的發生必須知足如下四個條件:

  1. 互斥條件:一個資源每次只能被一個進程使用。
  2. 請求與保持條件:一個進程因請求資源而阻塞時,對已得到的資源保持不放。
  3. 不剝奪條件:進程已得到的資源,在末使用完以前,不能強行剝奪。
  4. 循環等待條件:若干進程之間造成一種頭尾相接的循環等待資源關係。

避免死鎖最簡單的方法就是阻止循環等待條件,將系統中全部的資源設置標誌位、排序,規定全部的進程申請資源必須以必定的順序(升序或降序)作操做來避免死鎖。

Q:如何檢查死鎖?

A:經過jConsole檢查死鎖

參考資料:java 查看線程死鎖


可重入鎖

可重入鎖,也叫作遞歸鎖,指的是同一線程 外層函數得到鎖以後 ,內層遞歸函數仍然有獲取該鎖的代碼,但不受影響。

在JAVA環境下 ReentrantLock 和synchronized 都是 可重入鎖


synchronized

加到 static 方法上是給 Class 上鎖,即整個類上鎖。


Lock

Lock對象必須被顯式地建立、鎖定和釋放。

緊接着lock的調用,後面是try-finally語句,同時finally裏面要有unclock來釋放鎖

public class MutexEvenGenerator extends IntGenerator {
  private int currentEvenValue = 0;
  private Lock lock = new ReentrantLock();
  public int next() {
    lock.lock();
    try {
      ++currentEvenValue;
      Thread.yield(); // Cause failure faster
      ++currentEvenValue;
      return currentEvenValue;
} finally {
      lock.unlock();
    }
}
public static void main(String[] args) {
    EvenChecker.test(new MutexEvenGenerator());
  }
} ///:~

volatile

  1. volatile保證了可視性和有序性,沒有原子性。
  2. 因爲有些時候對 volatile的操做,不會被保存,說明不會形成阻塞。不可用與多線程環境下的計數器。
  3. 禁止指令重排序優化

​ 禁止指令重排序優化。編譯器只保證程序執行結果與源代碼相同,卻不保證明際指令的順序與源代碼相同。這在單線程看起來沒什麼問題,然而一旦引入多線程,這種亂序就可能致使嚴重問題。volatile關鍵字就能夠從語義上解決這個問題。 jdk1.5之後生效。

參考:Java面試官最愛的volatile關鍵字


JMM(java內存模型)

關注點:主存和工做內存, happens-before原則(主要是前三條)

JMM規定全部變量都是存在主存中的,每一個線程又包含本身的工做內存。因此線程的操做都是以工做內存爲主,它們只能訪問本身的工做內存,且工做先後都要把值在同步回主內存。

java內存模型

原子性

基本類型變量,除了long和double,都能保證原子性的操做。

long和double因爲是分離的32位來操做,不能保證原子性。

可見性

當一個變量被volatile修飾時,那麼對它的修改會馬上刷新到主存,當其它線程須要讀取該變量時,會去內存中讀取新值。而普通變量則不能保證這一點。

其實經過synchronized和Lock也可以保證可見性,線程在釋放鎖以前,會把共享變量值都刷回主存,可是synchronized和Lock的開銷都更大。

有序性

JMM是容許編譯器和處理器對指令重排序的,可是規定了as-if-serial語義,即無論怎麼重排序,程序的執行結果不能改變。


happens-before原則
  1. 程序順序規則: 一個線程中的每一個操做,happens-before於該線程中的任意後續操做
  2. 監視器鎖規則:對一個線程的解鎖,happens-before於隨後對這個線程的加鎖
  3. volatile變量規則: 對一個volatile域的寫,happens-before於後續對這個volatile域的讀
  4. 傳遞性:若是A happens-before B ,且 B happens-before C, 那麼 A happens-before C
  5. start()規則: 若是線程A執行操做ThreadB_start()(啓動線程B) , 那麼A線程的ThreadB_start()happens-before 於B中的任意操做
  6. join()原則: 若是A執行ThreadB.join()而且成功返回,那麼線程B中的任意操做happens-before於線程A從ThreadB.join()操做成功返回。
  7. interrupt()原則: 對線程interrupt()方法的調用先行發生於被中斷線程代碼檢測到中斷事件的發生,能夠經過Thread.interrupted()方法檢測是否有中斷髮生
  8. finalize()原則:一個對象的初始化完成先行發生於它的finalize()方法的開始

優化

  • 減小鎖持有時間(儘可能縮小鎖的範圍)
  • 減少鎖粒度
  • 鎖分離
  • 鎖粗化
  • 鎖消除

同步器(AQS)

同步器是一些使線程可以等待另外一個線程的對象,容許它們協調動做。最經常使用的同步器是CountDownLatch和Semaphore,不經常使用的是Barrier 和Exchanger

延伸點:java多線程面試彙總

併發工具類(三)控制併發線程數的Semaphore


其餘

Java程序的種類

  1. 內嵌於Web文件中,由瀏覽器來觀看的_Applet
  2. 可獨立運行的 Application
  3. 服務器端的 Servlets

關鍵字和保留字

ggg

要注意true,false,null, friendly,sizeof不是java的關鍵字,可是你不能把它們做爲java標識符用。


null

  1. null是表明不肯定的對象,null是一個關鍵字。所以能夠將null賦給引用類型變量,但不能夠將null賦給基本類型變量。

  2. null自己不是對象,也不是Objcet的實例
  3. Java默認給引用變量賦值
  4. 容器類型與null

List:容許重複元素,能夠加入任意多個null。

Set:不容許重複元素,最多能夠加入一個null。

Map:Map的key最多能夠加入一個null,value字段沒有限制。

數組:基本類型數組,定義後,若是不給定初始值,則java運行時會自動給定值。引用類型數組,不給定初始值,則全部的元素值爲null。

  1. null的其餘做用

一、判斷一個引用類型數據是否null。 用==來判斷。

二、釋放內存,讓一個非null的引用類型變量指向null。這樣這個對象就再也不被任何對象應用了。等待JVM垃圾回收機制去回收。

包導入

java.lang包定義了一些基本的類型,包括Integer,String之類的,是java程序必備的包,有解釋器自動引入,無需手動導入

工具 功能
javac.exe 把.java文件編譯爲.class文件(每一個類一個.class文件)
java.exe 執行編譯好的.class文件
javadoc.exe 生成Java說明文檔,api文檔
jdb.exe Java調試器
javaprof.exe 剖析工具

java代碼執行過程

  • 編譯器將Java源代碼編譯成字節碼class文件
  • 類加載到JVM裏面後,執行引擎把字節碼轉爲可執行代碼
  • 執行的過程,再把可執行代碼轉爲機器碼,由底層的操做系統完成執行。

常見碼錶

Java語言使用的是Unicode字符集。

ascii:美國標準信息交換碼。使用的是1個字節的7位來表示該表中的字符。

ISO8859-1:拉丁碼錶。使用1個字節來表示。

GB2312:簡體中文碼錶。

GBK:簡體中文碼錶,比GB2312融入更多的中文文件和符號。

unicode:國際標準碼錶。都用兩個字節表示一個字符。

UTF-8:對unicode進行優化,每個字節都加入了標識頭。


面向對象的五大原則

名稱 功能
單一職責原則(Single-Resposibility Principle) 一個類,最好只作一件事,只有一個引發它的變化。單一職責原則能夠看作是低耦合、高內聚在面向對象原則上的引伸,將職責定義爲引發變化的緣由,以提升內聚性來減小引發變化的緣由。
開放封閉原則(Open-Closed principle) 軟件實體應該是可擴展的,而不可修改的。也就是,對擴展開放,對修改封閉的。
Liskov替換原則(Liskov-Substituion Principle) 子類必須可以替換其基類。這一思想體現爲對繼承機制的約束規範,只有子類可以替換基類時,才能保證系統在運行期內識別子類,這是保證繼承複用的基礎。
依賴倒置原則(Dependecy-Inversion Principle) 依賴於抽象。具體而言就是高層模塊不依賴於底層模塊,兩者都同依賴於抽象;抽象不依賴於具體,具體依賴於抽象。
接口隔離原則(Interface-Segregation Principle) 使用多個小的專門的接口,而不要使用一個大的總接口

Session

session.setAttribute()和session.getAttribute()配對使用,做用域是整個會話期間,在全部的頁面都使用這些數據的時候使用。

request.getAttribute()表示從request範圍取得設置的屬性,必需要先setAttribute設置屬性,才能經過getAttribute來取得,設置與取得的爲Object對象類型。


J2EE相關名詞

  1. web容器:給處於其中的應用程序組件(JSP,SERVLET)提供一個環境,使JSP,SERVLET直接和容器中的環境變量接接口互,沒必要關注其它系統問題。主要有WEB服務器來實現。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。該容器提供的接口嚴格遵照J2EE規範中的WEB APPLICATION 標準。咱們把遵照以上標準的WEB服務器就叫作J2EE中的WEB容器。
  2. Web container:實現J2EE體系結構中Web組件協議的容器。這個協議規定了一個Web組件運行時的環境,包括安全,一致性,生命週期管理,事務,配置和其它的服務。一個提供和JSP和J2EE平臺APIs界面相同服務的容器。一個Web container 由Web服務器或者J2EE服務器提供。
  3. EJB容器:Enterprise java bean 容器。更具備行業領域特點。他提供給運行在其中的組件EJB各類管理功能。只要知足J2EE規範的EJB放入該容器,立刻就會被容器進行高效率的管理。而且能夠經過現成的接口來得到系統級別的服務。例如郵件服務、事務管理。一個實現了J2EE體系結構中EJB組件規範的容器。 這個規範指定了一個Enterprise bean的運行時環境,包括安全,一致性,生命週期,事務, 配置,和其餘的服務。
  4. JNDI:(Java Naming & Directory Interface)JAVA命名目錄服務。主要提供的功能是:提供一個目錄系統,讓其它各地的應用程序在其上面留下本身的索引,從而知足快速查找和定位分佈式應用程序的功能。
  5. JMS:(Java Message Service)JAVA消息服務。主要實現各個應用程序之間的通信。包括點對點和廣播。
  6. JTA:(Java Transaction API)JAVA事務服務。提供各類分佈式事務服務。應用程序只需調用其提供的接口便可。
  7. JAF:(Java Action FrameWork)JAVA安全認證框架。提供一些安全控制方面的框架。讓開發者經過各類部署和自定義實現本身的個性安全控制策略。
  8. RMI/IIOP:(Remote Method Invocation /internet對象請求中介協議)他們主要用於經過遠程調用服務。例如,遠程有一臺計算機上運行一個程序,它提供股票分析服務,咱們能夠在本地計算機上實現對其直接調用。固然這是要經過必定的規範才能在異構的系統之間進行通訊。RMI是JAVA特有的。RMI-IIOP出現之前,只有RMI和CORBA兩種選擇來進行分佈式程序設計。RMI-IIOP綜合了RMI和CORBA的優勢,克服了他們的缺點,使得程序員能更方便的編寫分佈式程序設計,實現分佈式計算。首先,RMI-IIOP綜合了RMI的簡單性和CORBA的多語言性(兼容性),其次RMI-IIOP克服了RMI只能用於Java的缺點和CORBA的複雜性(能夠不用掌握IDL)。

延伸點:JDK, JRE 和JVM的區別


Properties類

繼承自Hashtable

我本身實際使用應該只有在xml裏

<context:property-placeholder location="classpath*:conf/conf_a.properties"/>  
   <bean class="com.xxx.aaa.Bean1"  
          p:driverClassName="${modulea.jdbc.driverClassName}"  
          p:url="${modulea.jdbc.url}"  
          p:username="${modulea.jdbc.username}"  
          p:password="${modulea.jdbc.password}"/>

可變參數

兼容數組類參數的。

必須做爲參數列表的最後一項

能匹配定長的方法,那麼優先匹配該方法。含有不定參數的那個重載方法是最後被選中的。

參考: Java方法的可變參數個數

相關文章
相關標籤/搜索