畢業季,對於程序員來講也是不錯的找工做的機會,一份好的簡歷是打開公司大門的鑰匙,但能不能進入本身理想的公司,成爲其中的一員,在於面試的成敗。本文將介紹一些公司面試時提出的常見的面試題,並作一些簡單的回答。也爲本身找新工做時,不在去對公司提出的問題去東找西找。php
(1)抽象:從字面意思就能夠了解,象就是有點模糊的意思,還沒肯定好的意思。在面向對象的概念中,咱們知道全部的對象都是經過類來描繪的,可是並非全部的類都是用來描繪對象的,若是一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。抽象類每每用來表徵咱們在對問題領域進行分析、 設計中得出的抽象概念,是對一系列看上去不一樣,可是本質上相同的具體概念的抽象,咱們不能把它們實例化(拿不出一個具體的東西)因此稱之爲抽象。打個比方來講:咱們要描述「車」,它就是一個抽象,它有質量、體積等一些共性,但又缺少特性(不肯定是什麼類型的車(轎車,公交車等),它們有本身的特性),咱們拿不出惟一一種能表明車的東西(由於不管是轎車仍是公交車都不能表明車),可用抽象類來描述它,因此抽象類是不可以實例化的。當咱們用某個類來具體描述「車」時,這個類就能夠繼承描述「車」的抽象類,從而知道「轎車」是一種「車」。java
(2)封裝: 隱藏對象的屬性和實現細節,僅對外公開接口,控制在程序中屬性的讀和修改的訪問級別。那爲何要封裝呢?1.隱藏實現細節。好比你買了一輛車,你只須要知道如何去開,並不須要去了解它的實現原理。2.安全性。好比你在一個程序中對age這個屬性進行了私有化操做,並提供了對外的get與set方法,當外界使用set方法爲其賦值的時候,你能夠在set方法裏面作判斷,控制在合理範圍之內(0-100歲),這樣外界就沒法隨意的進行賦值了。3.代碼複用性。好比在工具類中封裝的各類方法,你能夠在任意地方重複調用,而不用再每處都去實現其細節。4.分工化。封裝分爲屬性封裝,方法封裝,類封裝,插件封裝,模塊封裝,系統封裝等等。有利於程序的協助分工,互不干擾,方便了模塊之間的相互組合與分解,也有利於代碼的調試。程序員
(3)繼承:是面向對象最顯著的一個特性,繼承是從已有的類中派生出新的類稱爲子類,子類繼承父類的數據屬性和行爲,並能根據本身的需求擴展出新的行爲,提升了代碼的複用性。簡化理解:當兩個類具備相同的特徵(屬性)和行爲(方法)時,能夠將相同的部分抽取出來放到一個類中做爲父類,其它兩個類繼承這個父類。繼承後子類自動擁有了父類的屬性和方法,但特別注意的是,父類的私有屬性和構造方法並不能被繼承。另外子類能夠寫本身特有的屬性和方法,目的是實現功能的擴展,子類也能夠複寫父類的方法即方法的重寫。面試
(4)多態:相同的事物,調用其相同的方法,參數也相同時,但表現的行爲卻不一樣。另外Java實現多態有三個必要條件:繼承、重寫、向上轉型。繼承:在多態中必須存在有繼承關係的子類和父類。重寫:子類對父類中某些方法進行從新定義,在調用這些方法時就會調用子類的方法。向上轉型:在多態中須要將子類的引用賦給父類對象,只有這樣該引用纔可以具有技能調用父類的方法和子類的方法。正則表達式
當一個子類繼承一父類,而子類中的方法與父類中的方法的名稱,參數個數、類型都徹底一致時,就稱子類中的這個方法重寫了父類中的方法。spring
對於同一個類,若是這個類裏面有兩個或者多個重名的方法,可是方法的參數個數、類型、順序至少有一個不同,這時候構成方法重載。sql
一個java文件從被加載到被卸載這個生命過程,總共要經歷5個階段,JVM將類加載過程分爲:
加載->連接(驗證+準備+解析)->初始化(使用前的準備)->使用->卸載
(1)加載
首先經過一個類的全限定名來獲取此類的二進制字節流;其次將這個字節流所表明的靜態存儲結構轉化爲方法區的運行時數據結構;最後在java堆中生成一個表明這個類的Class對象,做爲方法區這些數據的訪問入口。總的來講就是查找並加載類的二進制數據。
(2)連接:
驗證:確保被加載類的正確性;
準備:爲類的靜態變量分配內存,並將其初始化爲默認值;
解析:把類中的符號引用轉換爲直接引用;
(3)類的初始化
(1)類何時才被初始化
1)建立類的實例,也就是new一個對象
2)訪問某個類或接口的靜態變量,或者對該靜態變量賦值
3)調用類的靜態方法
4)反射(Class.forName(「com.lyj.load」))
5)初始化一個類的子類(會首先初始化子類的父類)
6)JVM啓動時標明的啓動類,即文件名和類名相同的那個類
(2)類的初始化順序
1)若是這個類尚未被加載和連接,那先進行加載和連接
2)假如這個類存在直接父類,而且這個類尚未被初始化(注意:在一個類加載器中,類只能初始化一次),那就初始化直接的父類(不適用於接口)
3)加入類中存在初始化語句(如static變量和static塊),那就依次執行這些初始化語句。
4)總的來講,初始化順序依次是:(靜態變量、靜態初始化塊)–>(變量、初始化塊)–> 構造器;若是有父類,則順序是:父類static方法 –> 子類static方法 –> 父類構造方法- -> 子類構造方法 .數據庫
做用域 當前類 同包 子類 其餘編程
public √ √ √ √數組
protected √ √ √ ×
default √ √ × ×
private √ × × ×
類的成員不寫訪問修飾時默認爲default。默認對於同一個包中的其餘類至關於公開(public),對於不是同一個包中的其餘類至關於私有(private)。受保護(protected)對子類至關於公開,對不是同一包中的沒有父子關係的類至關於私有。
是值傳遞。Java 編程語言只有值傳遞參數。當一個對象實例做爲一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的屬性能夠在被調用過程當中被改變,但對象的引用是永遠不會改變的。(java中只存在值傳遞,只存在值傳遞!!! 然而咱們常常看到對於對象(數組,類,接口)的傳遞彷佛有點像引用傳遞,能夠改變對象中某個屬性的值。可是不要被這個假象所矇蔽,實際上這個傳入函數的值是對象引用的拷貝,即傳遞的是引用的地址值,因此仍是按值傳遞。)
三者在執行速度方面的比較:StringBuilder > StringBuffer > String。緣由在於:String是字符串常量,而StringBuffer與StringBuilder是字符串變量。
在線程安全上,StringBuilder是線程不安全的,而StringBuffer是線程安全的。
ArithmeticException(算術異常)
ClassCastException (類轉換異常)
IllegalArgumentException (非法參數異常)
IndexOutOfBoundsException (下表越界異常)
NullPointerException (空指針異常)
SecurityException (安全異常)
1.final修飾符(關鍵字)。被final修飾的類,就意味着不能再派生出新的子類,不能做爲父類而被子類繼承。所以一個類不能既被abstract聲明,又被final聲明。將變量或方法聲明爲final,能夠保證他們在使用的過程當中不被修改。被聲明爲final的變量必須在聲明時給出變量的初始值,而在之後的引用中只能讀取。被final聲明的方法也一樣只能使用,不能重載。
2.inally是在異常處理時提供finally塊來執行任何清除操做。無論有沒有異常被拋出、捕獲,finally塊都會被執行。try塊中的內容是在無異常時執行到結束。catch塊中的內容,是在try塊內容發生catch所聲明的異常時,跳轉到catch塊中執行。finally塊則是不管異常是否發生,都會執行finally塊的內容,因此在代碼邏輯中有須要不管發生什麼都必須執行的代碼,就能夠放在finally塊中。
3.finalize是方法名。java技術容許使用finalize()方法在垃圾收集器將對象從內存中清除出去以前作必要的清理工做。這個方法是由垃圾收集器在肯定這個對象沒有被引用時對這個對象調用的。它是在object類中定義的,所以全部的類都繼承了它。子類覆蓋finalize()方法以整理系統資源或者被執行其餘清理工做。finalize()方法是在垃圾收集器刪除對象以前對這個對象調用的。
詳細請看:https://www.jianshu.com/p/6d1cbe38a54b
與C語言不一樣,Java內存(堆內存)的分配與回收由JVM垃圾收集器自動完成,Java堆是被全部線程共享的一塊內存區域,全部對象實例和數組都在堆上進行內存分配。爲了進行高效的垃圾回收,虛擬機把堆內存劃分紅新生代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation)3個區域。
新生代由 Eden 與 Survivor Space(S0,S1)構成,大小經過-Xmn參數指定,Eden 與 Survivor Space 的內存大小比例默認爲8:1,能夠經過-XX:SurvivorRatio 參數指定,好比新生代爲10M 時,Eden分配8M,S0和S1各分配1M。大多數狀況下,對象在Eden中分配,當Eden沒有足夠空間時,會觸發一次Minor GC,虛擬機提供了-XX:+PrintGCDetails參數,告訴虛擬機在發生垃圾回收時打印內存回收日誌。Survivor:意思爲倖存者,是新生代和老年代的緩衝區域。當新生代發生GC(Minor GC)時,會將存活的對象移動到S0內存區域,並清空Eden區域,當再次發生Minor GC時,將Eden和S0中存活的對象移動到S1內存區域。存活對象會反覆在S0和S1之間移動,當對象從Eden移動到Survivor或者在Survivor之間移動時,對象的GC年齡自動累加,當GC年齡超過默認閾值15時,會將該對象移動到老年代,能夠經過參數-XX:MaxTenuringThreshold 對GC年齡的閾值進行設置。
老年代的空間大小即-Xmx 與-Xmn 兩個參數之差,用於存放通過幾回Minor GC以後依舊存活的對象。當老年代的空間不足時,會觸發Major GC/Full GC,速度通常比Minor GC慢10倍以上。
類的元數據如方法數據、方法信息(字節碼,棧和變量大小)、運行時常量池、已肯定的符號引用和虛方法表等被保存在永久代中,32位默認永久代的大小爲64M,64位默認爲85M,能夠經過參數-XX:MaxPermSize進行設置,一旦類的元數據超過了永久代大小,就會拋出OOM異常。虛擬機團隊在JDK8的HotSpot中,把永久代從Java堆中移除了,並把類的元數據直接保存在本地內存區域(堆外內存),稱之爲元空間。
GC動做發生以前,須要肯定堆內存中哪些對象是存活的,通常有兩種方法:引用計數法和可達性分析法。
一、引用計數法
在對象上添加一個引用計數器,每當有一個對象引用它時,計數器加1,當使用完該對象時,計數器減1,計數器值爲0的對象表示不可能再被使用。
二、可達性分析法
經過一系列稱爲 「GC Roots」 的對象做爲起點,從這些節點開始向下搜索,搜索路徑稱爲 「引用鏈」,如下對象可做爲GC Roots:
當一個對象到 GC Roots 沒有任何引用鏈時,意味着該對象能夠被回收。
Https是一種基於SSL(Secure Sockets Layer 安全套接層)/TLS(Transport Layer Security 傳輸層安全)的http協議,全部的http數據都是在SSL/TLS協議封裝之上傳輸的。
Https協議在Http協議的基礎上,添加了SSL/TLS握手以及數據加密傳輸,也屬於應用層協議。
HTTP協議運行在TCP之上,全部傳輸的內容都是明文,客戶端和服務器端都沒法驗證對方的身份。
HTTPS是運行在SSL/TLS之上的HTTP協議,SSL/TLS運行在TCP之上。全部傳輸的內容都通過加密,加密採用對稱加密,但對稱加密的密鑰用服務器方的證書進行了非對稱加密。
(1). IoC(Inversion of Control)是指容器控制程序對象之間的關係,而不是傳統實現中,由程序代碼直接操控。控制權由應用代碼中轉到了外部容器,控制權的轉移是所謂反轉。 對於Spring而言,就是由Spring來控制對象的生命週期和對象之間的關係;IoC還有另一個名字——「依賴注入(Dependency Injection)」。從名字上理解,所謂依賴注入,即組件之間的依賴關係由容器在運行期決定,即由容器動態地將某種依賴關係注入到組件之中。
(2). 在Spring的工做方式中,全部的類都會在spring容器中登記,告訴spring這是個什麼東西,你須要什麼東西,而後spring會在系統運行到適當的時候,把你要的東西主動給你,同時也把你交給其餘須要你的東西。全部的類的建立、銷燬都由 spring來控制,也就是說控制對象生存週期的再也不是引用它的對象,而是spring。對於某個具體的對象而言,之前是它控制其餘對象,如今是全部對象都被spring控制,因此這叫控制反轉。
(3). 在系統運行中,動態的向某個對象提供它所須要的其餘對象。
(4). 依賴注入的思想是經過反射機制實現的,在實例化一個類時,它經過反射調用類中set方法將事先保存在HashMap中的類屬性注入到類中。 總而言之,在傳統的對象建立方式中,一般由調用者來建立被調用者的實例,而在Spring中建立被調用者的工做由Spring來完成,而後注入調用者,即所謂的依賴注入or控制反轉。 注入方式有兩種:依賴注入和設置注入; IoC的優勢:下降了組件之間的耦合,下降了業務對象之間替換的複雜性,使之可以靈活的管理對象。
(1). AOP面向方面編程基於IoC,是對OOP的有益補充;
(2). AOP利用一種稱爲「橫切」的技術,剖解開封裝的對象內部,並將那些影響了 多個類的公共行爲封裝到一個可重用模塊,並將其名爲「Aspect」,即方面。所謂「方面」,簡單地說,就是將那些與業務無關,卻爲業務模塊所共同調用的 邏輯或責任封裝起來,好比日誌記錄,便於減小系統的重複代碼,下降模塊間的耦合度,並有利於將來的可操做性和可維護性。
(3). AOP表明的是一個橫向的關 系,將「對象」比做一個空心的圓柱體,其中封裝的是對象的屬性和行爲;則面向方面編程的方法,就是將這個圓柱體以切面形式剖開,選擇性的提供業務邏輯。而 剖開的切面,也就是所謂的「方面」了。而後它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡,但完成了效果。
(4). 實現AOP的技術,主要分爲兩大類:一是採用動態代理技術,利用截取消息的方式,對該消息進行裝飾,以取代原有對象行爲的執行;二是採用靜態織入的方式,引入特定的語法建立「方面」,從而使得編譯器能夠在編譯期間織入有關「方面」的代碼。
(5). Spring實現AOP:JDK動態代理和CGLIB代理 JDK動態代理:其代理對象必須是某個接口的實現,它是經過在運行期間建立一個接口的實現類來完成對目標對象的代理;其核心的兩個類是InvocationHandler和Proxy。 CGLIB代理:實現原理相似於JDK動態代理,只是它在運行期間生成的代理對象是針對目標類擴展的子類。CGLIB是高效的代碼生成包,底層是依靠ASM(開源的java字節碼編輯類庫)操做字節碼實現的,性能比JDK強;須要引入包asm.jar和cglib.jar。 使用AspectJ注入式切面和@AspectJ註解驅動的切面實際上底層也是經過動態代理實現的。
有3個表:
Employee 職工 (工號,姓名,性別,年齡,部門)(num,name,sex,age,department)
Wage工資 (編號,工資金額)(No,amount)
Attend出勤 (工號,工資編號,出勤率)(num,No,attendance)
請根據要求,編寫相應的SQL語句。
(1)寫一個SQL語句,查詢工資金額爲8000的職工工號和姓名。
(2)寫一個SQL語句,查詢職工張三的出勤率。
(3)寫一個SQL語句,查詢出勤率爲10而且工資金額小於2500的職工信息。
參考答案:
(1):① select e.num , e.name from employee e where ( select count(*) from attend a WHERE a.num = e.num and a.No=ANY( select w.No from wage w where amount='8000'))
② SELECT a.num, e.name FROM employee e LEFT JOIN attend a ON e.num = a.num LEFT JOIN wage w ON a.no = w.no WHERE w.amount = 8000;
(2):① select a.attendance from attend a where a.num = ( select e.num from employee e where e.name='張三')
② SELECT e.name, a.attendance FROM attend a LEFT JOIN employee e ON a.num = e.num WHERE e.name = '張 三'
(3):select * from Employee e
where (select No from Attend where num=e.num and attendance='10') =
( select No from Wage where amount<2500 );
區別:
(1)#將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:order by #user_id#,若是傳入的值是id,則解析成的sql爲order by "id"。
(2)$將傳入的數據直接顯示生成在sql中。如:order by $user_id$,若是傳入的值是id,則解析成的sql爲order by id。
(3)#方式在很大程度上可以防止sql注入。
(4)$方式沒法防止sql注入。
(5)$方式通常用於傳入數據庫對象,例如傳入表名。(這裏得注意SQL注入問題)
(6)通常能用#的就別用$。
ps:在使用mybatis中還遇到<![CDATA[]]>的用法,在該符號內的語句,將不會被當成字符串來處理,而是直接當成sql語句,好比要執行一個存儲過程。
總結區別:#{} 傳入值時,sql解析時,參數是帶引號的,而${}穿入值,sql解析時,參數是不帶引號的。
舉個例子:
select * from ${table_Name} where name = #{name}
在這個例子中,若是表名爲
user; delete user; --
則動態解析以後 sql 以下:
select * from user; delete
user; -- where name = ?;
--以後的語句被註釋掉,而本來查詢用戶的語句變成了查詢全部用戶信息+刪除用戶表的語句,會對數據庫形成致命損傷。
可是表名用參數傳遞進來的時候,只能使用 ${} 。這也提醒在這種用法中要當心sql注入的問題。
防止SQL注入方法:
首先,永遠不要相信用戶的輸入。
(1)不使用SQL,考慮NoSQL。
(2)正則表達式,字符串過濾。
(3)參數綁定PreparedStatement。
(4)使用正則表達式過濾傳入的參數。
(5)JSP中調用該函數檢查是否包函非法字符或JSP頁面判斷代碼
但願各位將本身碰見的面試題評論出來,後期我會一一在這裏呈現。相互學習,相互進步。