JAVA面試題彙總

一、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>
(3),紅黑樹
//紅黑樹
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>
摘自http://www.2cto.com/kf/201606/515215.html
http://www.cnblogs.com/ITtangtang/p/3948406.html
三、說說你知道的幾個Java集合類:list、set、queue、map實現類。
在編程中,經常須要集中存放多個數據。從傳統意義上講,數組是咱們的一個很好的選擇,前提是咱們事先已經明確知道咱們將要保存的對象的數量。一旦在數組初始化時指定了這個數組長度,這個數組長度就是不可變的,若是咱們須要保存一個能夠動態增加的數據(在編譯時沒法肯定具體的數量),java的集合類就是一個很好的設計方案了。
集合類主要負責保存、盛裝其餘數據,所以集合類也被稱爲容器類。因此的集合類都位於java.util包下,後來爲了處理多線程環境下的併發安全問題,java5還在java.util.concurrent包下提供了一些多線程支持的集合類。
Java容器類類庫的用途是"保存對象",並將其劃分爲兩個不一樣的概念:
1) Collection
一組"對立"的元素,一般這些元素都服從某種規則
   1.1) List必須保持元素特定的順序
   1.2) Set不能有重複元素
   1.3) Queue保持一個隊列(先進先出)的順序
2) Map
一組成對的"鍵值對"對象
Collection和Map的區別在於容器中每一個位置保存的元素個數:
1) Collection 每一個位置只能保存一個元素(對象)
2) Map保存的是"鍵值對",就像一個小型數據庫。咱們可1. Interface Iterable
迭代器接口,這是Collection類的父接口。實現這個Iterable接口的對象容許使用foreach進行遍歷,也就是說,全部的Collection集合對象都具備"foreach可遍歷性"。這個Iterable接口只
有一個方法: iterator()。它返回一個表明當前集合對象的泛型<T>迭代器,用於以後的遍歷操做
1.1 Collection
Collection是最基本的集合接口,一個Collection表明一組Object的集合,這些Object被稱做Collection的元素。Collection是一個接口,用以提供規範定義,不能被實例化使用
    1) Set
    Set集合相似於一個罐子,"丟進"Set集合裏的多個對象之間沒有明顯的順序。Set繼承自Collection接口,不能包含有重複元素(記住,這是整個Set類層次的共有屬性)。
    Set判斷兩個對象相同不是使用"=="運算符,而是根據equals方法。也就是說,咱們在加入一個新元素的時候,若是這個新元素對象和Set中已有對象進行注意equals比較都返回false,  
   則Set就會接受這個新元素對象,不然拒絕。
    由於Set的這個制約,在使用Set集合的時候,應該注意兩點:1) 爲Set集合裏的元素的實現類實現一個有效的equals(Object)方法、2) 對Set的構造函數,傳入的Collection參數不能包
  含重複的元素
        1.1) HashSet
        HashSet是Set接口的典型實現,HashSet使用HASH算法來存儲集合中的元素,所以具備良好的存取和查找性能。當向HashSet集合中存入一個元素時,HashSet會調用該對象的
     hashCode()方法來獲得該對象的hashCode值,而後根據該HashCode值決定該對象在HashSet中的存儲位置。
        值得主要的是,HashSet集合判斷兩個元素相等的標準是兩個對象經過equals()方法比較相等,而且兩個對象的hashCode()方法的返回值相等
            1.1.1) LinkedHashSet
            LinkedHashSet集合也是根據元素的hashCode值來決定元素的存儲位置,但和HashSet不一樣的是,它同時使用鏈表維護元素的次序,這樣使得元素看起來是以插入的順序保存的。
       當遍歷LinkedHashSet集合裏的元素時,LinkedHashSet將會按元素的添加順序來訪問集合裏的元素。
            LinkedHashSet須要維護元素的插入順序,所以性能略低於HashSet的性能,但在迭代訪問Set裏的所有元素時(遍歷)將有很好的性能(鏈表很適合進行遍歷)
        1.2) SortedSet   
        此接口主要用於排序操做,即實現此接口的子類都屬於排序的子類
            1.2.1) TreeSet
            TreeSet是SortedSet接口的實現類,TreeSet能夠確保集合元素處於排序狀態
        1.3) EnumSet
        EnumSet是一個專門爲枚舉類設計的集合類,EnumSet中全部元素都必須是指定枚舉類型的枚舉值,該枚舉類型在建立EnumSet時顯式、或隱式地指定。EnumSet的集合元素也是有序的,
     它們以枚舉值在Enum類內的定義順序來決定集合元素的順序
    2) List
    List集合表明一個元素有序、可重複的集合,集合中每一個元素都有其對應的順序索引。List集合容許加入重複元素,由於它能夠經過索引來訪問指定位置的集合元素。List集合默認按元素
   的添加順序設置元素的索引
        2.1) ArrayList
        ArrayList是基於數組實現的List類,它封裝了一個動態的增加的、容許再分配的Object[]數組。
        2.2) Vector
        Vector和ArrayList在用法上幾乎徹底相同,但因爲Vector是一個古老的集合,因此Vector提供了一些方法名很長的方法,但隨着JDK1.2之後,java提供了系統的集合框架,就將
     Vector改成實現List接口,統一納入集合框架體系中
            2.2.1) Stack
            Stack是Vector提供的一個子類,用於模擬"棧"這種數據結構(LIFO後進先出)
        2.3) LinkedList
        implements List<E>, Deque<E>。實現List接口,能對它進行隊列操做,便可以根據索引來隨機訪問集合中的元素。同時它還實現Deque接口,即能將LinkedList看成雙端隊列
     使用。天然也能夠被看成"棧來使用"
    3) Queue
    Queue用於模擬"隊列"這種數據結構(先進先出 FIFO)。隊列的頭部保存着隊列中存放時間最長的元素,隊列的尾部保存着隊列中存放時間最短的元素。新元素插入(offer)到隊列的尾部,
   訪問元素(poll)操做會返回隊列頭部的元素,隊列不容許隨機訪問隊列中的元素。結合生活中常見的排隊就會很好理解這個概念
        3.1) PriorityQueue
        PriorityQueue並非一個比較標準的隊列實現,PriorityQueue保存隊列元素的順序並非按照加入隊列的順序,而是按照隊列元素的大小進行從新排序,這點從它的類名也能夠
     看出來
        3.2) Deque
        Deque接口表明一個"雙端隊列",雙端隊列能夠同時從兩端來添加、刪除元素,所以Deque的實現類既能夠當成隊列使用、也能夠當成棧使用
            3.2.1) ArrayDeque
            是一個基於數組的雙端隊列,和ArrayList相似,它們的底層都採用一個動態的、可重分配的Object[]數組來存儲集合元素,當集合元素超出該數組的容量時,系統會在底層重
       新分配一個Object[]數組來存儲集合元素
            3.2.2) LinkedList
