一、String類爲何是final的html
final的目的是不能改變,出於安全和效率的考慮。final修飾類時,類不可被繼承;修飾變量,變量的值不能夠被修改;修飾方法,方法不可被子類重寫。若是有一個String的引用,它引用的必定是一個String對象,而不多是其餘類的對象。String 一旦被建立是不能被修改的,由於設計者將 String 設計爲能夠共享的。設計成final,JVM纔不用對相關方法在虛函數表中查詢,而直接定位到String類的相關方法上,提升了執行效率。 Java設計者認爲共享帶來的效率更高。總而言之,就是要保證 java.lang.String 引用的對象必定是 java.lang.String的對象,而不是引用它的子孫類,這樣才能保證它的效率和安全。前端
二、HashMap的源碼,實現原理,底層結構。java
HashMap的實現原理:首先有一個每一個元素都是鏈表(可能表述不許確)的數組,當添加一個元素(key-value)時,就首先計算元素key的hash值,以此肯定插入數組中的位置,可是可能存在同一hash值的元素已經被放在數組同一位置了,這時就添加到同一hash值的元素的後面,他們在數組的同一位置,可是造成了鏈表,同一各鏈表上的Hash值是相同的,因此說數組存放的是鏈表。而當鏈表長度太長時,鏈表就轉換爲紅黑樹,這樣大大提升了查找的效率。當鏈表數組的容量超過初始容量的0.75時,再散列將鏈表數組擴大2倍,把原鏈表數組的搬移到新的數組中。node
在JDK1.6,JDK1.7中,HashMap採用位桶+鏈表實現,即便用鏈表處理衝突,同一hash值的鏈表都存儲在一個鏈表裏。可是當位於一個桶中的元素較多,即hash值相等的元素較多時,經過key值依次查找的效率較低。而JDK1.8中,HashMap採用位桶+鏈表+紅黑樹實現,當鏈表長度超過閾值(8)時,將鏈表轉換爲紅黑樹,這樣大大減小了查找時間。mysql
JDK1.8中的數據結構:程序員
(1)位桶結構web
transient
Node<k,v>[] table;
//存儲(位桶)的數組</k,v>
算法
(2)數組元素Node<k,v>實現了Entry接口sql
//Node是單向鏈表,它實現了Map.Entry接口
static
class
Node<k,v>
implements
Map.Entry<k,v> {
final
int
hash;
final
K key;
V value;
Node<k,v> next;
//構造函數Hash值 鍵 值 下一個節點
Node(
int
hash, K key, V value, Node<k,v> next) {
this
.hash = hash;
this
.key = key;
this
.value = value;
this
.next = next;
}
public
final
K getKey() {
return
key; }
public
final
V getValue() {
return
value; }
public
final
String toString() {
return
key + = + value; }
public
final
int
hashCode() {
return
Objects.hashCode(key) ^ Objects.hashCode(value);
}
public
final
V setValue(V newValue) {
V oldValue = value;
value = newValue;
return
oldValue;
}
//判斷兩個node是否相等,若key和value都相等,返回true。能夠與自身比較爲true
public
final
boolean
equals(Object o) {
if
(o ==
this
)
return
true
;
if
(o
instanceof
Map.Entry) {
Map.Entry<!--?,?--> e = (Map.Entry<!--?,?-->)o;
if
(Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return
true
;
}
return
false
;
}</k,v></k,v></k,v></k,v>
//紅黑樹
static
final
class
TreeNode<k,v>
extends
LinkedHashMap.Entry<k,v> {
TreeNode<k,v> parent;
// 父節點
TreeNode<k,v> left;
//左子樹
TreeNode<k,v> right;
//右子樹
TreeNode<k,v> prev;
// needed to unlink next upon deletion
boolean
red;
//顏色屬性
TreeNode(
int
hash, K key, V val, Node<k,v> next) {
super
(hash, key, val, next);
}
//返回當前節點的根節點
final
TreeNode<k,v> root() {
for
(TreeNode<k,v> r =
this
, p;;) {
if
((p = r.parent) ==
null
)
return
r;
r = p;
}
}</k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,v>
對於隨機訪問get和set,ArrayList以爲優於LinkedList,由於LinkedList要移動指針。 數據庫
對於新增和刪除操做add和remove,LinedList比較佔優點,由於ArrayList要移動數據。
這一點要看實際狀況的。若只對單條數據插入或刪除,ArrayList的速度反而優於LinkedList。但如果批量隨機的插入刪除數據,LinkedList的速度大大優於ArrayList. 由於ArrayList每插入一條數據,要移動插入點及以後的全部數據。 這一點我作了實驗。在分別有200000條「記錄」的ArrayList和LinkedList的首位插入20000條數據,LinkedList耗時約是ArrayList的20分之1。
查找操做indexOf,lastIndexOf,contains等,二者差很少。
隨機查找指定節點的操做get,ArrayList速度要快於LinkedList.
這裏只是理論上分析,事實上也不必定,ArrayList在末尾插入和刪除數據的話,速度反而比LinkedList要快。
http://blog.csdn.net/qianzhiyong111/article/details/6678035
五、Java中的隊列都有哪些,有什麼區別
在java5中新增長了java.util.Queue接口,用以支持隊列的常見操做。Queue接口與List、Set同一級別,都是繼承了Collection接口。 Queue使用時要儘可能避免Collection的add()和remove()方法,而是要使用offer()來加入元素,使用poll()來獲取並移出元素。它們的優 點是經過返回值能夠判斷成功與否,add()和remove()方法在失敗的時候會拋出異常。 若是要使用前端而不移出該元素,使用 element()或者peek()方法。 值得注意的是LinkedList類實現了Queue接口,所以咱們能夠把LinkedList當成Queue來用。
LinkedList實現了Queue接口。Queue接口窄化了對LinkedList的方法的訪問權限(即在方法中的參數類型若是是Queue時,就徹底只能訪問Queue接口所定義的方法 了,而不能直接訪問 LinkedList的非Queue的方法),以使得只有恰當的方法纔可使用。BlockingQueue 繼承了Queue接口
http://blog.sina.com.cn/s/blog_566fd08d0101fwcr.html
六、反射中,Class.forName和classloader的區別。
首先這個問題,沒有固定答案,全看我的理解,畢竟這2個的數據結構,你們確定都是知道的。能有以下回答,基本就夠用啦。
數組: 數組就像一個班級同樣,一旦分完班,一個班多少人,每一個人的學號啥的都是肯定的啦,根據學號,喊一個學號就會有我的中, 這個學號就是下標,根據下標找人就是快。單個之間關係不大 鏈表: 鏈表就像一個鐵鏈,一環扣一環,不能跳過一個,直接去找下一個,必須挨個找,根據節點的next的指向,查找,要查找就得一個個查。
(1) 從邏輯結構角度來看 a, 數組必須事先定義固定的長度(元素個數),不能適應數據動態地增減的狀況。當數據增長時,可能超出原先定義的元素個數;當數據減小時,形成內存浪費。 b,鏈表動態地進行存儲分配,能夠適應數據動態地增減的狀況,且能夠方便地插入、刪除數據項。(數組中插入、刪除數據項時,須要移動其它數據項) (2)從內存存儲角度來看 a,(靜態)數組從棧中分配空間(這個有待肯定,畢竟是Java的數組), 對於程序員方便快速,但自由度小。 b, 鏈表從堆中分配空間, 自由度大但申請管理比較麻煩.
數組和鏈表的區別整理以下:
數組靜態分配內存,鏈表動態分配內存; 數組在內存中連續,鏈表不連續; 數組元素在棧區,鏈表元素在堆區; 數組利用下標定位,時間複雜度爲O(1),鏈表定位元素時間複雜度O(n); 數組插入或刪除元素的時間複雜度O(n),鏈表的時間複雜度O(1)。
九、Java內存泄露的問題調查定位:jmap,jstack的使用等等。
http://blog.csdn.net/gzh0222/article/details/8538727
http://www.open-open.com/lib/view/open1390916852007.html
十、string、stringbuilder、stringbuffer區別
http://www.cnblogs.com/xudong-bupt/p/3961159.html
http://blog.csdn.net/clam_clam/article/details/6831345
十一、hashtable和hashmap的區別
http://www.cnblogs.com/carbs/archive/2012/07/04/2576995.html
十二、異常的結構,運行時異常和非運行時異常,各舉個例子。http://blog.csdn.net/qq_27093465/article/details/52268531
1三、String 類的經常使用方法
http://gao851214.blog.163.com/blog/static/344574752013124115841575/
.ToLower() //轉爲小寫字符串"AbC"-->"abc"
.ToUpper() //轉爲大寫"AbC" -->"ABC"
.Trim() //去掉字符串首尾的空格" abc "-->"abc"
Equals(string value,StringComparison comparisonType); //相等判斷
CompareTo(string value) //與value比較大小
.Split(params char [] separator) //separator 是分隔字符,如:','、'|' 等等。
.Split(char [] separator ,StringSplitOptions splitOpt)//StringSplitOptions.RemoveEmptyEntries
.Split(string[] separator,StringSplitOptions splitOpt)// 按字符串分隔
.Replace(char oldChar,char newChar) //替換字符串中的字符,如:'a'替換爲'b'
.Replace(string oldStr,string newStr)//替換字符串中的字符串,如:"李時珍"替換爲"李秀麗"
.SubString(int startIndex) //從指定序號開始,一直到最後,組成的字符串
.SubString(int startIndex,int length) //從指定序號startIndex,連續取length個,若是超過長度會報異常
.Contains(char c) // 是否包含 字符
.Contains(string str) // 是否包含 子字符串
.StartsWith(string str) //是否以str開頭,如:http://baidu.com就以http://開頭
.EndsWith(string str) //是否以str結尾
IndexOf(char c) //找到第一個字符c的index,若是沒找到返回-1
.IndexOf(string str) //找到第一個字符串str的位置
1四、 Java 的引用類型有哪幾種
http://blog.csdn.net/yxpjx/article/details/6171868
在JDK 1.2之前的版本中,若一個對象不被任何變量引用,那麼程序就沒法再使用這個對象。也就是說,只有對象處於可觸及(reachable)狀態,程序才能使用它。從JDK 1.2版本開始,把對象的引用分爲4種級別,從而使程序能更加靈活地控制對象的生命週期。這4種級別由高到低依次爲:強引用、軟引用、弱引用和虛引用。
⑴強引用(StrongReference) 強引用是使用最廣泛的引用。若是一個對象具備強引用,那垃圾回收器毫不會回收它。當內存空間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具備強引用的對象來解決內存不足的問題。 ps:強引用其實也就是咱們平時A a = new A()這個意思。
⑵軟引用(SoftReference) 若是一個對象只具備軟引用,則內存空間足夠,垃圾回收器就不會回收它;若是內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就能夠被程序使用。軟引用可用來實現內存敏感的高速緩存(下文給出示例)。 軟引用能夠和一個引用隊列(ReferenceQueue)聯合使用,若是軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。
⑶弱引用(WeakReference) 弱引用與軟引用的區別在於:只具備弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它所管轄的內存區域的過程當中,一旦發現了只具備弱引用的對象,無論當前內存空間足夠與否,都會回收它的內存。不過,因爲垃圾回收器是一個優先級很低的線程,所以不必定會很快發現那些只具備弱引用的對象。 弱引用能夠和一個引用隊列(ReferenceQueue)聯合使用,若是弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。
⑷虛引用(PhantomReference) 「虛引用」顧名思義,就是形同虛設,與其餘幾種引用都不一樣,虛引用並不會決定對象的生命週期。若是一個對象僅持有虛引用,那麼它就和沒有任何引用同樣,在任什麼時候候均可能被垃圾回收器回收。 虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列 (ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,若是發現它還有虛引用,就會在回收對象的內存以前,把這個虛引用加入到與之 關聯的引用隊列中。
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue);
程序能夠經過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。若是程序發現某個虛引用已經被加入到引用隊列,那麼就能夠在所引用的對象的內存被回收以前採起必要的行動。
1五、抽象類和接口的區別
http://www.cnblogs.com/azai/archive/2009/11/10/1599584.html
1.abstract class 在 Java 語言中表示的是一種繼承關係,一個類只能使用一次繼承關係。可是,一個類卻能夠實現多個interface。
2.在abstract class 中能夠有本身的數據成員,也能夠有非abstarct的成員方法,而在interface中,只可以有靜態的不能被修改的數據成員(也就是必須是static final的,不過在 interface中通常不定義數據成員),全部的成員方法都是abstract的。
3.abstract class和interface所反映出的設計理念不一樣。其實abstract class表示的是"is-a"關係,interface表示的是"like-a"關係。
4.實現抽象類和接口的類必須實現其中的全部方法。抽象類中能夠有非抽象方法。接口中則不能有實現方法。
5.接口中定義的變量默認是public static final 型,且必須給其初值,因此實現類中不能從新定義,也不能改變其值。
6.抽象類中的變量默認是 friendly 型,其值能夠在子類中從新定義,也能夠從新賦值。
7.接口中的方法默認都是 public,abstract 類型的。
結論abstract class 和 interface 是 Java語言中的兩種定義抽象類的方式,它們之間有很大的類似性。可是對於它們的選擇卻又每每反映出對於問題領域中的概 念本質的理解、對於設計意圖的反映是否正確、合理,由於它們表現了概念間的不一樣的關係(雖然都可以實現需求的功能)。這其實也是語言的一種的慣用法,但願讀者朋友可以細細體會。
1六、 java的基礎類型和字節大小
Int: 4 字節 Short: 2字節 Long: 8字節 Byte: 1字節 Character: 2字節 Float: 4字節 Double: 8字節Boolean:系統沒有提供Size方法;http://www.cnblogs.com/doit8791/archive/2012/05/25/2517448.html
1七、Hashtable,HashMap,ConcurrentHashMap底層實現原理與線程安全問題。
http://blog.csdn.net/qq_27093465/article/details/52279473
1八、若是不讓你用Java Jdk提供的工具,你本身實現一個Map,你怎麼作。
說了很久,說了HashMap源代碼,若是我作,就會借鑑HashMap的原理,說了一通HashMap實現。
http://www.cnblogs.com/xwdreamer/archive/2012/05/14/2499339.html
http://www.importnew.com/7099.html
HashMap是基於哈希表的Map接口的非同步實現。此實現提供全部可選的映射操做,並容許使用null值和null鍵。此類不保證映射的順序,特別是它不保證該順序恆久不變。在java編程語言中,最基本的結構就是兩種,一個是數組,另一個是模擬指針(引用),全部的數據結構均可以用這兩個基本結構來構造的,HashMap也不例外。HashMap其實是一個「鏈表散列」的數據結構,即數組和鏈表的結合體。
HashMap的功能是經過「鍵(key)」可以快速的找到「值」。下面咱們分析下HashMap存數據的基本流程:
一、 當調用put(key,value)時,首先獲取key的hashcode,int hash = key.hashCode();
二、 再把hash經過一下運算獲得一個int h.
hash ^= (hash >>> 20) ^ (hash>>> 12);
int h = hash ^ (hash >>> 7) ^ (hash>>> 4);
爲何要通過這樣的運算呢?這就是HashMap的高明之處。先看個例子,一個十進制數32768(二進制1000 0000 0000 0000),通過上述公式運算以後的結果是35080(二進制1000 1001 0000 1000)。看出來了嗎?或許這樣還看不出什麼,再舉個數字61440(二進制1111 0000 0000 0000),運算結果是65263(二進制1111 1110 1110 1111),如今應該很明顯了,它的目的是讓「1」變的均勻一點,散列的本意就是要儘可能均勻分佈。那這樣有什麼意義呢?看第3步。
三、 獲得h以後,把h與HashMap的承載量(HashMap的默認承載量length是16,能夠自動變長。在構造HashMap的時候也能夠指定一個長 度。這個承載量就是上圖所描述的數組的長度。)進行邏輯與運算,即 h & (length-1),這樣獲得的結果就是一個比length小的正數,咱們把這個值叫作index。其實這個index就是索引將要插入的值在數組中的 位置。第2步那個算法的意義就是但願可以得出均勻的index,這是HashTable的改進,HashTable中的算法只是把key的 hashcode與length相除取餘,即hash % length,這樣有可能會形成index分佈不均勻。還有一點須要說明,HashMap的鍵能夠爲null,它的值是放在數組的第一個位置。
四、 咱們用table[index]表示已經找到的元素須要存儲的位置。先判斷該位置上有沒有元素(這個元素是HashMap內部定義的一個類Entity, 基本結構它包含三個類,key,value和指向下一個Entity的next),沒有的話就建立一個Entity<k,v>對象,在 table[index]位置上插入,這樣插入結束;若是有的話,經過鏈表的遍歷方式去逐個遍歷,看看有沒有已經存在的key,有的話用新的value替 換老的value;若是沒有,則在table[index]插入該Entity,把原來在table[index]位置上的Entity賦值給新的 Entity的next,這樣插入結束。
總結:keyàhashcodeàhàindexà遍歷鏈表à插入
http://www.360doc.com/content/10/1214/22/573136_78200435.shtml
1九、Hash衝突怎麼辦?哪些解決散列衝突的方法?
一)哈希表簡介
非哈希表的特色:關鍵字在表中的位置和它之間不存在一個肯定的關係,查找的過程爲給定值一次和各個關鍵字進行比較,查找的效率取決於和給定值進行比較的次數。
哈希表的特色:關鍵字在表中位置和它之間存在一種肯定的關係。
哈希函數:通常狀況下,須要在關鍵字與它在表中的存儲位置之間創建一個函數關係,以f(key)做爲關鍵字爲key的記錄在表中的位置,一般稱這個函數f(key)爲哈希函數。
hash : 翻譯爲「散列」,就是把任意長度的輸入,經過散列算法,變成固定長度的輸出,該輸出就是散列值。
這種轉換是一種壓縮映射,散列值的空間一般遠小於輸入的空間,不一樣的輸入可能會散列成相同的輸出,因此不可能從散列值來惟一的肯定輸入值。
簡單的說就是一種將任意長度的消息壓縮到莫伊固定長度的消息摘要的函數。
hash衝突:(大師兄本身寫的哦)就是根據key即通過一個函數f(key)獲得的結果的做爲地址去存放當前的key value鍵值對(這個是hashmap的存值方式),可是卻發現算出來的地址上已經有人先來了。就是說這個地方要擠一擠啦。這就是所謂的hash衝突啦
二)哈希函數處理衝突的方法
其中,
爲關鍵字
的直接Hash地址,
爲Hash表的長度,
爲
每次再探測時的地址增量。根據的不一樣取法,有不一樣的稱呼。
線性探測再散列
二次探測再散列
僞隨機再散列 僞隨機數
(2)拉鍊法 拉鍊法又叫鏈地址法,適合處理衝突比較嚴重的狀況。基本思想是把全部關鍵字爲同義詞的記錄存儲在同一個 線性鏈表中。
(3)再哈希法
再哈希法又叫雙哈希法,有多個不一樣的Hash函數,當發生衝突時,使用第二個,第三個,....,等哈希函數
計算地址,直到無衝突。雖然不易發生彙集,可是增長了計算時間。
(4)創建公共溢出區
創建公共溢出區的基本思想是:假設哈希函數的值域是[1,m-1],則設向量HashTable[0...m-1]爲基本
表,每一個份量存放一個記錄,另外設向量OverTable[0...v]爲溢出表,全部關鍵字和基本表中關鍵字爲同義
詞的記錄,無論它們由哈希函數獲得的哈希地址是什麼,一旦發生衝突,都填入溢出表。
http://blog.csdn.net/qq_27093465/article/details/52269862
Java NIO非堵塞應用一般適用用在I/O讀寫等方面,咱們知道,系統運行的性能瓶頸一般在I/O讀寫,包括對端口和文件的操做上,過去,在打開一個I/O通道後,read()將一直等待在端口一邊讀取字節內容,若是沒有內容進來,read()也是傻傻的等,這會影響咱們程序繼續作其餘事情,那麼改進作法就是開設線程,讓線程去等待,可是這樣作也是至關耗費資源的。
Java NIO非堵塞技術實際是採起Reactor模式,或者說是Observer模式爲咱們監察I/O端口,若是有內容進來,會自動通知咱們,這樣,咱們就沒必要開啓多個線程死等,從外界看,實現了流暢的I/O讀寫,不堵塞了。
Java NIO出現不僅是一個技術性能的提升,你會發現網絡上處處在介紹它,由於它具備里程碑意義,從JDK1.4開始,Java開始提升性能相關的功能,從而使得Java在底層或者並行分佈式計算等操做上已經能夠和C或Perl等語言並駕齊驅。
若是你至今仍是在懷疑Java的性能,說明你的思想和觀念已經徹底落伍了,Java一兩年就應該用新的名詞來定義。從JDK1.5開始又要提供關於線程、併發等新性能的支持,Java應用在遊戲等適時領域方面的機會已經成熟,Java在穩定本身中間件地位後,開始蠶食傳統C的領域。
NIO主要原理和適用。
NIO 有一個主要的類Selector,這個相似一個觀察者,只要咱們把須要探知的socketchannel告訴Selector,咱們接着作別的事情,當有事件發生時,他會通知咱們,傳回一組SelectionKey,咱們讀取這些Key,就會得到咱們剛剛註冊過的socketchannel,而後,咱們從這個Channel中讀取數據,放心,包準可以讀到,接着咱們能夠處理這些數據。
Selector內部原理實際是在作一個對所註冊的channel的輪詢訪問,不斷的輪詢(目前就這一個算法),一旦輪詢到一個channel有所註冊的事情發生,好比數據來了,他就會站起來報告,交出一把鑰匙,讓咱們經過這把鑰匙來讀取這個channel的內容。
http://ifeve.com/overview/
2五、 String 編碼UTF-8 和GBK的區別?
UTF-8:Unicode TransformationFormat-8bit,容許含BOM,但一般不含BOM。是用以解決國際上字符的一種多字節編碼,它對英文使用8位(即一個字節),中文使用24爲(三個字節)來編碼。UTF-8包含全世界全部國家須要用到的字符,是國際編碼,通用性強。UTF-8編碼的文字能夠在各國支持UTF8字符集的瀏覽器上顯示。如,若是是UTF8編碼,則在外國人的英文IE上也能顯示中文,他們無需下載IE的中文語言支持包。
GBK是國家標準GB2312基礎上擴容後兼容GB2312的標準。GBK的文字編碼是用雙字節來表示的,即不論中、英文字符均使用雙字節來表示,爲了區分中文,將其最高位都設定成1。GBK包含所有中文字符,是國家編碼,通用性比UTF8差,不過UTF8佔用的數據庫比GBD大。
GBK、GB2312等與UTF8之間都必須經過Unicode編碼才能相互轉換:
GBK、GB2312--Unicode--UTF8
UTF8--Unicode--GBK、GB2312
對於一個網站、論壇來講,若是英文字符較多,則建議使用UTF-8節省空間。不過如今不少論壇的插件通常只支持GBK。
個編碼的區別詳細解釋
簡單來講,unicode,gbk和大五碼就是編碼的值,而utf-8,uft-16之類就是這個值的表現形式.而前面那三種編碼是一兼容的,同一個漢字,那三個碼值是徹底不同的.如"漢"的uncode值與gbk就是不同的,假設uncode爲a040,gbk爲b030,而uft-8碼,就是把那個值表現的形式.utf-8碼徹底只針對uncode來組織的,若是GBK要轉UTF-8必須先轉uncode碼,再轉utf-8就OK了.
2六、何時使用字節流、何時使用字符流?
字符流處理的單元爲2個字節的Unicode字符,分別操做字符、字符數組或字符串,而字節流處理單元爲1個字節,操做字節和字節數組。因此字符流是由Java虛擬機將字節轉化爲2個字節的Unicode字符爲單位的字符而成的,因此它對多國語言支持性比較好!若是是音頻文件、圖片、歌曲,就用字節流好點,若是是關係到中文(文本)的,用字符流好點.
全部文件的儲存是都是字節(byte)的儲存,在磁盤上保留的並非文件的字符而是先把字符編碼成字節,再儲存這些字節到磁盤。在讀取文件(特別是文本文件)時,也是一個字節一個字節地讀取以造成字節序列.
字節流可用於任何類型的對象,包括二進制對象,而字符流只能處理字符或者字符串; 2.
字節流提供了處理任何類型的IO操做的功能,但它不能直接處理Unicode字符,而字符流就能夠。
2七、遞歸讀取文件夾下的文件,代碼怎麼實現?http://www.360doc.com/content/10/0518/00/1121193_28143533.shtml
/**
* 遞歸讀取文件夾下的 全部文件
*
* @param testFileDir 文件名或目錄名
*/
private static void testLoopOutAllFileName(String testFileDir) {
if (testFileDir == null) {
//由於new File(null)會空指針異常,因此要判斷下
return;
}
File[] testFile = new File(testFileDir).listFiles();
if (testFile == null) {
return;
}
for (File file : testFile) {
if (file.isFile()) {
System.out.println(file.getName());
} else if (file.isDirectory()) {
System.out.println("-------this is a directory, and its files are as follows:-------");
testLoopOutAllFileName(file.getPath());
} else {
System.out.println("文件讀入有誤!");
}
}
}
2八、session和cookie的區別和聯繫,session的生命週期,多個服務部署時session管理。
兩者的定義:
當你在瀏覽網站的時候,WEB 服務器會先送一小小資料放在你的計算機上,Cookie 會幫你在網站上所打的文字或是一些選擇,都紀錄下來。當下次你再光臨同一個網站,WEB 服務器會先看看有沒有它上次留下的 Cookie 資料,有的話,就會依據 Cookie
裏的內容來判斷使用者,送出特定的網頁內容給你。 Cookie 的使用很廣泛,許多有提供我的化服務的網站,都是利用 Cookie來辨認使用者,以方便送出使用者量身定作的內容,像是 Web 接口的免費 email 網站,都要用到 Cookie。具體來講cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在服務器端保持狀態的方案。同時咱們也看到,因爲採用服務器端保持狀態的方案在客戶端也須要保存一個標識,因此session機制可能須要藉助於cookie機制來達到保存標識的目的,但實際上它還有其餘選擇。
cookie機制。正統的cookie分發是經過擴展HTTP協議來實現的,服務器經過在HTTP的響應頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie。然而純粹的客戶端腳本如JavaScript或者VBScript也能夠生成cookie。而cookie的使用是由瀏覽器按照必定的原則在後臺自動發送給服務器的。瀏覽器檢查全部存儲的cookie,若是某個cookie所聲明的做用範圍大於等於將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上發送給服務器。 cookie的內容主要包括:名字,值,過時時間,路徑和域。路徑與域一塊兒構成cookie的做用範圍。若不設置過時時間,則表示這個cookie的生命期爲瀏覽器會話期間,關閉瀏覽器窗口,cookie就消失。這種生命期爲瀏覽器會話期的cookie被稱爲會話cookie。會話cookie通常不存儲在硬盤上而是保存在內存裏,固然這種行爲並非規範規定的。若設置了過時時間,瀏覽器就會把cookie保存到硬盤上,關閉後再次打開瀏覽器,這些cookie仍然有效直到超過設定的過時時間。存儲在硬盤上的cookie能夠在不一樣的瀏覽器進程間共享,好比兩個IE窗口。而對於保存在內存裏的cookie,不一樣的瀏覽器有不一樣的處理方式
session機制。session機制是一種服務器端的機制,服務器使用一種相似於散列表的結構(也可能就是使用散列表)來保存信息。當程序須要爲某個客戶端的請求建立一個session時,服務器首先檢查這個客戶端的請求裏是否已包含了一個session標識(稱爲session id),若是已包含則說明之前已經爲此客戶端建立過session,服務器就按照session id把這個session檢索出來使用(檢索不到,會新建一個),若是客戶端請求不包含session id,則爲此客戶端建立一個session而且生成一個與此session相關聯的session id,session id的值應該是一個既不會重複,又不容易被找到規律以仿造的字符串,這個session id將被在本次響應中返回給客戶端保存。保存這個session id的方式能夠採用cookie,這樣在交互過程當中瀏覽器能夠自動的按照規則把這個標識發送給服務器。通常這個cookie的名字都是相似於SEEESIONID。但cookie能夠被人爲的禁止,則必須有其餘機制以便在cookie被禁止時仍然可以把session id傳遞迴服務器。常常被使用的一種技術叫作URL重寫,就是把session id直接附加在URL路徑的後面。還有一種技術叫作表單隱藏字段。就是服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時可以把session id傳遞迴服務器。好比: <form name="testform" action="/xxx"> < input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"> < input type="text"> < /form> 實際上這種技術能夠簡單的用對action應用URL重寫來代替。
cookie 和session 的區別:
一、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。
二、cookie不是很安全,別人能夠分析存放在本地的COOKIE並進行COOKIE欺騙 考慮到安全應當使用session。
三、session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能 考慮到減輕服務器性能方面,應當使用COOKIE。
四、單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。
五、因此我的建議: 將登錄信息等重要信息存放爲SESSION 其餘信息若是須要保留,能夠放在COOKIE中
2九、servlet的一些相關問題
一,什麼是Servlet?
Servlet是一個Java編寫的程序,此程序是基於Http協議的,在服務器端運行的(如tomcat),是按照Servlet規範編寫的一個Java類。
二,Servlet有什麼做用?主要是處理客戶端的請求並將其結果發送到客戶端。
三,Servlet的生命週期?Servlet的生命週期是由Servlet的容器來控制的,它能夠分爲3個階段;初始化,運行,銷燬。
初始化階段: 1,Servlet容器加載servlet類,把servlet類的.class文件中的數據讀到內存中。
2,而後Servlet容器建立一個ServletConfig對象。ServletConfig對象包含了Servlet的初始化配置信息。
3,Servlet容器建立一個servlet對象。
4,Servlet容器調用servlet對象的init方法進行初始化。
運行階段:
當servlet容器接收到一個請求時,servlet容器會針對這個請求建立servletRequest和servletResponse對象。而後調用service方法。並把這兩個參數傳遞給service方法。Service方法經過servletRequest對象得到請求的信息。並處理該請求。再經過servletResponse對象生成這個請求的響應結果。而後銷燬servletRequest和servletResponse對象。咱們無論這個請求是post提交的仍是get提交的,最終這個請求都會由service方法來處理。
銷燬階段:
當Web應用被終止時,servlet容器會先調用servlet對象的destrory方法,而後再銷燬servlet對象,同時也會銷燬與servlet對象相關聯的servletConfig對象。咱們能夠在destroy方法的實現中,釋放servlet所佔用的資源,如關閉數據庫鏈接,關閉文件輸入輸出流等。
在這裏該注意的地方:在servlet生命週期中,servlet的初始化和和銷燬階段只會發生一次,而service方法執行的次數則取決於servlet被客戶端訪問的次數
四,Servlet怎麼處理一個請求?
當用戶發送一個請求到某個Servlet的時候,Servlet容器會建立一個ServletRequst和ServletResponse對象。在ServletRequst對象中封裝了用戶的請求信息,而後Servlet容器把ServletRequst和ServletResponse對象傳給用戶所請求的Servlet,Servlet把處理好的結果寫在ServletResponse中,而後Servlet容器把響應結果傳給用戶。
五,Servlet與JSP有什麼區別?
1,jsp經編譯後就是servlet,也能夠說jsp等於servlet。
2,jsp更擅長頁面(表現)。servlet更擅長邏輯編輯。 (最核心的區別)。
3,在實際應用中採用Servlet來控制業務流程,而採用JSP來生成動態網頁.
在struts框架中,JSP位於MVC設計模式的視圖層,而Servlet位於控制層。
六,Servlet裏的cookie技術?
cookies是一種WEB服務器經過瀏覽器在訪問者的硬盤上存儲信息的手段,是由Netscape公司開發出來的。
1,Cookie有效期限未到時,Cookie能使用戶在不鍵入密碼和用戶名的狀況下進入曾經瀏覽過的一些站點。
2,Cookie能使站點跟蹤特定訪問者的訪問次數、最後訪問時間和訪問者進入站點的路徑。
七,Servlet裏的過濾器?
過濾器的主要做用
1,任何系統或網站都要判斷用戶是否登陸。
2,網絡聊天系統或論壇,功能是過濾非法文字
3,統一解決編碼
(2)怎麼建立一個過濾器:
1,生成一個普通的class類,實現Filter接口(javax.servlet.Filter;)。
2,重寫接口裏面的三個方法:init,doFilter,destroy。
3,而後在web.xml配置過濾器
八,Servlet裏的監聽器?
監聽器的做用:自動執行一些操做。
三種servlet監聽器:
對request的監聽。對session的監聽。對application的監聽。
怎麼建立一個session監聽器:
1,生成一個普通的class類,若是是對session的監聽,則實現HttpSessionListener。
2,而後重寫裏面的五個方法:Servlet是運行在Servlet容器中的,由Servlet容器來負責Servlet實例的查找、建立以及整個生命週期的管理,Servlet整個生命週期能夠分爲四個階段:類裝載及實例建立階段、實例初始化階段、服務階段以及實例銷燬階段。
類裝載及實例建立階段
默認狀況下,Servlet實例是在接受到第一個請求時進行建立而且之後的請求進行復用,若是有Servlet實例須要進行一些複雜的操做,須要在初始化時就完成,好比打開文件、初始化網絡鏈接等,能夠配置在服務器啓動時就建立實例,具體配置方法爲在聲明servlet標籤中添加<load-on-startup>1</load-on-startup>標籤。
初始化 init(ServletConfig config)一旦Servlet實例被建立,將會調用Servlet的inint方法,同時傳入ServletConfig實例,傳入Servlet的相關配置信息,init方法在整個Servlet生命週期中只會調用一次。
服務 services()爲了提升效率,Servlet規範要求一個Servlet實例必須可以同時服務於多個客戶端請求,即service()方法運行在多線程的環境下,Servlet開發者必須保證該方法的線程安全性。
銷燬 destory()當Servlet容器將決定結束某個Servlet時,將會調用destory()方法,在destory方法中進行資源釋放,一旦destory方法被調用,Servlet容器將不會再發送任何請求給這個實例,若Servlet容器需再次使用該Servlet,需從新再實例化該Servlet實例。
2、Servlet執行流程
web服務器接受到一個http請求後,web服務器會將請求移交給servlet容器,servlet容器首先對所請求的URL進行解析並根據web.xml 配置文件找到相應的處理servlet,同時將request、response對象傳遞給它,servlet經過request對象可知道客戶端的請求者、請求信息以及其餘的信息等,servlet在處理完請求後會把全部須要返回的信息放入response對象中並返回到客戶端,servlet一旦處理完請求,servlet容器就會刷新response對象,並把控制權從新返回給web服務器。
3、與其它技術的比較 v 其它服務相比servlet有如下的一些優勢:
一、運行速度上比CGI快,由於使用了多線程
二、servlet使用了標準的api,可被許多web服務支持
三、與系統無關性,一次編譯屢次使用