1.static關鍵字的含義,是否可以重寫私有方法或靜態(tài)方法,為什么?
1.static關鍵字:
簡單:static關鍵字表明一個成員變量或者成員方法可以在沒有所屬的類的實例變量的情況下被訪問。
詳細:通常來說,當創(chuàng)建類時,就是在描述那個類的對象的外觀與行為。除非用new創(chuàng)建那個對象,否則,實際上并未獲得任何對象。執(zhí)行new來創(chuàng)建對象的時候,數(shù)據(jù)存儲空間才被分配,其方法才供外界調用。有兩種情形用上述方法是無法解決的。一種情形是,只想為某特定域分配單一存儲空間,而不去考慮究竟要創(chuàng)建多少個對象,甚至根本不需要創(chuàng)建任何對象。另一種情形是,希望某個方法不與包含他的類的任何對象關聯(lián)在一起。也就是說,即使沒有創(chuàng)建對象,也能夠調用方法。簡單來說,static的主要目的就是創(chuàng)建獨立于具體對象的域變量與方法。
可見,static變量并不是所在類的某個具體對象所有,而是該類的所有對象所共有的,靜態(tài)變量既能被對象調用,也能直接拿類來調用。除此之外,靜態(tài)變量不能引用非靜態(tài)方法,原因正如前面描述靜態(tài)加載時機中說的那樣,加載靜態(tài)的時候,非靜態(tài)的變量、方法等還不存在,當然就無法引用了。但是,非靜態(tài)方法或類卻能正常引用靜態(tài)變量或方法。因為非靜態(tài)總是在靜態(tài)之后出現(xiàn)的。靜態(tài)方法和靜態(tài)變量一樣,屬于類所有,在類加載的同時執(zhí)行,不屬于某個具體的對象,所有對象均能調用。
2.不可以重寫私有方法,因為私有方法不能被子類訪問,所以無法重寫;
3.靜態(tài)方法不依賴類就可以訪問。這就是它的用途啊,沒有new對象可調用的方法。然而,重寫是依賴對象的。重寫父類的某一方法,而static不依賴類。
2.抽象類和接口有什么區(qū)別?
1.抽象類和接口都不能夠實例化,但可以定義抽象類和接口類型的引用。
2.一個類如果繼承了某個抽象類或者實現(xiàn)了某個接口都需要對其中的抽象方法全部進行實現(xiàn),否則該類仍然需要被聲明為抽象類。
3.接口比抽象類更加抽象,因為抽象類中可以定義構造器,可以有抽象方法和具體方法,而接口中不能定義構造器而且其中的方法全部都是抽象方法。
4.抽象類中的成員可以是private、默認、protected、public的,而接口中的成員全都是public的。
5.抽象類中可以定義成員變量,而接口中定義的成員變量實際上都是常量。
6.有抽象方法的類必須被聲明為抽象類,而抽象類未必要有抽象方法。
3.為什么java在實現(xiàn)equals必須要同時實現(xiàn)hashcode方法?
原文地址:why在重寫equals時還必須重寫hashcode方法 - 發(fā)表是最好的記憶 - 博客園
首先我們先來看下String類的源碼:可以發(fā)現(xiàn)String是重寫了Object類的equals方法的,并且也重寫了hashcode方法
1、如果兩個對象相同(即用equals比較返回true),那么它們的hashCode值一定要相同;
2、如果兩個對象的hashCode相同,它們并不一定相同(即用equals比較返回false)
自我的理解:
由于為了提高程序的效率才實現(xiàn)了hashcode方法,先進行hashcode的比較,如果不同,那沒就不必在進行equals的比較了,這樣就大大減少了equals比較的次數(shù),這對比需要比較的數(shù)量很大的效率提高是很明顯的,一個很好的例子就是在集合中的使用;
我們都知道java中的List集合是有序的,因此是可以重復的,而set集合是無序的,因此是不能重復的,那么怎么能保證不能被放入重復的元素呢,但靠equals方法一樣比較的話,如果原來集合中以后又10000個元素了,那么放入10001個元素,難道要將前面的所有元素都進行比較,看看是否有重復,歐碼噶的,這個效率可想而知,因此hashcode就應遇而生了,java就采用了hash表,利用哈希算法(也叫散列算法),就是將對象數(shù)據(jù)根據(jù)該對象的特征使用特定的算法將其定義到一個地址上,那么在后面定義進來的數(shù)據(jù)只要看對應的hashcode地址上是否有值,那么就用equals比較,如果沒有則直接插入,只要就大大減少了equals的使用次數(shù),執(zhí)行效率就大大提高了。
繼續(xù)上面的話題,為什么必須要重寫hashcode方法,其實簡單的說就是為了保證同一個對象,保證在equals相同的情況下hashcode值必定相同,如果重寫了equals而未重寫hashcode方法,可能就會出現(xiàn)兩個沒有關系的對象equals相同的(因為equal都是根據(jù)對象的特征進行重寫的),但hashcode確實不相同的。
4.請描述statement和preparedStatement的區(qū)別?
與Statement相比,①PreparedStatement接口代表預編譯的語句,它主要的優(yōu)勢在于可以減少SQL的編譯錯誤并增加SQL的安全性(減少SQL注射攻擊的可能性);②PreparedStatement中的SQL語句是可以帶參數(shù)的,避免了用字符串連接拼接SQL語句的麻煩和不安全;③當批量處理SQL或頻繁執(zhí)行相同的查詢時,PreparedStatement有明顯的性能上的優(yōu)勢,由于數(shù)據(jù)庫可以將編譯優(yōu)化后的SQL語句緩存起來,下次執(zhí)行相同結構的語句時就會很快(不用再次編譯和生成執(zhí)行計劃)
5.闡述ArrayList、Vector、LinkedList的存儲性能和特性。?
ArrayList 和Vector都是使用數(shù)組方式存儲數(shù)據(jù),此數(shù)組元素數(shù)大于實際存儲的數(shù)據(jù)以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數(shù)組元素移動等內存操作,所以索引數(shù)據(jù)快而插入數(shù)據(jù)慢,Vector中的方法由于添加了synchronized修飾,因此Vector是線程安全的容器,但性能上較ArrayList差,因此已經(jīng)是Java中的遺留容器。LinkedList使用雙向鏈表實現(xiàn)存儲(將內存中零散的內存單元通過附加的引用關聯(lián)起來,形成一個可以按序號索引的線性結構,這種鏈式存儲方式與數(shù)組的連續(xù)存儲方式相比,內存的利用率更高),按序號索引數(shù)據(jù)需要進行前向或后向遍歷,但是插入數(shù)據(jù)時只需要記錄本項的前后項即可,所以插入速度較快。Vector屬于遺留容器(Java早期的版本中提供的容器,除此之外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經(jīng)不推薦使用,但是由于ArrayList和LinkedListed都是非線程安全的,如果遇到多個線程操作同一個容器的場景,則可以通過工具類Collections中的synchronizedList方法將其轉換成線程安全的容器后再使用(這是對裝潢模式的應用,將已有對象傳入另一個類的構造器中創(chuàng)建新的對象來增強實現(xiàn))。
注:ArrayList和LinkedList的區(qū)別
ArrayList和LinkedList的大致區(qū)別如下:1.ArrayList是實現(xiàn)了基于動態(tài)數(shù)組的數(shù)據(jù)結構,LinkedList基于鏈表的數(shù)據(jù)結構。?2.對于隨機訪問get和set,ArrayList覺得優(yōu)于LinkedList,因為LinkedList要移動指針。?3.對于新增和刪除操作add和remove,LinedList比較占優(yōu)勢,因為ArrayList要移動數(shù)據(jù)。
上代碼:
當我們在集合中裝5萬條數(shù)據(jù),測試運行結果如下:

顯然我們可以看出ArrayList更適合讀取數(shù)據(jù),linkedList更多的時候添加或刪除數(shù)據(jù)。
ArrayList內部是使用可増長數(shù)組實現(xiàn)的,所以是用get和set方法是花費常數(shù)時間的,但是如果插入元素和刪除元素,除非插入和刪除的位置都在表末尾,否則代碼開銷會很大,因為里面需要數(shù)組的移動。LinkedList是使用雙鏈表實現(xiàn)的,所以get會非常消耗資源,除非位置離頭部很近。但是插入和刪除元素花費常數(shù)時間。
6.闡述ArrayList和數(shù)組的區(qū)別
ArrayList可以算是Array的加強版,(對array有所取舍的加強)。?
存儲內容比較:
? ? Array數(shù)組可以包含基本類型和對象類型,
? ? ArrayList卻只能包含對象類型。
但是需要注意的是:Array數(shù)組在存放的時候一定是同種類型的元素。ArrayList就不一定了,因為ArrayList可以存儲Object。
空間大小比較:
? ? ? ? ? 它的空間大小是固定的,空間不夠時也不能再次申請,所以需要事前確定合適的空間大小。
? ? ? ? ? ArrayList的空間是動態(tài)增長的,如果空間不夠,它會創(chuàng)建一個空間比原空間大一倍的新數(shù)組,然后將所有元素復制到新數(shù)組中,接著拋棄舊數(shù)組。而且,每次添加新的元素的時候都會檢查內部數(shù)組的空間是否足夠。(比較麻煩的地方)。
方法上的比較:
ArrayList作為Array的增強版,當然是在方法上比Array更多樣化,比如添加全部addAll()、刪除全部removeAll()、返回迭代器iterator()等。
適用場景:
如果想要保存一些在整個程序運行期間都會存在而且不變的數(shù)據(jù),我們可以將它們放進一個全局數(shù)組里,但是如果我們單純只是想要以數(shù)組的形式保存數(shù)據(jù),而不對數(shù)據(jù)進行增加等操作,只是方便我們進行查找的話,那么,我們就選擇ArrayList。而且還有一個地方是必須知道的,就是如果我們需要對元素進行頻繁的移動或刪除,或者是處理的是超大量的數(shù)據(jù),那么,使用ArrayList就真的不是一個好的選擇,因為它的效率很低,使用數(shù)組進行這樣的動作就很麻煩,那么,我們可以考慮選擇LinkedList。
7.final與finally的區(qū)別,為什么內部類訪問的外部變量需要final來修飾
a.final是一個關鍵字,修飾變量那么變量初始化之后就不可改變,修飾類則不可以繼承,修飾方法,那么方法就不可以被重寫,而finally與try,catch語句塊一起使用,始終執(zhí)行。
b.當使用成員內部類時,它可以直接訪問外類的變量(public、默認、private權限修飾符修飾的),不會出現(xiàn)問題;而在使用它訪問局部變量時,Java8以前的版本會報錯:從內部類中訪問本地變量a,需要被聲明為最終類型。這時候你在變量前面加個狀態(tài)修飾符final,就能正常運行了。
我們知道,當方法調用完以后,方法就會被當作垃圾而被回收,可是局部內部類創(chuàng)建的對象在堆內存,它并不會立即消失,相反,它仍存在,并且仍在調用局部變量,這顯然與局部變量已被銷毀矛盾。這時候Java語言提供了一個巧妙的解決辦法,用狀態(tài)修飾符final修飾該變量,從而該變量成了常量,解決了這個問題。
8.fileReader和bufferedReader的執(zhí)行速度
a.首先摘錄一段在百度里面搜索到的關于緩沖區(qū)的作用以及效果描述:這么說吧,緩沖區(qū)的主要目的是加速的, 內存的緩沖區(qū)讀寫速度要遠遠快于硬盤,如果讀一點從硬盤文件取一點,或者有一點內容就直接寫到硬盤文件一點,速度會比較慢
舉一個例子,只是為了好理解,實際情況并不完全一樣,我要從某學生宿舍(相當于硬盤)開車接送98個學生到公司(相當于CPU)來進行面試.接一個學生過來,面試完送一個回去,再接另一個過來,速度會很慢
我在公司找兩個10人房間(相當于緩沖區(qū)),一次接10個學生在等待面試房間(read緩存)里,面試一個,送進等待送回房間(write緩存),等待面試房間空了,自動再接10個.
同樣的,等待送回房間滿10人后自動一起送回去.......這樣是不是快得多?
b.當BufferedReader在讀取文本文件時,會先盡量從文件中讀入字符數(shù)據(jù)并置入緩沖區(qū),而之后若使用read()方法,會先從緩沖區(qū)中進行讀取,如果緩沖區(qū)數(shù)據(jù)不足,才會再從文件中讀取。
FileReader : 字符流
BufferedReader : 也是字符流,但是在BufferedReader可以先把數(shù)據(jù)放到一個緩存區(qū)里,然后在進行處理,而且在BufferedReader 里有一個readLine()方法。
9.請描述一下ArrayBlockingQueue和LinkedBlockingQueue的區(qū)別和聯(lián)系
詳細的解釋摘自ArrayBlockingQueue與LinkedBlockingQueue - 簡書
隊列中鎖的實現(xiàn)不同
ArrayBlockingQueue實現(xiàn)的隊列中的鎖是沒有分離的,即生產(chǎn)和消費用的是同一個鎖;
LinkedBlockingQueue實現(xiàn)的隊列中的鎖是分離的,即生產(chǎn)用的是putLock,消費是takeLock
在生產(chǎn)或消費時操作不同
ArrayBlockingQueue實現(xiàn)的隊列中在生產(chǎn)和消費的時候,是直接將枚舉對象插入或移除的;
LinkedBlockingQueue實現(xiàn)的隊列中在生產(chǎn)和消費的時候,需要把枚舉對象轉換為Node進行插入或移除,會影響性能
隊列大小初始化方式不同
ArrayBlockingQueue實現(xiàn)的隊列中必須指定隊列的大?。?/p>
LinkedBlockingQueue實現(xiàn)的隊列中可以不指定隊列的大小,但是默認是Integer.MAX_VALUE
4.ArrayBlockingQueue采用的是數(shù)組,LinkedBlockingQueue采用的是單向鏈表
put? take 實現(xiàn)原理:
里面有兩個顯式條件隊列Condition? 由ReentrantLock? newConditon()得到
一個為notFull:沒有滿
另一個為notEmpty:不是空的
final Object[] items;緩沖隊列
當put一個元素時先判斷是不是滿的如果是九調用notFull.await()阻塞到不是滿的
添加成功之后調用notEmpty.singnal();通知消費者有產(chǎn)品可消費了,解除消費者阻塞
當take一個元素時先判斷是不是空的如果是空的先調用notEmpty.await()阻塞,如果取得了元素(從items里面移除),就調用notFull.singnal()喚醒并阻塞的生產(chǎn)者。
10.你描述一下使用過的java.util.concurrent包下的類 以及使用場景
鏈接一下:java 并發(fā) concurrent 包 - CSDN博客
11.SpringMVC中如何實現(xiàn)參數(shù)的解析
鏈接:SpringMVC之分析請求參數(shù)的解析過程(一) - 程序園
12.springMVC中IOC和AOP的理解
鏈接:Spring面試,IoC和AOP的理解 - Sandy_wu
13.session和cookie之間的區(qū)別和聯(lián)系
1. 由于HTTP協(xié)議是無狀態(tài)的協(xié)議,所以服務端需要記錄用戶的狀態(tài)時,就需要用某種機制來識具體的用戶,這個機制就是Session.典型的場景比如購物車,當你點擊下單按鈕時,由于HTTP協(xié)議無狀態(tài),所以并不知道是哪個用戶操作的,所以服務端要為特定的用戶創(chuàng)建了特定的Session,用用于標識這個用戶,并且跟蹤用戶,這樣才知道購物車里面有幾本書。這個Session是保存在服務端的,有一個唯一標識。在服務端保存Session的方法很多,內存、數(shù)據(jù)庫、文件都有。集群的時候也要考慮Session的轉移,在大型的網(wǎng)站,一般會有專門的Session服務器集群,用來保存用戶會話,這個時候 Session 信息都是放在內存的,使用一些緩存服務比如Memcached之類的來放 Session。
2. 思考一下服務端如何識別特定的客戶?這個時候Cookie就登場了。每次HTTP請求的時候,客戶端都會發(fā)送相應的Cookie信息到服務端。實際上大多數(shù)的應用都是用 Cookie 來實現(xiàn)Session跟蹤的,第一次創(chuàng)建Session的時候,服務端會在HTTP協(xié)議中告訴客戶端,需要在 Cookie 里面記錄一個Session ID,以后每次請求把這個會話ID發(fā)送到服務器,我就知道你是誰了。有人問,如果客戶端的瀏覽器禁用了 Cookie 怎么辦?一般這種情況下,會使用一種叫做URL重寫的技術來進行會話跟蹤,即每次HTTP交互,URL后面都會被附加上一個諸如 sid=xxxxx 這樣的參數(shù),服務端據(jù)此來識別用戶。
3. Cookie其實還可以用在一些方便用戶的場景下,設想你某次登陸過一個網(wǎng)站,下次登錄的時候不想再次輸入賬號了,怎么辦?這個信息可以寫到Cookie里面,訪問網(wǎng)站的時候,網(wǎng)站頁面的腳本可以讀取這個信息,就自動幫你把用戶名給填了,能夠方便一下用戶。這也是Cookie名稱的由來,給用戶的一點甜頭。
所以,總結一下:
Session是在服務端保存的一個數(shù)據(jù)結構,用來跟蹤用戶的狀態(tài),這個數(shù)據(jù)可以保存在集群、數(shù)據(jù)庫、文件中;
Cookie是客戶端保存用戶信息的一種機制,用來記錄用戶的一些信息,也是實現(xiàn)Session的一種方式。
14.java的包裝類和基本數(shù)據(jù)類型之間的區(qū)別
1、包裝類是對象,擁有方法和字段,對象的調用都是通過引用對象的地址,基本類型不是?
2、包裝類型是引用的傳遞,基本類型是值的傳遞?
3、聲明方式不同,基本數(shù)據(jù)類型不需要new關鍵字,而包裝類型需要new在堆內存中進行new來分配內存空間?
4、存儲位置不同,基本數(shù)據(jù)類型直接將值保存在值棧中,而包裝類型是把對象放在堆中,然后通過對象的引用來調用他們?
5、初始值不同,eg: int的初始值為 0 、 boolean的初始值為false 而包裝類型的初始值為null?
6、使用方式不同,基本數(shù)據(jù)類型直接賦值使用就好 ,而包裝類型是在集合如 coolection Map時會使用
15.多線程中的wait和sleep的區(qū)別
?sleep()和wait()方法的最大區(qū)別是:
sleep()睡眠時,保持對象鎖,仍然占有;
而wait()睡眠時,釋放對象鎖。
16.linux中查看服務器日志的命令
tail?-f?-n?5?/var/log/syslog
這個是輸出最近5行的日志命令
17.事務的四大特性
⑴ 原子性(Atomicity)
原子性是指事務包含的所有操作要么全部成功,要么全部失敗回滾,這和前面兩篇博客介紹事務的功能是一樣的概念,因此事務的操作如果成功就必須要完全應用到數(shù)據(jù)庫,如果操作失敗則不能對數(shù)據(jù)庫有任何影響。
⑵ 一致性(Consistency)
一致性是指事務必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另一個一致性狀態(tài),也就是說一個事務執(zhí)行之前和執(zhí)行之后都必須處于一致性狀態(tài)。
拿轉賬來說,假設用戶A和用戶B兩者的錢加起來一共是5000,那么不管A和B之間如何轉賬,轉幾次賬,事務結束后兩個用戶的錢相加起來應該還得是5000,這就是事務的一致性。
⑶ 隔離性(Isolation)
隔離性是當多個用戶并發(fā)訪問數(shù)據(jù)庫時,比如操作同一張表時,數(shù)據(jù)庫為每一個用戶開啟的事務,不能被其他事務的操作所干擾,多個并發(fā)事務之間要相互隔離。
即要達到這么一種效果:對于任意兩個并發(fā)的事務T1和T2,在事務T1看來,T2要么在T1開始之前就已經(jīng)結束,要么在T1結束之后才開始,這樣每個事務都感覺不到有其他事務在并發(fā)地執(zhí)行。
關于事務的隔離性數(shù)據(jù)庫提供了多種隔離級別,稍后會介紹到。
⑷ 持久性(Durability)
持久性是指一個事務一旦被提交了,那么對數(shù)據(jù)庫中的數(shù)據(jù)的改變就是永久性的,即便是在數(shù)據(jù)庫系統(tǒng)遇到故障的情況下也不會丟失提交事務的操作。
18.linux 查看并殺死進程
ps -ef|grep java
kill xxx
killall -9 NAME
19.redis可以存放的數(shù)據(jù)類型都有?
String----------字符串
Hash------------字典
List-------------列表
Set--------------集合
Sorted Set------有序集合
詳情摘自:Redis中的五種數(shù)據(jù)類型使用場景 - 簡書
關于redis常用的命令使用摘自:Redis常用數(shù)據(jù)類型介紹、使用場景及其操作命令 - lizhenghn - 博客園
20.java虛擬機中的內存模型?

關于詳細的模型介紹摘自:jvm的內存分配總結 - 簡書
21.String str2 = new String("ABC")?創(chuàng)建了幾個對象,他和String str2 = "ABC"的區(qū)別?
詳情摘自java中String new和直接賦值的區(qū)別 - CSDN博客
22.java集合關系,以及l(fā)ist,set,map關系區(qū)別

區(qū)別摘自:Java 面試高頻提問知識點之:Set、List 和 Map 的區(qū)別 - Java開發(fā)社區(qū) | CTOLib碼庫
23.hashMap和hashTable的區(qū)別?
1.hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
2.hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。
3.hashMap允許空鍵值,而hashTable不允許。
24.JVM中的永久代中會發(fā)生垃圾回收嗎?
垃圾回收不會發(fā)生在永久代,如果永久代滿了或者是超過了臨界值,會觸發(fā)完全垃圾回收。如果你仔細查看垃圾收集器的輸出信息,就會發(fā)現(xiàn)永久代也是被回收的。這就是為什么正確的永久代大小對避免full?gc是非常重要的原因。
25.在java中,對象什么時候可以被垃圾回收?
當對象對當前使用這個對象的應用程序變得不可觸及的時候,這個對象就可以被回收了。
26.java中垃圾回收有什么目的?什么時候進行垃圾回收?
垃圾回收是在內存總存在沒有引用的對象或者超過作用域的對象時進行。
垃圾回收的目的就是識別并且丟棄應用不再使用的對象來釋放和重用資源。
27.hashMap的工作原理是什么?
Java總的hashMap是以鍵值對的形式來存儲元素的。HashMap需要一個hash函數(shù),他使用hashCode()和equals()方法來想集合或者集合添加和檢索元素。當調用put()方法的時候,HashMap會計算key的hash值,然后把鍵值對存儲在集合中合適的索引上。如果key已經(jīng)存在了,value就會被更新成新值。HashMap的一些重要的特性是他的容量,負載銀子河擴容極限。