1.2 Map
Map用於保存具備"映射關係"的數據,所以Map集合裏保存着兩組值,一組值用於保存Map裏的key,另一組值用於保存Map裏的value。key和value均可以是任何引用類型的數據。Map的key不允
許重複,即同一個Map對象的任何兩個key經過equals方法比較結果老是返回false。
關於Map,咱們要從代碼複用的角度去理解,java是先實現了Map,而後經過包裝了一個全部value都爲null的Map就實現了Set集合
Map的這些實現類和子接口中key集的存儲形式和Set集合徹底相同(即key不能重複)
Map的這些實現類和子接口中value集的存儲形式和List很是相似(即value能夠重複、根據索引來查找)
    1) HashMap
    和HashSet集合不能保證元素的順序同樣,HashMap也不能保證key-value對的順序。而且相似於HashSet判斷兩個key是否相等的標準也是: 兩個key經過equals()方法比較返回true、
   同時兩個key的hashCode值也必須相等
        1.1) LinkedHashMap
        LinkedHashMap也使用雙向鏈表來維護key-value對的次序,該鏈表負責維護Map的迭代順序,與key-value對的插入順序一致(注意和TreeMap對全部的key-value進行排序進行區
分)
    2) Hashtable
    是一個古老的Map實現類
        2.1) Properties
        Properties對象在處理屬性文件時特別方便(windows平臺上的.ini文件),Properties類能夠把Map對象和屬性文件關聯起來,從而能夠把Map對象中的key-value對寫入到屬性文
     件中,也能夠把屬性文件中的"屬性名-屬性值"加載到Map對象中
    3) SortedMap
    正如Set接口派生出SortedSet子接口,SortedSet接口有一個TreeSet實現類同樣,Map接口也派生出一個SortedMap子接口,SortedMap接口也有一個TreeMap實現類
        3.1) TreeMap
        TreeMap就是一個紅黑樹數據結構,每一個key-value對即做爲紅黑樹的一個節點。TreeMap存儲key-value對(節點)時,須要根據key對節點進行排序。TreeMap能夠保證全部的
     key-value對處於有序狀態。一樣,TreeMap也有兩種排序方式: 天然排序、定製排序
    4) WeakHashMap
    WeakHashMap與HashMap的用法基本類似。區別在於,HashMap的key保留了對實際對象的"強引用",這意味着只要該HashMap對象不被銷燬,該HashMap所引用的對象就不會被垃圾回收。
  但WeakHashMap的key只保留了對實際對象的弱引用,這意味着若是WeakHashMap對象的key所引用的對象沒有被其餘強引用變量所引用,則這些key所引用的對象可能被垃圾回收,當垃
  圾回收了該key所對應的實際對象以後,WeakHashMap也可能自動刪除這些key所對應的key-value對
    5) IdentityHashMap
    IdentityHashMap的實現機制與HashMap基本類似,在IdentityHashMap中,當且僅當兩個key嚴格相等(key1 == key2)時,IdentityHashMap才認爲兩個key相等
    6) EnumMap
    EnumMap是一個與枚舉類一塊兒使用的Map實現,EnumMap中的全部key都必須是單個枚舉類的枚舉值。建立EnumMap時必須顯式或隱式指定它對應的枚舉類。EnumMap根據key的天然順序
  (即枚舉值在枚舉類中的定義順序)以經過"鍵"找到該鍵對應的"值"
