JAVA基礎
- HashMap原理?為什么使用數(shù)組+鏈表?可以用ArrayList或LinkedList代替數(shù)組嗎?HashMap為什么要進行擴容,擴容后原來的元素怎么進行處理?JDK8為什么在鏈表長度大于8時改用紅黑樹?為什么說HashMap是線程不安全的?
HashMap使用Entry數(shù)組存儲鍵值對,每一個鍵值對是一個Entry實體,Entry是一個單向鏈表結構,所以HashMap是使用數(shù)組加鏈表實現(xiàn)的。
根據(jù)key的hash值對數(shù)組長度取模運算得到元素在數(shù)組的下標,當出現(xiàn)hash值一樣的情況時,就在數(shù)組對應下標位置形成一條鏈表。
可以使用AarrayList或LinkedList代替數(shù)組。
HashMap默認數(shù)組長度是16,當元素越來越多的時候,碰撞的幾率越來越高,為了提高查詢效率,對數(shù)組進行擴容。擴容后原來的元素要重新計算在數(shù)組中的新位置并放入。
因為紅黑樹的平均查找長度是log(n),長度為8的時候,平均查找長度為3,如果繼續(xù)使用鏈表,平均查找長度為8/2=4,這才有轉(zhuǎn)換為樹的必要。
在多線程的時候,put的時候可能導致數(shù)據(jù)不一致,get操作可能因為resize而引起死循環(huán)。
- ==和equals的區(qū)別?如果兩個對象相等,hashcode相同么?兩個對象的hashcode相同,兩個對象一定相等么,為什么?
"==" 用于基本數(shù)據(jù)類型,是直接比較存儲的值是否相等;如果用于引用類型的變量,比較的是所指向變量的地址。equals不能用于基本數(shù)據(jù)類型,euqals繼承自Object,如果沒有進行重寫,比較的是變量所指向的地址,如果進行了重寫,根據(jù)重寫內(nèi)容進行比較。
兩個對象相等,它們的hashcode一定相同。hashcode相同,兩個對象不一定相等,哈希沖突。
- static變量和實例變量有什么區(qū)別?static方法可以使用this,super等關鍵字嗎?
static變量在類被虛擬機載入的時候就會進行初始化,存在于靜態(tài)方法區(qū),生命周期隨類加載而加載,隨類消失而消失。
實例變量在對象創(chuàng)建后通過對象調(diào)用,存儲于堆內(nèi)存種,隨著類的消失而消失。
static方法不能使用this,super關鍵字,因為靜態(tài)創(chuàng)建早于對象。
- 基本數(shù)據(jù)類型?自動裝箱是在干什么?String是基本數(shù)據(jù)類型么?String值在初始化還能修改么?
自動裝箱是將基本數(shù)據(jù)類型和對應的包裝類型做一個轉(zhuǎn)化。
String不是基本數(shù)據(jù)類型,是引用類型。String是final修飾的,值在初始化后不能進行修改。
- 值傳遞和引用傳遞
值傳遞就是在方法調(diào)用的時候,實參是將自己的一份拷貝賦給形參,在方法內(nèi),對該參數(shù)值的修改不影響原來實參。
引用傳遞是在方法調(diào)用的時候,實參將自己的地址傳遞給形參,此時方法內(nèi)對該參數(shù)值的改變,就是對該實參的實際操作。
- 異常處理的時候,finally代碼塊的主要用來干什么?
無論是否拋出異常,finally代碼塊總是會被執(zhí)行,finally代碼塊主要用來釋放資源,比如:I/O緩沖區(qū),數(shù)據(jù)庫連接。
- 將一個高精度值轉(zhuǎn)向低精度會發(fā)生什么,例如int轉(zhuǎn)為byte?
int是32位的,而byte是8位的,強制轉(zhuǎn)化后int類型的高24位將會被丟棄。
- String、StringBuffer、StringBuilder的區(qū)別?
String是只讀字符串,String引用的字符串內(nèi)容是不能被改變的。
StringBuilder和StringBuffer的方法完全相同,它的效率比StringBuffer要高,但是線程不安全。
ArrayList和LinkedList的區(qū)別
遍歷刪除ArrayList中的元素時怎么做,使用ArrayList的remove還是Iterator的remove方法?
Iterator的remove方法,否則會拋出ConcurrentModificationException。
JSP/Servlet
- cookie和session的作用、區(qū)別?
Cookie:主要用在保存客戶端,其值在客戶端與服務器之間傳送,不安全,存儲的數(shù)據(jù)量有限。
Session:保存在服務器端,每一個session在服務器端有一個sessionID作一個標識。存儲的數(shù)據(jù)量大,安全性高。占用服務端的內(nèi)存資源。
- jsp有哪些內(nèi)置對象?作用分別是什么?
request:用戶端請求,此請求會包含來自GET/POST請求的參數(shù);
response:網(wǎng)頁傳回用戶端的回應;
pageContext:網(wǎng)頁的屬性是在這里管理;
session:與請求有關的會話期;
application:servlet正在執(zhí)行的內(nèi)容;
out:用來傳送回應的輸出;
config:servlet的構架部件;
page:JSP網(wǎng)頁本身;
exception:針對錯誤網(wǎng)頁,未捕捉的例外。
- get和post的區(qū)別?
get傳輸?shù)臄?shù)據(jù)量小,主要是由于受URL長度的限制;而post可以傳輸大量的數(shù)據(jù);
get將表單中的數(shù)據(jù)按照var=value的形式,添加到action所指向的URL后面,并且兩者用“?”連接,而各個變量之間使用“&”連接;post是將表單中的數(shù)據(jù)放在form的數(shù)據(jù)體中,按照變量和值相對應的方式,傳遞到action所指向的URL
- servlet中請求轉(zhuǎn)發(fā)和重定向的區(qū)別?
重定向(redirect)其實是兩次request,第一次,客戶端request,A服務器響應,并response回來,告訴瀏覽器,你應該去B。這個時候IE可以看到地址變了,而且歷史的回退按鈕也亮了。重定向可以訪問自己web應用以外的資源。在重定向的過程中,傳輸?shù)男畔粊G失。
請求轉(zhuǎn)發(fā)(forward)是服務器內(nèi)部把對一個request/response的處理權,移交給另外一個.對于客戶端而言,它只知道自己最早請求的那個A,而不知道中間的B,甚至C、D。傳輸?shù)男畔⒉粫G失。
- 如果客戶端禁止cookie,session 還能用嗎?有什么其它辦法?
一般會把存儲到客戶端的cookie中,如果瀏覽器禁用了 cookie,瀏覽器請求服務器無法攜帶 sessionid,服務器無法識別請求中的用戶身份,session失效。
通過url重寫將sessionid作為參數(shù)追加到url中;可以使用header
- 如何避免sql注入?
控制wen應用數(shù)據(jù)庫操作權限;
對傳遞的參數(shù)進行格式校驗;
對特殊字符做轉(zhuǎn)義處理;
使用參數(shù)化sql查詢,避免sql拼接
多線程
- 多線程的創(chuàng)建方式?
繼承Thread類、實現(xiàn)Runnable接口、使用Executor框架來創(chuàng)建線程池
- 使用多線程有什么好處?
避免阻塞(異步調(diào)用)、避免CPU空轉(zhuǎn)、提升性能
- 悲觀鎖、樂觀鎖的優(yōu)缺點?
悲觀鎖:總是假設最壞的情況,每次去拿數(shù)據(jù)的時候都認為別人會修改,所以每次拿數(shù)據(jù)的時候都會上鎖,這樣別人拿數(shù)據(jù)的時候就會阻塞知道它拿到鎖;比如關系型數(shù)據(jù)庫的行鎖、表鎖、讀鎖、寫鎖;比如java里面的同步原語synchronized關鍵字的實現(xiàn)也是悲觀鎖;
樂觀鎖:每次去拿數(shù)據(jù)的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下再次期間別人有沒有更新這個數(shù)據(jù)。樂觀鎖適用于多讀的應用類型,可以提高吞吐量。
- 線程都有哪些狀態(tài),分別在什么時候處于這些狀態(tài)?
新建狀態(tài):當用new操作符創(chuàng)建一個線程時,線程還沒有開始運行,此時處于新建狀態(tài);
就緒狀態(tài):一個新創(chuàng)建的線程并不自動開始運行,要執(zhí)行線程,必須要調(diào)用線程的start()方法,當線程對象調(diào)用start()方法即啟動了線程,start()方法創(chuàng)建線程運行的系統(tǒng)資源,并調(diào)度線程運行run()方法;
運行狀態(tài):當線程獲得cpu時間后,才進入運行狀態(tài),真正開始實行run()方法;
阻塞狀態(tài):a.線程通過調(diào)用sleep方法進入睡眠狀態(tài);b.線程調(diào)用一個在I/O上被阻塞的操作,即該操作在輸入輸出操作完成之前不會返回到它的調(diào)用者;c.線程試圖得到一個鎖,而該鎖正被其他線程持有;d.線程正等待某個觸發(fā)條件
死亡狀態(tài):run方法自然退出而自然死亡,或者一個未捕獲的異常終止了run方法而使線程猝死。
- sleep方法和wait方法有什么區(qū)別?
sleep它不會釋放鎖,wait會放棄對象鎖
數(shù)據(jù)庫
- mysql和oracle下的分頁實現(xiàn)?
mysql:是使用關鍵字limit來進行分頁的.LIMIT [offset,] rows:offset指定要返回的第一行的偏移量(也就是從哪個索引開始),rows第二個指定返回行的最大數(shù)目。初始行的偏移量是0(不是1)
oracle:一般是使用rownum 加select 嵌套查詢
- 幾種連接方式及區(qū)別?
內(nèi)連接: 只連接匹配的行
左外連接: 包含左邊表的全部行(不管右邊的表中是否存在與它們匹配的行),以及右邊表中全部匹配的行
右外連接: 包含右邊表的全部行(不管左邊的表中是否存在與它們匹配的行),以及左邊表中全部匹配的行
全外連接: 包含左、右兩個表的全部行,不管另外一邊的表中是否存在與它們匹配的行。
交叉連接: 生成笛卡爾積-它不使用任何匹配或者選取條件,而是直接將一個數(shù)據(jù)源中的每個行與另一個數(shù)據(jù)源的每個行都一一匹配
- 索引的優(yōu)缺點
索引最大的好處是提高查詢速度,
缺點是更新數(shù)據(jù)時效率低,因為要同時更新索引
對數(shù)據(jù)進行頻繁查詢進建立索引,如果要頻繁更改數(shù)據(jù)不建議使用索引。
- sql優(yōu)化方案:
sql盡量使用索引,而且查詢要走索引;
表關聯(lián)時大數(shù)據(jù)量的表做主表;
SELECT子句中避免使用*號;
多使用內(nèi)部函數(shù)提高SQL效率;
避免在索引列上使用計算等
- 開發(fā)中使用數(shù)據(jù)庫連接池的好處?
維護一定數(shù)量的連接,減少創(chuàng)建連接的時間;更快的響應時間;統(tǒng)一的管理。
- 如果不考慮事務的隔離性,會發(fā)生什么問題?
臟讀是指在一個事務處理過程里讀取了另一個未提交的事務中的數(shù)據(jù)。
不可重復讀是指在對于數(shù)據(jù)庫中的某個數(shù)據(jù),一個事務范圍內(nèi)多次查詢卻返回了不同的數(shù)據(jù)值,這是由于在查詢間隔,被另一個事務修改并提交了。
Spring
- AOP與IOC的概念
IOC就是控制反轉(zhuǎn),是指創(chuàng)建對象的控制權的轉(zhuǎn)移,以前創(chuàng)建對象的主動權和時機是由自己把控的,而現(xiàn)在這種權力轉(zhuǎn)移到Spring容器中,并由容器根據(jù)配置文件去創(chuàng)建實例和管理各個實例之間的依賴關系,對象與對象之間松散耦合,也利于功能的復用。
AOP,一般稱為面向切面,作為面向?qū)ο蟮囊环N補充,用于將那些與業(yè)務無關,但卻對多個對象產(chǎn)生影響的公共行為和邏輯,抽取并封裝為一個可重用的模塊,這個模塊被命名為“切面”(Aspect),減少系統(tǒng)中的重復代碼,降低了模塊間的耦合度,同時提高了系統(tǒng)的可維護性。
- Spring中用到了哪些設計模式?
(1)工廠模式:BeanFactory就是簡單工廠模式的體現(xiàn),用來創(chuàng)建對象的實例;
(2)單例模式:Bean默認為單例模式。
(3)代理模式:Spring的AOP功能用到了JDK的動態(tài)代理和CGLIB代理;
(4)模板方法:用來解決代碼重復的問題。比如. RestTemplate, JmsTemplate, JpaTemplate。
(5)觀察者模式:定義對象鍵一種一對多的依賴關系,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都會得到通知被制動更新,如Spring中l(wèi)istener的實現(xiàn)--ApplicationListener。
- Spring事務的實現(xiàn)方式?
編程式事務管理使用TransactionTemplate。
聲明式事務管理建立在AOP之上的。其本質(zhì)是通過AOP功能,對方法前后進行攔截,將事務處理的功能編織到攔截的方法中,也就是在目標方法開始之前加入一個事務,在執(zhí)行完目標方法之后根據(jù)執(zhí)行情況提交或者回滾事務。
- SpringMVC的運行流程
(1)用戶發(fā)送請求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到請求后,調(diào)用HandlerMapping處理器映射器,請求獲取Handle;
(3)處理器映射器根據(jù)請求url找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一并返回給DispatcherServlet;
(4)DispatcherServlet 調(diào)用 HandlerAdapter處理器適配器;
(5)HandlerAdapter 經(jīng)過適配調(diào)用 具體處理器(Handler,也叫后端控制器);
(6)Handler執(zhí)行完成返回ModelAndView;
(7)HandlerAdapter將Handler執(zhí)行結果ModelAndView返回給DispatcherServlet;
(8)DispatcherServlet將ModelAndView傳給ViewResolver視圖解析器進行解析;
(9)ViewResolver解析后返回具體View;
(10)DispatcherServlet對View進行渲染視圖(即將模型數(shù)據(jù)填充至視圖中)
(11)DispatcherServlet響應用戶。
- SpringMVC常用的注解有哪些?
@RequestMapping:用于處理請求 url 映射的注解,可用于類或方法上。用于類上,則表示類中的所有響應請求的方法都是以該地址作為父路徑。
@RequestBody:注解實現(xiàn)接收http請求的json數(shù)據(jù),將json轉(zhuǎn)換為java對象。
@ResponseBody:注解實現(xiàn)將conreoller方法返回對象轉(zhuǎn)化為json對象響應給客戶。
- Spring注入bean的幾種方式?
JVM
- JVM的內(nèi)存劃分
程序計數(shù)器: 為線程私有,存儲的是當前線程所執(zhí)行程序的內(nèi)存地址。
Java虛擬機棧:為線程私有,生命周期與線程相同。
本地方法棧:與Java虛擬機棧作用相似。
Java堆:Java虛擬機管理的最大一塊內(nèi)存,是線程共享的內(nèi)存區(qū)域,它在虛擬機啟動時創(chuàng)建,用于存放對象實例。
方法區(qū):用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)。
運行時常量池:是方法區(qū)的一部分,存放Class文件中的符號引用等。
- 對象在內(nèi)存中怎么存儲的?
對象在內(nèi)存中的布局分為3塊區(qū)域:對象頭、實例數(shù)據(jù)、對齊填充。
對象頭包括標志字段(Mark Word)和類型指針(Klass Pointer)兩部分信息。
實例數(shù)據(jù)存儲在對象中定義的各種類型的字段內(nèi)容。
對齊補充不是必然存在的,僅僅起著占位符的作用。如果實例數(shù)據(jù)不是8字節(jié)的整數(shù)倍,需要通過對其填充來補全。
- JVM在垃圾回收之前怎么判斷對象是否被引用?
可達性分析算法:以GC Roots為起點向下搜索,當一個對象到GC Roots沒有任何引用鏈相連,則判定對象是可回收的。
- 垃圾收集算法及垃圾收集器
加載:通過類限定名找到字節(jié)碼文件并利用字節(jié)碼文件創(chuàng)建一個Class對象。
驗證:確保Class文件的字節(jié)流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全。
準備:為類變量分配內(nèi)存并設置類變量初始值的階段。
解析:虛擬機將常量池內(nèi)的符號引用替換為直接引用的過程。
初始化:類初始化階段是類加載過程的最后一步,到了初始化階段才開始執(zhí)行類中定義的Java'程序代碼。
redis
- redis有哪些功能
緩存、會話共享、消息隊列
- redis數(shù)據(jù)類型
String(字符串)、Hash(哈希)、List(列表)、Set(集合)、zset(sorted set:有序集合)
- 緩存穿透、緩存雪崩和緩存擊穿
緩存穿透,是指查詢一個數(shù)據(jù)庫一定不存在的數(shù)據(jù)。
緩存雪崩,是指在某一個時間段,緩存集中過期失效。
緩存擊穿,是指一個key非常熱點,在不停的扛著大并發(fā),大并發(fā)集中對這一個點進行訪問,當這個key在失效的瞬間,持續(xù)的大并發(fā)就穿破緩存,直接請求數(shù)據(jù)庫。
- 怎么保證緩存和數(shù)據(jù)庫數(shù)據(jù)的一致性?
前端
- js字符串操作常用函數(shù)
concat() – 將兩個或多個字符的文本組合起來,返回一個新的字符串。
indexOf() – 返回字符串中一個子串第一處出現(xiàn)的索引。如果沒有匹配項,返回 -1 。
charAt() – 返回指定位置的字符。
lastIndexOf() – 返回字符串中一個子串最后一處出現(xiàn)的索引,如果沒有匹配項,返回 -1 。
match() – 檢查一個字符串是否匹配一個正則表達式。
substr() 函數(shù) -- 返回從string的startPos位置,長度為length的字符串
substring() – 返回字符串的一個子串。傳入?yún)?shù)是起始位置和結束位置。
slice() – 提取字符串的一部分,并返回一個新字符串。
replace() – 用來查找匹配一個正則表達式的字符串,然后使用新字符串代替匹配的字符串。
search() – 執(zhí)行一個正則表達式匹配查找。如果查找成功,返回字符串中匹配的索引值。否則返回 -1 。
split() – 通過將字符串劃分成子串,將一個字符串做成一個字符串數(shù)組。
length – 返回字符串的長度,所謂字符串的長度是指其包含的字符的個數(shù)。
toLowerCase() – 將整個字符串轉(zhuǎn)成小寫字母。
toUpperCase() – 將整個字符串轉(zhuǎn)成大寫字母。
- JavaScript中如何檢測一個變量是一個String類型
typeof(obj) === "string"
typeof obj === "string"
obj.constructor === String
- 比較typeof與instanceof
typeof返回值是一個字符串,用來說明變量的數(shù)據(jù)類型。
instanceof 用于判斷一個變量是否屬于某個對象的實例。
- 什么是跨域?跨域請求資源的方法有哪些?
由于瀏覽器同源策略,凡是發(fā)送請求url的協(xié)議、域名、端口三者之間任意一與當前頁面地址不同即為跨域。
CORS(后端處理)、porxy代理
jquery選擇器
css盒子模型
一個元素占有空間的大小由幾個部分構成,其中包括元素的內(nèi)容(content),元素的內(nèi)邊距(padding),元素的邊框(border),元素的外邊距(margin)四個部分。這四個部分占有的空間中,有的部分可以顯示相應的內(nèi)容,而有的部分只用來分隔相鄰的區(qū)域或區(qū)域。4個部分一起構成了css中元素的盒模型。行內(nèi)元素有哪些?塊級元素有哪些? 空(void)元素有那些?
行內(nèi)元素:a、b、span、img、input、strong、select、label、em、button、textarea
塊級元素:div、ul、li、dl、dt、dd、p、h1-h6、blockquote
空元素:即系沒有內(nèi)容的HTML元素,例如:br、meta、hr、link、input、img