http://www.cnblogs.com/LittleHann/p/3690187.html
四、描述一下ArrayList和LinkedList各自實現和區別
ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。

對於隨機訪問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的區別。

Class的裝載分了三個階段,loading,linking和initializing,分別定義在The Java Language Specification的12.2,12.3和12.4。 Class.forName(className) 其實是調用Class.forName(className, true,  this.getClass().getClassLoader())。注意第二個參數,是指Class被loading後是否是必須被初始化。 ClassLoader.loadClass(className)實際上調用的是ClassLoader.loadClass(name, false),第二個參數指出Class是否被link。
區別就出來了。Class.forName(className)裝載的class已經被初始化,而ClassLoader.loadClass(className)裝載的class尚未被link。 通常狀況下,這兩個方法效果同樣,都能裝載Class。但若是程序依賴於Class是否被初始化,就必須用Class.forName(name)了。 例 如,在JDBC編程中,常看到這樣的用法,Class.forName("com.mysql.jdbc.Driver"),若是換成了 getClass().getClassLoader().loadClass("com.mysql.jdbc.Driver"),就不行。
原來,Driver在static塊中會註冊本身到java.sql.DriverManager。而static塊就是在Class的初始化中被執行。因此這個地方就只能用Class.forName(className)。
http://www.th7.cn/Program/java/201610/997137.shtml
七、Java七、Java8的新特性
http://blog.csdn.net/xuanjiewu/article/details/50731358
http://blog.csdn.net/qq_30641447/article/details/49853067
八、Java數組和鏈表兩種結構的操做效率,在哪些狀況下(從開頭開始,從結尾開始,從中間開始),哪些操做(插入,查找,刪除)的效率高。

首先這個問題,沒有固定答案,全看我的理解,畢竟這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地址,爲Hash表的長度,

    每次再探測時的地址增量。根據的不一樣取法,有不一樣的稱呼。

    線性探測再散列    

    二次探測再散列    

    僞隨機再散列       僞隨機數

(2)拉鍊法  拉鍊法又叫鏈地址法,適合處理衝突比較嚴重的狀況。基本思想是把全部關鍵字爲同義詞的記錄存儲在同一個 線性鏈表中。

(3)再哈希法

    再哈希法又叫雙哈希法,有多個不一樣的Hash函數,當發生衝突時,使用第二個,第三個,....,等哈希函數

    計算地址,直到無衝突。雖然不易發生彙集,可是增長了計算時間。

(4)創建公共溢出區

    創建公共溢出區的基本思想是:假設哈希函數的值域是[1,m-1],則設向量HashTable[0...m-1]爲基本

    表,每一個份量存放一個記錄,另外設向量OverTable[0...v]爲溢出表,全部關鍵字和基本表中關鍵字爲同義

    詞的記錄,無論它們由哈希函數獲得的哈希地址是什麼,一旦發生衝突,都填入溢出表。

http://blog.csdn.net/qq_27093465/article/details/52269862

 20、 HashMap衝突很厲害,最差性能,你會怎麼解決?
從O(n)提高到log(n)咯,用二叉排序樹的思路說了一通。
2一、rehash
http://blog.csdn.net/qq_27093465/article/details/52270519
rehash是在hash table的大小不能知足需求,形成過多hash碰撞後須要進行的擴容hash table的操做,其實一般的作法確實是創建一個額外的hash table,將原來的hash table中的數據在新的數據中進行從新輸入,從而生成新的hash表。
2二、hashCode() 與 equals() 生成算法、方法怎麼重寫 
http://blog.sina.com.cn/s/blog_5da93c8f0101djjr.html
2三、講講IO裏面的常見類,字節流、字符流、接口、實現類、方法阻塞。
http://www.cnblogs.com/oubo/archive/2012/01/06/2394638.html
2四、講講NIO

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服務支持

三、與系統無關性,一次編譯屢次使用

相關文章
相關標籤/搜索