一、public、private、protected、Friendly的區別與做用域html
public,protected,friendly,private的訪問權限以下:前端
第一句錯,第二句不錯。java
Java規範:
a.高位轉低位須要強制轉換
b.低位轉高位自動轉.mysql
複合賦值(E1 op=E2)等價於簡單賦值(E1=(T)((E1) op (E2))),而(s1 += 1)表達式使用的是複合賦值操做符,複合賦值表達式自動地將所執行計算的結果轉型爲其左側變量的類型。若是結果的類型與該變量的類型相同,那麼這個轉型不會形成任何影響。jquery
繼承結構:Error和Exception都是繼承於Throwable,RuntimeException繼承自Exception。程序員
Error和RuntimeException及其子類稱爲未檢查異常(Unchecked exception),其它異常成爲受檢查異常(Checked Exception)。web
Error類通常是指與虛擬機相關的問題,如系統崩潰,虛擬機錯誤,內存空間不足,方法調用棧溢出等。如Java.lang.StackOverFlowError和Java.lang.OutOfMemoryError。對於這類錯誤,Java編譯器不去檢查他們。對於這類錯誤的致使的應用程序中斷,僅靠程序自己沒法恢復和預防,遇到這樣的錯誤,建議讓程序終止。ajax
Exception類表示程序能夠處理的異常,能夠捕獲且可能恢復。遇到這類異常,應該儘量處理異常,使程序恢復運行,而不該該隨意終止異常。正則表達式
Exception又分爲運行時異常(Runtime Exception)和受檢查的異常(Checked Exception )。算法
RuntimeException:其特色是Java編譯器不去檢查它,也就是說,當程序中可能出現這類異常時,即便沒有用try……catch捕獲,也沒有用throws拋出,仍是會編譯經過,如除數爲零的ArithmeticException、錯誤的類型轉換、數組越界訪問和試圖訪問空指針等。處理RuntimeException的原則是:若是出現RuntimeException,那麼必定是程序員的錯誤。
受檢查的異常(IOException等):這類異常若是沒有try……catch也沒有throws拋出,編譯是通不過的。這類異常通常是外部錯誤,例如文件找不到、試圖從文件尾後讀取數據等,這並非程序自己的錯誤,而是在應用環境中出現的外部錯誤。
ArrayList 採用的是數組形式來保存對象的,這種方式將對象放在連續的位置中,因此最大的缺點就是插入刪除時很是麻煩
LinkedList 採用的將對象存放在獨立的空間中,並且在每一個空間中還保存下一個連接的索引 可是缺點就是查找很是麻煩 要叢第一個索引開始
ArrayList和Vector都是用數組方式存儲數據,此數組元素數要大於實際的存儲空間以便進行元素增長和插入操做,他們都容許直接用序號索引元素,可是插入數據元素涉及到元素移動等內存操做,因此索引數據快而插入數據慢.
Vector使用了sychronized方法(線程安全),因此在性能上比ArrayList要差些.
LinkedList使用雙向鏈表方式存儲數據,按序號索引數據須要前向或後向遍歷數據,因此索引數據慢,是插入數據時只須要記錄先後項便可,因此插入的速度快.
arraylist和vector的區別?
1).同步性:Vector是線程安全的,也就是說是同步的,而ArrayList是線程不安全的,不是同步的
2).數據增加:當須要增加時,Vector默認增加爲原來一培,而ArrayList倒是原來的一半
1.heap是堆,stack是棧。
2.stack的空間由操做系統自動分配和釋放,heap的空間是手動申請和釋放的,heap經常使用new關鍵字來分配。
3.stack空間有限,heap的空間是很大的自由區。在Java中,若只是聲明一個對象,則先在棧內存中爲其分配地址空間,若再new一下,實例化它,則在堆內存中爲其分配地址。
4.舉例:數據類型 變量名;這樣定義的東西在棧區。如:Object a =null; 只在棧內存中分配空間。new 數據類型();或者malloc(長度); 這樣定義的東西就在堆區如:Object b =new Object(); 則在堆內存中分配空間
throws用在方法聲明中,代表當前方法在運行時會有異常拋出,須要在調用該方法的時候注意控制異常
throw用在方法體內,手動製造一個異常,中斷代碼的繼續執行
try-catch-finally是一塊兒使用的
當某段代碼在運行期間可能會發生異常而終止執行時,使用。
結構爲
try
{
//可能發生異常的代碼
}
catch (異常類型 )
{
//異常發生時的處理方式
}
finally
{
//其餘必須執行的語句
}
當try語句塊中的代碼在執行時發生異常,就會被catch捕獲,進入catch語句塊進行處理,若是沒有發生異常就繼續執行
finally語句塊中的代碼是一些必須執行的語句,這裏的代碼不管try中是否發生異常都會被執行。
try 用來指定一塊預防全部「異常」的程序;
catch 子句緊跟在 try 塊後面,用來指定你想要捕捉的「異常」的類型;
throw 語句用來明確地拋出一個「異常」;
throws 用來標明一個成員函數可能拋出的各類「異常」;
Finally 爲確保一段代碼無論發生什麼「異常」都被執行一段代碼;
throw關鍵字一般用在方法體中,而且拋出一個異常對象。程序在執行到throw語句時當即中止,它後面的語句都不執行。經過throw拋出異常後,若是想在上一級代碼中來捕獲並處理異常,則須要在拋出異常的方法中使用throws關鍵字在方法聲明中指明要跑出的異常;若是要捕捉throw拋出的異常,則必須使用try—catch語句。可見,throw能夠主動拋出異常,也就是能夠在try中拋出異常。
類的多少沒有限制,不過一個java源文件最多隻能有一個public 修飾的 class,沒有也行,若是有這個.java文件的文件名得是public類的類名,編譯.java文件的時候,它會給每個類生成一個.class文件。
內存泄露就是指一個再也不被程序使用的對象或變量一直被佔據在內存中。java中有垃圾回收機制,它能夠保證一對象再也不被引用的時候,即對象變成了孤兒的時候,對象將自動被垃圾回收器從內存中清除掉。因爲Java 使用有向圖的方式進行垃圾回收管理,能夠消除引用循環的問題,例若有兩個對象,相互引用,只要它們和根進程不可達的,那麼GC也是能夠回收它們的。
java中的內存泄露的狀況:
1.長生命週期的對象持有短生命週期對象的引用就極可能發生內存泄露,儘管短生命週期對象已經再也不須要,可是由於長生命週期對象持有它的引用而致使不能被回收,這就是java中內存泄露的發生場景,通俗地說,就是程序員可能建立了一個對象,之後一直再也不使用這個對象,這個對象卻一直被引用,即這個對象無用可是卻沒法被垃圾回收器回收的,這就是java中可能出現內存泄露的狀況,例如,緩存系統,咱們加載了一個對象放在緩存中(例如放在一個全局map對象中),而後一直再也不使用它,這個對象一直被緩存引用,但卻再也不被使用。
檢查java中的內存泄露,必定要讓程序將各類分支狀況都完整執行到程序結束,而後看某個對象是否被使用過,若是沒有,則才能斷定這個對象屬於內存泄露。
2.若是一個外部類的實例對象的方法返回了一個內部類的實例對象,這個內部類對象被長期引用了,即便那個外部類實例對象再也不被使用,但因爲內部類持久外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會形成內存泄露。
3.當一個對象被存儲進HashSet集合中之後,就不能修改這個對象中的那些參與計算哈希值的字段了,不然,對象修改後的哈希值與最初存儲進HashSet集合中時的哈希值就不一樣了,在這種狀況下,即便在contains方法使用該對象的當前引用做爲的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會致使沒法從HashSet集合中單獨刪除當前對象,形成內存泄露。
Java中的流分爲兩種,一種是字節流,另外一種是字符流,分別由四個抽象類來表示(每種流包括輸入和輸出兩種因此一共四個):InputStream,OutputStream,Reader,Writer。Java中其餘多種多樣變化的流均是由它們派生出來的.
字符流和字節流是根據處理數據的不一樣來區分的。字節流按照8位傳輸,字節流是最基本的,全部文件的儲存是都是字節(byte)的儲存,在磁盤上保留的並非文件的字符而是先把字符編碼成字節,再儲存這些字節到磁盤。
1.字節流可用於任何類型的對象,包括二進制對象,而字符流只能處理字符或者字符串;
2. 字節流提供了處理任何類型的IO操做的功能,但它不能直接處理Unicode字符,而字符流就能夠。
讀文本的時候用字符流,例如txt文件。讀非文本文件的時候用字節流,例如mp3。理論上任何文件都可以用字節流讀取,但當讀取的是文本數據時,爲了能還原成文本你必須再通過一個轉換的工序,相對來講字符流就省了這個麻煩,能夠有方法直接讀取。
字符流處理的單元爲2個字節的Unicode字符,分別操做字符、字符數組或字符串,而字節流處理單元爲1個字節, 操做字節和字節數組。因此字符流是由Java虛擬機將字節轉化爲2個字節的Unicode字符爲單位的字符而成的,因此它對多國語言支持性比較好!
1.字節流:繼承於InputStream \ OutputStream。
OutputStream提供的方法:
void write(int b):寫入一個字節的數據
void write(byte[] buffer):將數組buffer的數據寫入流
void write(byte[] buffer,int offset,int len):從buffer[offset]開始,寫入len個字節的數據
void flush():強制將buffer內的數據寫入流
void close():關閉流
InputStream提供的方法:
int read():讀出一個字節的數據,若是已達文件的末端,返回值爲-1
int read(byte[] buffer):讀出buffer大小的數據,返回值爲實際所讀出的字節數
int read(byte[] buffer,int offset,int len)
int available():返回流內可供讀取的字節數目
long skip(long n):跳過n個字節的數據,返回值爲實際所跳過的數據數
void close():關閉流
2.字符流,繼承於InputStreamReader \ OutputStreamWriter。
字符流的類:1),BufferedReader是一種過濾器(filter)(extends FilterReader)。過濾
器用來將流的數據加以處理再輸出。構造函數爲:
BufferedReader(Reader in):生成一個緩衝的字符輸入流,in爲一個讀取器
BufferedReader(Reader in,int size):生成一個緩衝的字符輸入流,並指定緩衝區的大小爲size
public class IOStreamDemo { public void samples() throws IOException { //1. 這是從鍵盤讀入一行數據,返回的是一個字符串 BufferedReader stdin =new BufferedReader(new InputStreamReader(System.in)); System.out.print("Enter a line:"); System.out.println(stdin.readLine());
//2. 這是從文件中逐行讀入數據
BufferedReader in = new BufferedReader(new FileReader("IOStreamDemo.java")); String s, s2 = new String(); while((s = in.readLine())!= null) s2 += s + "\n"; in.close();
//3. 這是從一個字符串中逐個讀入字節 StringReader in1 = new StringReader(s2); int c; while((c = in1.read()) != -1) System.out.print((char)c);
//4. 這是將一個字符串寫入文件 try { BufferedReader in2 = new BufferedReader(new StringReader(s2)); PrintWriter out1 = new PrintWriter(new BufferedWriter(new FileWriter("IODemo.out"))); int lineCount = 1; while((s = in2.readLine()) != null ) out1.println(lineCount++ + ": " + s); out1.close(); } catch(EOFException e) { System.err.println("End of stream"); } } }
對於上面的例子,須要說明的有如下幾點:
1. InputStreamReader是InputStream和Reader之間的橋樑,因爲System.in是字節流,須要用它來包裝以後變爲字符流供給BufferedReader使用。
3. PrintWriter out1 = new PrintWriter(new BufferedWriter(new FileWriter("IODemo.out")));
這句話體現了Java輸入輸出系統的一個特色,爲了達到某個目的,須要包裝好幾層。首先,輸出目的地是文件IODemo.out,因此最內層包裝的是FileWriter,創建一個輸出文件流,接下來,咱們但願這個流是緩衝的,因此用BufferedWriter來包裝它以達到目的,最後,咱們須要格式化輸出結果,因而將PrintWriter包在最外層。
Java流有着另外一個重要的用途,那就是利用對象流對對象進行序列化。
在一個程序運行的時候,其中的變量數據是保存在內存中的,一旦程序結束這些數據將不會被保存,一種解決的辦法是將數據寫入文件,而Java中提供了一種機制,它能夠將程序中的對象寫入文件,以後再從文件中把對象讀出來從新創建。這就是所謂的對象序列化。Java中引入它主要是爲了RMI(Remote Method Invocation)和Java Bean所用,不過在平時應用中,它也是頗有用的一種技術。
不能夠。由於非static方法是要與對象關聯在一塊兒的,必須建立一個對象後,才能夠在該對象上進行方法調用,而static方法調用時不須要建立對象,能夠直接調用。也就是說,當一個static方法被調用時,可能尚未建立任何實例對象,若是從一個static方法中發出對非static方法的調用,那個非static方法是關聯到哪一個對象上的呢?這個邏輯沒法成立,因此,一個static方法內部發出對非static方法的調用。
在實際編程過程當中,咱們經常要遇到這種狀況:有一個對象A,在某一時刻A中已經包含了一些有效值,此時可能會須要一個和A徹底相同新對象B,而且此後對B任何改動都不會影響到A中的值,也就是說,A與B是兩個獨立的對象,但B的初始值是由A對象肯定的。Clone 有缺省行爲,super.clone();他負責產生正確大小的空間,並逐位複製。使用clone()來複制一個對象,clone()從Object類繼承。全部具備clone功能的類都有一個特性,那就是它直接或間接地實現了Cloneable接口。
protected native Object clone() throws CloneNotSupportedException;
能夠看出它是一個protected方法,因此咱們不能簡單地調用它;關鍵字native,代表這個方法使用Java之外的語言實現。
對於 object x,
x.clone() != x
x.clone().getClass() == x.getClass()
x.clone().equals(x)
以上返回的值都爲true
要說明的有兩點:一是拷貝對象返回的是一個新對象,而不是一個引用。二是拷貝對象與用new操做符返回的新對象的區別就是這個拷貝已經包含了一些原來對象的信息,而不是對象的初始信息。
1.淺複製與深複製概念
⑴淺複製(淺克隆):被複制對象的全部變量都含有與原來的對象相同的值,而全部的對其餘對象的引用仍然指向原來的對象。換言之,淺複製僅僅複製所考慮的對象,而不復制它所引用的對象。
⑵深複製(深克隆)
被複制對象的全部變量都含有與原來的對象相同的值,除去那些引用其餘對象的變量。那些引用其餘對象的變量將指向被複制過的新對象,而再也不是原有的那些被引用的對象。換言之,深複製把要複製的對象所引用的對象都複製了一遍。
Java中交互方式分爲同步和異步兩種:
同步交互:指發送一個請求,須要等待返回,而後纔可以發送下一個請求,有個等待過程;
異步交互:指發送一個請求,不須要等待返回,隨時能夠再發送下一個請求,即不須要等待。 區別:一個須要等待,一個不須要等待,在部分狀況下,咱們的項目開發中都會優先選擇不須要等待的異步交互方式。
哪些狀況建議使用同步交互呢?好比銀行的轉帳系統,對數據庫的保存操做等等,都會使用同步交互操做,其他狀況都優先使用異步交互。
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,而且更名爲MyBatis。
MyBatis是一個優秀的持久層框架,它對jdbc的操做數據庫的過程進行封裝,使開發者只須要關注 SQL 自己,而不須要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。
Mybatis經過xml或註解的方式將要執行的statement配置起來,並經過java對象和statement中的sql進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射成java對象並返回。
一、 mybatis配SqlMapConfig.xml,此文件做爲mybatis的全局配置文件,配置了mybatis的運行環境等信息。
mapper.xml文件即sql映射文件,文件中配置了操做數據庫的sql語句。此文件須要在SqlMapConfig.xml中加載。
二、 經過mybatis環境等配置信息構造SqlSessionFactory即會話工廠
三、 由會話工廠建立sqlSession即會話,操做數據庫須要經過sqlSession進行。
四、 mybatis底層自定義了Executor執行器接口操做數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器。
五、 Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sql的id便是Mapped statement的id。
六、 Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor經過 Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數。
七、 Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor經過 Mapped Statement在執行sql後將輸出結果映射至java對象中,輸出結果映射過程至關於jdbc編程中對結果的解析處理過程。
工做流程:mybatis經過sqlSessionFactory建立sqlSession,(1)這兩個方法來自不一樣的類分別是,sleep來自Thread類,和wait來自Object類;sleep是Thread的靜態類方法,誰調用的誰去睡覺,即便在a線程裏調用了b的sleep方法,實際上仍是a去睡覺,要讓b線程睡覺要在b的代碼中調用sleep。
(2)最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其餘線程能夠使用同步控制塊或者方法。sleep不出讓系統資源;wait是進入線程等待池等待,出讓系統資源,其餘線程能夠佔用CPU。通常wait不會加時間限制,由於若是wait線程的 運行資源不夠,再出來也沒用,要等待其餘線程調用notify/notifyAll喚醒等待池中的全部線程,纔會進入就緒隊列等待OS分配系統資源。 sleep(milliseconds)能夠用時間指定使它自動喚醒過來,若是時間不到只能調用interrupt()強行打斷;
(1)JAVA平臺提供了兩個類:String和StringBuffer,它們能夠儲存和操做字符串,即包含多個字符的字符數據。這個String類提供了數值不可改變的字符串。而這個StringBuffer類提供的字符串進行修改。當你知道字符數據要改變的時候你就能夠使用StringBuffer。典型地,你能夠使用StringBuffers來動態構造字符數據。另外,String實現了equals方法;而StringBuffer沒有實現equals方法,因此,new StringBuffer(「abc」).equals(new StringBuffer(「abc」)的結果爲false。
(2)StringBuffer線程安全的可變字符序列。一個相似於 String 的字符串緩衝區,但不能修改;經過某些方法調用能夠改變該序列的長度和內容,可將字符串緩衝區安全地用於多個線程。能夠在必要時對這些方法進行同步,所以任意特定實例上的全部操做就好像是以串行順序發生的,該順序與所涉及的每一個線程進行的方法調用順序一致;
(3)StringBuilder一個可變的字符序列。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用做 StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候(這種狀況很廣泛)。(若是可能,建議優先採用該類,由於在大多數實現中,它比 StringBuffer 要快。但將 StringBuilder 的實例用於多個線程是不安全的。若是須要這樣的同步,則建議使用 StringBuffer。);
(4)HashMap是Hashtable的輕量級實現(非同步非線程安全的實現),他們都完成了Map接口,主要區別在於HashMap容許空(null)鍵值(key),因爲非線程安全,在只有一個線程訪問的狀況下,效率要高於Hashtable。
(1)基本數據類型包括byte、int、char、long、float、double、boolean和short;java.lang.String類是final類型的,所以不能夠繼承這個類、不能修改這個類。爲了提升效率節省空間,咱們應該用StringBuffer類;
(2)int i = Integer.parseInt([String]);i = Integer.parseInt([String],[int radix]);或者int i = Integer.valueOf(my_str).intValue();int轉StringString s = String.valueOf(i);String s = Integer.toString(i);String s = "" + i;
(1)區別:Ajax是一門技術,它提供了異步更新的機制,使用客戶端與服務器間交換數據而非整個頁面文檔,實現頁面的局部更新。jQuery是一個框架,它對JS(JS是一門前端語言。)進行了封裝,使其更方便使用。jQuery使得JS與Ajax的使用更方便
jsp負責客戶端顯示
servlet負責控制,轉向等
(2)生命週期:Servlet 生命週期:Servlet 加載--->實例化--->服務--->銷燬;
init():在Servlet的生命週期中,僅執行一次init()方法。它是在服務器裝入Servlet時執行的,負責初始化Servlet對象。能夠配置服務器,以在啓動服務器或客戶機首次訪問Servlet時裝入Servlet。
service():它是Servlet的核心,負責響應客戶的請求。每當一個客戶請求一個HttpServlet對象,該對象的Service()方法 就要調用,並且傳遞給這個方法一個「請求」(ServletRequest)對象和一個「響應」(ServletResponse)對象做爲參數。在 HttpServlet中已存在Service()方法。默認的服務功能是調用與HTTP請求的方法相應的do功能。
destroy(): 僅執行一次,在服務器端中止且卸載Servlet時執行該方法。當Servlet對象退出生命週期時,負責釋放佔用的資源。一個 Servlet在運行service()方法時可能會產生其餘的線程,所以須要確認在調用destroy()方法時,這些線程已經終止或完成。
Ajax:ajax負責客戶端與服務器直接聯繫,而不用jsp提交表單。通常ajax與servlet聯繫,也可直接與javabean聯繫
工做機制:客戶端請求提交到DispatcherServlet
由DispatcherServlet控制器查詢一個或多個HandlerMapping,找處處理請求的Controller
DispatcherServlet將請求提交到Controller
Controller調用業務邏輯處理後,返回ModelAndView
DispatcherServlet查詢一個或多個ViewResoler視圖解析器,找到ModelAndView指定的視圖
視圖負責將結果顯示到客戶端
視圖的好處:視圖對象的定義比實體定義還要簡單,不須要註解,不須要映射,可是惟一不一樣的是咱們須要額外構造一個帶有字段初始化的構造函數
1.Spring事務機制主要包括聲明式事務和編程式事務,使用最多的就是聲明式事務。聲明式事物是具備AOP來實現的,但你並不須要真正精通AOP技術也能掌握聲明式事務而編程式事物提供了一致的事務編程風格,經過模塊化操做一致性地管理事務。
2.在使用Spring聲明式事務時,有一個很是重要的概念就是事務屬性。事務屬性一般由事務的傳播行爲,事務的隔離級別,事務的超時值和事務只讀標誌組成。咱們在進行事務劃分時,須要進行事務定義,也就是配置事務的屬性:
Spring在TransactionDefinition接口中定義這些屬性,以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事務管理的核心接口。
使用JDBC的時候開啓事務使用Connection,而使用Hibernate時開啓事務使用的是Session。因此若是咱們使用傳統的事務編程策略時,程序代碼必須和具體的事務操做代碼耦合。這樣在不一樣的事務策略之間切換時開發者必須手動改代碼。而若是使用Spring來管理事務則不會出現這種狀況。
Spring事務策略是經過PlatformTransactionManager接口實現的,它是整個Spring事務的核心。它是對事務策略的一個高度抽象,不依賴於任何具體的事務策略,而對於底層的具體的事務策略它相應的有不一樣的實現類。而對於不一樣的事務策略的切換一般由Spring容器來負責管理,應用程序既無須與具體的事務API耦合,也無須與特定的實現類耦合而將應用和持久化技術,事務API完全分離開來。
Spring事務管理的策略模式體如今哪?PlatformTransactionManager表明事務管理接口,但它並不知道底層到底如何管理事務的,而它只要求事務管理提供開始事務(getTransaction(TransactionDefinition definition)),提交事務(commit())和回滾事務(rollback())三個方法,具體的實現交給子類來完成。
SQL 注入簡介:
SQL注入是最多見的攻擊方式之一,它不是利用操做系統或其它系統的漏洞來實現攻擊的,而是程序員由於沒有作好判斷,被不法用戶鑽了SQL的空子。
SQL注入攻擊的整體思路
1.尋找到SQL注入的位置;
2.判斷服務器類型和後臺數據庫類型;
3.針對不通的服務器和數據庫特色進行SQL注入攻擊。
下面咱們先來看下什麼是SQL注入:
好比在一個登錄界面,要求用戶輸入用戶名和密碼:
用戶名: ' or 1=1 --
密 碼:
點登錄,如若沒有作特殊處理,而只是一條帶條件的查詢語句如:
String sql="select * from users where username='"+userName+"' and password='"+password+"' "
那麼這個非法用戶就很得意的登錄進去了.(固然如今的有些語言的數據庫API已經處理了這些問題)
這是爲何呢?咱們來看看這條語句,將用戶輸入的數據替換後獲得這樣一條語句:
select * from users where username='' or 1=1 --' and password=''
爲了更明白些,能夠將其複製到SQL分析器中,將會發現,這條語句會將數據庫的數據所有讀出來,爲何呢?
很簡單,看到條件後面 username='' or 1=1 用戶名等於 '' 或 1=1 那麼這個條件必定會成功,而後後面加兩個-,這意味着什麼?沒錯,註釋,它將後面的語句註釋,讓他們不起做用,這樣就能夠順利的把數據庫中的數據讀取出來了。
這仍是比較溫柔的,若是是執行
select * from users where username='' ;DROP Database (DB Name) --' and password=''
.......其餘的您能夠本身想象。。。
那麼咱們怎麼來處理這種狀況呢?下面我以Java爲列給你們兩種簡單的方法:
第一種採用預編譯語句集,它內置了處理SQL注入的能力,只要使用它的setString方法傳值便可:
String sql= "select * from users where username=? and password=?;
PreparedStatement preState = conn.prepareStatement(sql);
preState.setString(1, userName);
preState.setString(2, password);
ResultSet rs = preState.executeQuery();
...
第二種是採用正則表達式,將包含有單引號('),分號(;) 和 註釋符號(--)的語句給替換掉來防止SQL注入
public static String TransactSQLInjection(String str)
{
return str.replaceAll(".*([';]+|(--)+).*", " ");
// 我認爲 應該是return str.replaceAll("([';])+|(--)+","");
}
userName=TransactSQLInjection(userName);
password=TransactSQLInjection(password);
悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認爲別人會修改,因此每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關係型數據庫裏邊就用到了不少這種鎖機制,好比行鎖,表鎖等,讀鎖,寫鎖等,都是在作操做以前先上鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認爲別人不會修改,因此不會上鎖,可是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,能夠使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣能夠提升吞吐量,像數據庫若是提供相似於write_condition機制的其實都是提供的樂觀鎖。
悲觀鎖
格式 SELECT…FOR UPDATE
例:select * from account where name="Erica" for update
這條 sql 語句鎖定了 account 表中全部符合檢索條件( name=「Erica」 )的記錄。 本次事務提交以前(事務提交時會釋放事務過程當中的鎖),外界沒法修改這些記錄。
格式 SELECT…FOR UPDATE NOWAIT
該關鍵字的含義是「不用等待,當即返回」,若是當前請求的資源被其餘會話鎖定時,會發生阻塞,nowait能夠避免這一阻塞。
樂觀鎖
樂觀鎖,大可能是基於數據版本 ( Version )記錄機制實現。何謂數據版本?即爲數據增長一個版本標識,在基於數據庫表的版本解決方案中,通常是經過爲數據庫表增長一個 「version」 字段來實現。
讀取出數據時,將此版本號一同讀出,以後更新時,對此版本號加一。此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,若是提交的數據版本號大於數據庫表當前版本號,則予以更新,不然認爲是過時數據。
總結:
兩種鎖各有優缺點,不可認爲一種好於另外一種,像樂觀鎖適用於寫比較少的狀況下,即衝突真的不多發生的時候,這樣能夠省去了鎖的開銷,加大了系統的整個吞吐量。但若是常常產生衝突,上層應用會不斷的進行retry,這樣反卻是下降了性能,因此這種狀況下用悲觀鎖就比較合適。
泛型是Java SE 1.5的新特性,泛型的本質是參數化類型,也就是說所操做的數據類型被指定爲一個參數。這種參數類型能夠用在類、接口和方法的建立中,分別稱爲泛型類、泛型接口、泛型方法。 Java語言引入泛型的好處是安全簡單。
在Java SE 1.5以前,沒有泛型的狀況的下,經過對類型Object的引用來實現參數的「任意化」,「任意化」帶來的缺點是要作顯式的強制類型轉換,而這種轉換是要求開發者對實際參數類型能夠預知的狀況下進行的。對於強制類型轉換錯誤的狀況,編譯器可能不提示錯誤,在運行的時候纔出現異常,這是一個安全隱患。
泛型的好處是在編譯的時候檢查類型安全,而且全部的強制轉換都是自動和隱式的,提升代碼的重用率。
一、泛型的類型參數只能是類類型(包括自定義類),不能是簡單類型。
二、同一種泛型能夠對應多個版本(由於參數類型是不肯定的),不一樣版本的泛型類實例是不兼容的。
三、泛型的類型參數能夠有多個。
四、泛型的參數類型能夠使用extends語句,例如<T extends superclass>。習慣上稱爲「有界類型」。
五、泛型的參數類型還能夠是通配符類型。例如Class<?> classType = Class.forName("java.lang.String");
泛型簡單易用
類型安全 泛型的主要目標是實現Java的類型安全。 泛型能夠使編譯器知道一個對象的限定類型是什麼,這樣編譯器就能夠在一個高的程度上驗證這個類型
消除了強制類型轉換 使得代碼可讀性好,減小了不少出錯的機會
泛型的實現是靠類型擦除技術 類型擦除是在編譯期完成的 也就是在編譯期 編譯器會將泛型的類型參數都擦除成它的限定類型,若是沒有則擦除爲object類型以後在獲取的時候再強制類型轉換爲對應的類型。 在運行期間並無泛型的任何信息,所以也沒有優化。
AVA的容器---List,Map,Set
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Collection接口
Collection是最基本的集合接口,一個Collection表明一組Object,即Collection的元素(Elements)。一些 Collection容許相同的元素而另外一些不行。一些能排序而另外一些不行。Java SDK不提供直接繼承自Collection的類,Java SDK提供的類都是繼承自Collection的「子接口」如List和Set。
全部實現Collection接口的類都必須提供兩個標準的構造函數:無參數的構造函數用於建立一個空的Collection,有一個 Collection參數的構造函數用於建立一個新的Collection,這個新的Collection與傳入的Collection有相同的元素。後一個構造函數容許用戶複製一個Collection。
如何遍歷Collection中的每個元素?不論Collection的實際類型如何,它都支持一個iterator()的方法,該方法返回一個迭代子,使用該迭代子便可逐一訪問Collection中每個元素。典型的用法以下:
Iterator it = collection.iterator(); // 得到一個迭代子
while(it.hasNext()) {
Object obj = it.next(); // 獲得下一個元素
}
由Collection接口派生的兩個接口是List和Set。
List接口
List是有序的Collection,使用此接口可以精確的控制每一個元素插入的位置。用戶可以使用索引(元素在List中的位置,相似於數組下標)來訪問List中的元素,這相似於Java的數組。
和下面要提到的Set不一樣,List容許有相同的元素。
除了具備Collection接口必備的iterator()方法外,List還提供一個listIterator()方法,返回一個 ListIterator接口,和標準的Iterator接口相比,ListIterator多了一些add()之類的方法,容許添加,刪除,設定元素,還能向前或向後遍歷。
實現List接口的經常使用類有LinkedList,ArrayList,Vector和Stack。
LinkedList類
LinkedList實現了List接口,容許null元素。此外LinkedList提供額外的get,remove,insert方法在 LinkedList的首部或尾部。這些操做使LinkedList可被用做堆棧(stack),隊列(queue)或雙向隊列(deque)。
注意LinkedList沒有同步方法。若是多個線程同時訪問一個List,則必須本身實現訪問同步。一種解決方法是在建立List時構造一個同步的List:
List list = Collections.synchronizedList(new LinkedList(...));
ArrayList類
ArrayList實現了可變大小的數組。它容許全部元素,包括null。ArrayList沒有同步。
size,isEmpty,get,set方法運行時間爲常數。可是add方法開銷爲分攤的常數,添加n個元素須要O(n)的時間。其餘的方法運行時間爲線性。
每一個ArrayList實例都有一個容量(Capacity),即用於存儲元素的數組的大小。這個容量可隨着不斷添加新元素而自動增長,可是增加算法並無定義。當須要插入大量元素時,在插入前能夠調用ensureCapacity方法來增長ArrayList的容量以提升插入效率。
和LinkedList同樣,ArrayList也是非同步的(unsynchronized)。
Vector類
Vector很是相似ArrayList,可是Vector是同步的。由Vector建立的Iterator,雖然和ArrayList建立的 Iterator是同一接口,可是,由於Vector是同步的,當一個Iterator被建立並且正在被使用,另外一個線程改變了Vector的狀態(例如,添加或刪除了一些元素),這時調用Iterator的方法時將拋出ConcurrentModificationException,所以必須捕獲該異常。
Stack 類
Stack繼承自Vector,實現一個後進先出的堆棧。Stack提供5個額外的方法使得Vector得以被看成堆棧使用。基本的push和pop 方法,還有peek方法獲得棧頂的元素,empty方法測試堆棧是否爲空,search方法檢測一個元素在堆棧中的位置。Stack剛建立後是空棧。
Set接口
Set是一種不包含重複的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
很明顯,Set的構造函數有一個約束條件,傳入的Collection參數不能包含重複的元素。
請注意:必須當心操做可變對象(Mutable Object)。若是一個Set中的可變元素改變了自身狀態致使Object.equals(Object)=true將致使一些問題。
Map接口
請注意,Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不能包含相同的key,每一個key只能映射一個 value。Map接口提供3種集合的視圖,Map的內容能夠被看成一組key集合,一組value集合,或者一組key-value映射。
Hashtable類
Hashtable繼承Map接口,實現一個key-value映射的哈希表。任何非空(non-null)的對象均可做爲key或者value。
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操做的時間開銷爲常數。
Hashtable經過initial capacity和load factor兩個參數調整性能。一般缺省的load factor 0.75較好地實現了時間和空間的均衡。增大load factor能夠節省空間但相應的查找時間將增大,這會影響像get和put這樣的操做。
使用Hashtable的簡單示例以下,將1,2,3放到Hashtable中,他們的key分別是」one」,」two」,」three」:
Hashtable numbers = new Hashtable();
numbers.put(「one」, new Integer(1));
numbers.put(「two」, new Integer(2));
numbers.put(「three」, new Integer(3));
要取出一個數,好比2,用相應的key:
Integer n = (Integer)numbers.get(「two」);
System.out.println(「two = 」 + n);
因爲做爲key的對象將經過計算其散列函數來肯定與之對應的value的位置,所以任何做爲key的對象都必須實現hashCode和equals方法。hashCode和equals方法繼承自根類Object,若是你用自定義的類看成key的話,要至關當心,按照散列函數的定義,若是兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但若是兩個對象不一樣,則它們的hashCode不必定不一樣,若是兩個不一樣對象的hashCode相同,這種現象稱爲衝突,衝突會致使操做哈希表的時間開銷增大,因此儘可能定義好的hashCode()方法,能加快哈希表的操做。
若是相同的對象有不一樣的hashCode,對哈希表的操做會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只須要牢記一條:要同時複寫equals方法和hashCode方法,而不要只寫其中一個。
Hashtable是同步的。
HashMap類
HashMap和Hashtable相似,不一樣之處在於HashMap是非同步的,而且容許null,即null value和null key。,可是將HashMap視爲Collection時(values()方法可返回Collection),其迭代子操做時間開銷和HashMap 的容量成比例。所以,若是迭代操做的性能至關重要的話,不要將HashMap的初始化容量設得太高,或者load factor太低。
WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行「弱引用」,若是一個key再也不被外部所引用,那麼該key能夠被GC回收。
總結
若是涉及到堆棧,隊列等操做,應該考慮用List,對於須要快速插入,刪除元素,應該使用LinkedList,若是須要快速隨機訪問元素,應該使用ArrayList。
若是程序在單線程環境中,或者訪問僅僅在一個線程中進行,考慮非同步的類,其效率較高,若是多個線程可能同時操做一個類,應該使用同步的類。
要特別注意對哈希表的操做,做爲key的對象要正確複寫equals和hashCode方法。
儘可能返回接口而非實際的類型,如返回List而非ArrayList,這樣若是之後須要將ArrayList換成LinkedList時,客戶端代碼不用改變。這就是針對抽象編程。
Java 集合類 map set list arraylist hashmap hashtable(轉)
Vector的方法都是同步的(Synchronized),是線程安全的(thread-safe),而ArrayList的方法不是,因爲線程的同步必然要影響性能,所以,ArrayList的性能比Vector好。
當Vector或ArrayList中的元素超過它的初始大小時,Vector會將它的容量翻倍,而ArrayList只增長50%的大小,這樣,ArrayList就有利於節約內存空間。
Hashtable和HashMap
它們的性能方面的比較相似 Vector和ArrayList,好比Hashtable的方法是同步的,而HashMap的不是。
ArrayList和LinkedList
對 於處理一列數據項,Java提供了兩個類ArrayList和LinkedList,ArrayList的內部實現是基於內部數組Object[],因此 從概念上講,它更象數組,但LinkedList的內部實現是基於一組鏈接的記錄,因此,它更象一個鏈表結構,因此,它們在性能上有很大的差異。
(1) 從上面的分析可知,在ArrayList的前面或中間插入數據時,你必須將其後的全部數據相應的後移,這樣必然要花費較多時間,因此,當你的操做是在一列 數據的後面添加數據而不是在前面或中間,而且須要隨機地訪問其中的元素時,使用ArrayList會提供比較好的性能。
(2)而訪問鏈表中的某個元素時,就必須從鏈表的一端開始沿着鏈接方向一個一個元素地去查找,直到找到所需的元素爲止,因此,當你的操做是在一列數據的前面或中間添加或刪除數據,而且按照順序訪問其中的元素時,就應該使用LinkedList了。
(3)若是在編程中,1,2兩種情形交替出現,這時,你能夠考慮使用List這樣的通用接口,而不用關心具體的實現,在具體的情形下,它的性能由具體的實現來保證。
設置集合類的初始大小
在Java 集合框架中的大部分類的大小是能夠隨着元素個數的增長而相應的增長的,咱們彷佛不用關心它的初始大小,但若是咱們考慮類的性能問題時,就必定要考慮儘量 地設置好集合對象的初始大小,這將大大提升代碼的性能,好比,Hashtable缺省的初始大小爲101,載入因子爲0.75,即若是其中的元素個數超過 75個,它就必須增長大小並從新組織元素,因此,若是你知道在建立一個新的Hashtable對象時就知道元素的確切數目如爲110,那麼,就應將其初始 大小設爲110/0.75=148,這樣,就能夠避免從新組織內存並增長大小。
2六、錯誤和異常的區別(Error vs Exception)
1) java.lang.Error: Throwable的子類,用於標記嚴重錯誤。合理的應用程序不該該去try/catch這種錯誤。絕大多數的錯誤都是非正常的,就根本不應出現的。
java.lang.Exception: Throwable的子類,用於指示一種合理的程序想去catch的條件。即它僅僅是一種程序運行條件,而非嚴重錯誤,而且鼓勵用戶程序去catch它。
2) Error和RuntimeException 及其子類都是未檢查的異常(unchecked exceptions),而全部其餘的Exception類都是檢查了的異常(checked exceptions).
checked exceptions: 一般是從一個能夠恢復的程序中拋出來的,而且最好可以從這種異常中使用程序恢復。好比FileNotFoundException, ParseException等。檢查了的異常發生在編譯階段,必需要使用try…catch(或者throws)不然編譯不經過。
unchecked exceptions: 一般是若是一切正常的話本不應發生的異常,可是的確發生了。發生在運行期,具備不肯定性,主要是因爲程序的邏輯問題所引發的。好比ArrayIndexOutOfBoundException, ClassCastException等。從語言自己的角度講,程序不應去catch這類異常,雖然可以從諸如RuntimeException這樣的異常中catch並恢復,可是並不鼓勵終端程序員這麼作,由於徹底沒要必要。由於這類錯誤自己就是bug,應該被修復,出現此類錯誤時程序就應該當即中止執行。 所以,面對Errors和unchecked exceptions應該讓程序自動終止執行,程序員不應作諸如try/catch這樣的事情,而是應該查明緣由,修改代碼邏輯。
RuntimeException:RuntimeException體系包括錯誤的類型轉換、數組越界訪問和試圖訪問空指針等等。
處理RuntimeException的原則是:若是出現 RuntimeException,那麼必定是程序員的錯誤。例如,能夠經過檢查數組下標和數組邊界來避免數組越界訪問異常。其餘(IOException等等)checked異常通常是外部錯誤,例如試圖從文件尾後讀取數據等,這並非程序自己的錯誤,而是在應用環境中出現的外部錯誤。
Java的線程是經過java.lang.Thread類來實現的。VM啓動時會有一個由主方法所定義的線程。能夠經過建立Thread的實例來建立新的線程。每一個線程都是經過某個特定Thread對象所對應的方法run()來完成其操做的,方法run()稱爲線程體。經過調用Thread類的start()方法來啓動一個線程。
在Java當中,線程一般都有五種狀態,建立、就緒、運行、阻塞和死亡。
第一是建立狀態。在生成線程對象,並無調用該對象的start方法,這是線程處於建立狀態。
第二是就緒狀態。當調用了線程對象的start方法以後,該線程就進入了就緒狀態,可是此時線程調度程序尚未把該線程設置爲當前線程,此時處於就緒狀態。在線程運行以後,從等待或者睡眠中回來以後,也會處於就緒狀態。
第三是運行狀態。線程調度程序將處於就緒狀態的線程設置爲當前線程,此時線程就進入了運行狀態,開始運行run函數當中的代碼。
第四是阻塞狀態。線程正在運行的時候,被暫停,一般是爲了等待某個時間的發生(好比說某項資源就緒)以後再繼續運行。sleep,suspend,wait等方法均可以致使線程阻塞。
第五是死亡狀態。若是一個線程的run方法執行結束或者調用stop方法後,該線程就會死亡。對於已經死亡的線程,沒法再使用start方法令其進入就緒。
Thread Test = new Thread();
Test.start();
二、寫一個類實現Runnable接口,實現run方法。用new Thread(Runnable target).start()方法來啓動Test impelements Runnable;
Test t = new Test();
Thread test = new Thread(t);
test.start();
start()和run()方法的區別
1) start:
用start方法來啓動線程,真正實現了多線程運行,這時無需等待run方法體代碼執行完畢而直接繼續執行下面的代碼。經過調用Thread類的 start()方法來啓動一個線程,這時此線程處於就緒(可運行)狀態,並無運行,一旦獲得cpu時間片,就開始執行run()方法,這裏方法 run()稱爲線程體,它包含了要執行的這個線程的內容,Run方法運行結束,此線程隨即終止。
2) run:
run()方法只是類的一個普通方法而已,若是直接調用Run方法,程序中依然只有主線程這一個線程,其程序執行路徑仍是隻有一條,仍是要順序執行,仍是要等待run方法體執行完畢後纔可繼續執行下面的代碼,這樣就沒有達到寫線程的目的。
總結:調用start方法方可啓動線程,而run方法只是thread的一個普通方法調用,仍是在主線程裏執行。
這兩個方法應該都比較熟悉,把須要並行處理的代碼放在run()方法中,start()方法啓動線程將自動調用 run()方法,這是由jvm的內存機制規定的。而且run()方法必須是public訪問權限,返回值類型爲void。
答案:不能
解析:volatile關鍵字用在多線程同步中,可保證讀取的可見性,JVM只是保證從主內存加載到線程工做內存的值是最新的讀取值,而非cache中。但多個線程對
volatile的寫操做,沒法保證線程安全。例如假如線程1,線程2 在進行read,load 操做中,發現主內存中count的值都是5,那麼都會加載這個最新的值,在線程1堆count進行修改以後,會write到主內存中,主內存中的count變量就會變爲6;線程2因爲已經進行read,load操做,在進行運算以後,也會更新主內存count的變量值爲6;致使兩個線程及時用volatile關鍵字修改以後,仍是會存在併發的狀況。
A 是 B 否
答案:A
解析:Java建立對象的幾種方式(重要):
(1) 用new語句建立對象,這是最多見的建立對象的方法。
(2) 運用反射手段,調用java.lang.Class或者java.lang.reflect.Constructor類的newInstance()實例方法。
(3) 調用對象的clone()方法。
(4) 運用反序列化手段,調用java.io.ObjectInputStream對象的 readObject()方法。
(1)和(2)都會明確的顯式的調用構造函數 ;(3)是在內存上對已有對象的影印,因此不會調用構造函數 ;(4)是從文件中還原類的對象,也不會調用構造函數。
3一、
下面哪些是對稱加密算法()
A DES B AES C DSA D RSA
答案:AB
解析:經常使用的對稱加密算法有:DES、3DES、RC二、RC四、AES
經常使用的非對稱加密算法有:RSA、DSA、ECC
使用單向散列函數的加密算法:MD五、SHA
3二、抽象類和接口
抽象類遵循的原則:
(1)接口是公開的,裏面不能有私有的方法或變量,是用於讓別人使用的,而抽象類是能夠有私有方法或私有變量的。
(2)abstract class 在 Java 語言中表示的是一種繼承關係,一個類只能使用一次繼承關係。可是,一個類卻能夠實現多個interface,實現多重繼承。接口還有標識(裏面沒有任何方法,如Remote接口)和數據共享(裏面的變量全是常量)的做用。
(3)在abstract class 中能夠有本身的數據成員,也能夠有非abstarct的成員方法,而在interface中,只可以有靜態的不能被修改的數據成員(也就是必須是 static final的,不過在 interface中通常不定義數據成員),全部的成員方法默認都是 public abstract 類型的。
(4)abstract class和interface所反映出的設計理念不一樣。其實abstract class表示的是"is-a"關係,interface表示的是"has-a"關係。
(5)實現接口的必定要實現接口裏定義的全部方法,而實現抽象類能夠有選擇地重寫須要用到的方法,通常的應用裏,最頂級的是接口,而後是抽象類實現接口,最後纔到具體類實現。抽象類中能夠有非抽象方法。接口中則不能有實現方法。
(6)接口中定義的變量默認是public static final 型,且必須給其初值,因此實現類中不能從新定義,也不能改變其值。抽象類中的變量默認是 friendly 型,其值能夠在子類中從新定義,也能夠在子類中從新賦值。
Java提供和支持建立抽象類和接口。它們的實現有共同點,不一樣點在於:
3三、同步方法和同步代碼塊的區別是什麼?
在Java語言中,每個對象有一把鎖。線程能夠使用synchronized關鍵字來獲取對象上的鎖。synchronized關鍵字可應用在方法級別(粗粒度鎖)或者是代碼塊級別(細粒度鎖)。
3四、如何確保N個線程能夠訪問N個資源同時又不致使死鎖?
使用多線程的時候,一種很是簡單的避免死鎖的方式就是:指定獲取鎖的順序,並強制線程按照指定的順序獲取鎖。所以,若是全部的線程都是以一樣的順序加鎖和釋放鎖,就不會出現死鎖了。
3五、數組(Array)和列表(ArrayList)有什麼區別?何時應該使用Array而不是ArrayList?
下面列出了Array和ArrayList的不一樣點:
ArrayList和LinkedList有什麼區別?
ArrayList和LinkedList都實現了List接口,他們有如下的不一樣點:
ArrayList是基於索引的數據接口,它的底層是數組。它能夠以O(1)時間複雜度對元素進行隨機訪問。與此對應,LinkedList是以元素列表的形式存儲它的數據,每個元素都和它的前一個和後一個元素連接在一塊兒,在這種狀況下,查找某個元素的時間複雜度是O(n)。
相對於ArrayList,LinkedList的插入,添加,刪除操做速度更快,由於當元素被添加到集合任意位置的時候,不須要像數組那樣從新計算大小或者是更新索引。
LinkedList比ArrayList更佔內存,由於LinkedList爲每個節點存儲了兩個引用,一個指向前一個元素,一個指向下一個元素。
3六、多線程的安全問題
總結來講,多個線程在執行同一段代碼的時候,每次的執行結果和單線程執行的結果都是同樣的,不存在執行結果的二義性,就能夠稱做是線程安全的。線程安全問 題可能是由全局變量和靜態變量引發的,當多個線程對共享數據只執行讀操做,不執行寫操做時,通常是線程安全的;當多個線程都執行寫操做時,須要考慮線程同步來解決線程安全問題。
說明Java線程的兩個特性,可見性和有序性。多個線程之間是不能直接傳遞數據交互的,它們之間的交互只能經過共享變量來實現。
java容許多線程併發控制,當多個線程同時操做一個可共享的資源變量時(如數據的增刪改查),將會致使數據不許確,相互之間產生衝突,所以加入同步鎖以免在該線程沒有完成操做以前,被其餘線程的調用, 從而保證了該變量的惟一性和準確性
3七、java常見的數據類型是什麼和對應的包裝類是什麼?java的隱式類型?assert何時使用?
(1)int, double, float, long, short, boolean, byte, char
(2)Integer.Double,Float,Long,Short,Boolean,Byte,Characher.
(3)java的隱式類型是int,byte,short,char均可以隱含轉換爲int
(4)通常來講,assertion用於保證程序最基本、關鍵的正確性。assertion檢查一般在開發和測試時開啓。爲了提升性能,在軟件發佈後,assertion檢查一般是關閉的;
3八、線程中sleep和wait的區別
(1)這兩個方法來自不一樣的類分別是,sleep來自Thread類,和wait來自Object類;sleep是Thread的靜態類方法,誰調用的誰去睡覺,即便在a線程裏調用了b的sleep方法,實際上仍是a去睡覺,要讓b線程睡覺要在b的代碼中調用sleep。
(2)最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其餘線程能夠使用同步控制塊或者方法。sleep不出讓系統資源;wait是進入線程等待池等待,出讓系統資源,其餘線程能夠佔用CPU。通常wait不會加時間限制,由於若是wait線程的運行資源不夠,再出來也沒用,要等待其餘線程調用notify/notifyAll喚醒等待池中的全部線程,纔會進入就緒隊列等待OS分配系統資源。 sleep(milliseconds)能夠用時間指定使它自動喚醒過來,若是時間不到只能調用interrupt()強行打斷;
3九、string、stringbuffer和stringbuilder的區別?哪一個更安全?爲何?hashmap爲何查詢的比較快?
(1)JAVA平臺提供了兩個類:String和StringBuffer,它們能夠儲存和操做字符串,即包含多個字符的字符數據。這個String類提供了數值不可改變的字符串。而這個StringBuffer類提供的字符串進行修改。當你知道字符數據要改變的時候你就能夠使用StringBuffer。典型地,你能夠使用StringBuffer來動態構造字符數據。另外,String實現了equals方法;而StringBuffer沒有實現equals方法,因此,new StringBuffer(「abc」).equals(new StringBuffer(「abc」)的結果爲false。
(2)StringBuffer線程安全的可變字符序列。一個相似於 String 的字符串緩衝區,但不能修改;經過某些方法調用能夠改變該序列的長度和內容,可將字符串緩衝區安全地用於多個線程。能夠在必要時對這些方法進行同步,所以任意特定實例上的全部操做就好像是以串行順序發生的,該順序與所涉及的每一個線程進行的方法調用順序一致;
(3)StringBuilder一個可變的字符序列。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用做 StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候(這種狀況很廣泛)。(若是可能,建議優先採用該類,由於在大多數實現中,它比 StringBuffer 要快。但將 StringBuilder 的實例用於多個線程是不安全的。若是須要這樣的同步,則建議使用 StringBuffer。);
(4)HashMap是Hashtable的輕量級實現(非同步非線程安全的實現),他們都完成了Map接口,主要區別在於HashMap容許空(null)鍵值(key),因爲非線程安全,在只有一個線程訪問的狀況下,效率要高於Hashtable。
40、hibernat和mybaitis的優點和區別?haibernate的緩存機制有沒有了解過?如何使用hibernate將數據永久保存到數據庫中?mybaitates是如何實現查詢的?hibernate有不少數據操做時候如何優化?
(1)mybaitis的優點:
· MyBatis能夠進行更爲細緻的SQL優化,能夠減小查詢字段。
· MyBatis容易掌握,而Hibernate門檻較高。
(2)hibernate的優點:
· Hibernate的DAO層開發比MyBatis簡單,Mybatis須要維護SQL和結果映射;
· Hibernate對對象的維護和緩存要比MyBatis好,對增刪改查的對象的維護要方便;
· Hibernate數據庫移植性很好,MyBatis的數據庫移植性很差,不一樣的數據庫須要寫不一樣SQL。
· Hibernate有更好的二級緩存機制,能夠使用第三方緩存。MyBatis自己提供的緩存機制不佳。
(3)區別:Hibernate功能強大,數據庫無關性好,O/R映射能力強,若是你對Hibernate至關精通,並且對Hibernate進行了適當的封裝,那麼你的項目整個持久層代碼會至關簡單,須要寫的代碼不多,開發速度很快,很是爽。· iBATIS入門簡單,即學即用,提供了數據庫查詢的自動對象綁定功能,並且延續了很好的SQL使用經驗,對於沒有那麼高的對象模型要求的項目來講,至關完美。
(4)Hibernate一級緩存是Session緩存,利用好一級緩存就須要對Session的生命週期進行管理好。建議在一個Action操做中使用一個Session。一級緩存須要對Session進行嚴格管理。Hibernate二級緩存是SessionFactory級的緩存。 SessionFactory的緩存分爲內置緩存和外置緩存。內置緩存中存放的是SessionFactory對象的一些集合屬性包含的數據(映射元素據及預約SQL語句等),對於應用程序來講,它是隻讀的。外置緩存中存放的是數據庫數據的副本,其做用和一級緩存相似.二級緩存除了之內存做爲存儲介質外,還能夠選用硬盤等外部存儲設備。二級緩存稱爲進程級緩存或SessionFactory級緩存,它能夠被全部session共享,它的生命週期伴隨着SessionFactory的生命週期存在和消亡。
(5)mybatitis的查詢:Mybatis的SQL是手動編寫的,因此能夠按需求指定查詢的字段。mybatis是數據映射器(數據映射器層:用於在對象和數據庫之間搬運數據,同時保證對象、數據庫和數據映射器層自己相對獨立。Martin Fowler 《企業應用架構模式》)把sql語句的參數與結果(即輸入與輸出)映射爲類。爲如何在類和數據庫間創建映射帶來了更大的靈活性。同時也更好的隔離了數據庫設計和應用程序中使用的對象模型。
(6)hibernate 的持久化:Hibernate採用了更天然的面向對象的視角來持久化 Java 應用中的數據。使用 Hibernate 的開發者應該老是關注對象的狀態(state),沒必要考慮 SQL 語句的執行。這部分細節已經由 Hibernate 掌管穩當,只有開發者在進行系統性能調優的時候才須要進行了解。
(6)mybatis的調優:MyBatis在Session方面和Hibernate的Session生命週期是一致的,一樣須要合理的Session管理機制。MyBatis一樣具備二級緩存機制。 MyBatis能夠進行詳細的SQL優化設計。
(7)hibernate如何實現優化:
· 制定合理的緩存策略;
· 儘可能使用延遲加載特性;
· 採用合理的Session管理機制;
· 使用批量抓取,設定合理的批處理參數(batch_size);
· 進行合理的O/R映射設計
4一、spring、hibernate、Struts的工做原理,爲何使用這些框架?簡單說下struts2中數據傳遞狀況? hibernate的三種狀態和彼此的區別?使用hibernate如何分頁?spring的事務隔離級別?ssh如何整合(spring核心流程)?
(1)spring的工做原理:
I.Spring內部最核心的就是IOC了,動態注入,讓一個對象的建立不用new了,能夠自動的生產,這其實就是利用java裏的反射,反射其實就是在運行時動態的去建立、調用對象,Spring就是在運行時,根據xml Spring的配置文件來動態的建立對象,和調用對象裏的方法。
II.Spring工做原理還有一個核心就是Aop這個就是面向切面的編程,能夠爲某一類對象進行監督和控制(也就是在調用這類對象的具體方法的先後去調用你指定的模塊)從而達到對一個模塊擴充的功能這些都是經過配置類達到的。
III.Spring目的:就是讓對象與對象(模塊與模塊)之間的關係沒有經過代碼來關聯,都是經過配置類說明管理的(主要是經過反射機制)。
(2)hibernate的工做原理:
I.讀取並解析hibernate.cfg.xml配置文件
II.讀取並解析映射信息
III.建立SessionFactory
IV.負責被持久化對象CRUD操做,打開Sesssion
V.建立並啓動事務Transation
VI.操做數據,持久化操做
VII.提交事務,關閉Session,關閉SesstionFactory;
(3)struts的工做原理同下:
工做流程:
(1)客戶端提交一個HttpServletRequest請求(action或JSP頁面)。
(2)請求被提交到一系列Filter過濾器,如ActionCleanUp和FilterDispatcher等。
(3)FilterDispatcher是Struts2控制器的核心,它一般是過濾器鏈中的最後一個過濾器.
(4)請求被髮送到FilterDispatcher後,FilterDispatcher詢問ActionMapper時候須要調用某個action來處理這個Request。
(5)若是ActionMapper決定須要調用某個action,FilterDispatcher則把請求交給ActionProxy進行處理.
(6)ActionProxy經過Configuration Manager詢問框架的配置文件struts.xml,找到調用的action類。
(7)ActionProxy建立一個ActionInvocation實例,經過代理模式調用Action。
(8)action執行完畢後,返回一個result字符串,此時再按相反的順序經過Intercepter攔截器。
(9)最後ActionInvocation實例,負責根據struts.xml中配置result元素,找到與之相對應的result,決定進一步輸出。
簡要基本流程:
I.客戶端瀏覽器發出HTTP請求。II.根據web.xml配置,該請求被FilterDispatcher接收。III.根據struts.xml配置,找到須要調用的Action類和方法, 並經過IoC方式,將值注入給Aciton。IV.Action調用業務邏輯組件處理業務邏輯,這一步包含表單驗證。V.Action執行完畢,根據struts.xml中的配置找到對應的返回結果result,並跳轉到相應頁面。VI.返回HTTP響應到客戶端瀏覽器。
(4)使用緣由:
struts是開源軟件。使用Struts的目的是爲了幫助咱們減小在運用MVC設計模型來開發Web應用的時間。若是咱們想混合使用Servlets和JSP的優勢來創建可擴展的應用,struts是一個不錯的選擇。
Hibernate是一個開放源代碼的對象關係映射框架,它對JDBC進行了很是輕量級的對象封裝,使得Java程序員能夠爲所欲爲的使用對象編程思惟來操縱數據庫。 Hibernate能夠應用在任何使用JDBC的場合,既能夠在Java的客戶端程序使用,也能夠在Servlet/JSP的Web應用中使用,最具革命意義的是,Hibernate能夠在應用EJB的J2EE架構中取代CMP,完成數據持久化的重任;
Spring:Spring是一個開源框架,它是爲了解決企業應用開發的複雜性而建立的。Spring使用基本的JavaBean來完成之前只可能由EJB完成的事情。然而,Spring的用途不只限於服務器端的開發。從簡單性、可測試性和鬆耦合的角度而言,任何Java應用均可以從Spring中受益.
(5)struts數據傳遞:能夠直接基於應用程序域對象轉移,驗證數據,數據綁定,動做把從請求接收到的全部數據放在簡單的JavaBean上。除了單獨接受每一個數 據,struts2最優雅的地方時能夠建立一個對象來放置這些瑣碎的數據,咱們能夠把複雜對象自己提供給平臺的數據轉移機制。這不但節省時間,並且也能節 省工做量。
(6)hibernate的三種狀態和區別:
瞬時(transient):也叫自由狀態.數據庫中沒有數據與之對應,超過做用域會被JVM垃圾回收器回收,通常是new出來且與session沒有關聯的對象。
持久(persistent):數據庫中可能有數據與之對應(save),當前與session有關聯,而且相關聯的session沒有關閉,事務沒有提交;持久對象狀態發生改變,在事務提交時會影響到數據庫(hibernate能檢測到)。
脫管(detached):也叫遊離狀態.數據庫中可能有數據與之對應,但當前沒有session與之關聯,可是有oid;託管對象狀態發生改變,hibernate不能檢測到。
區別:Transient狀態的實體缺少與數據庫表記錄之間的聯繫,而Detached狀態的實體偏偏相反.只不過是脫離了session這個數據庫操做平臺而已.
(7)hibernate分頁:1.HQL查詢:Query query=session.createQuery(from 實體類);2.從第幾條開始:query.setFirstResult(mini);3.每次最多提取多少條數據:query.setMaxResults(max);接收返回的結果集:List<實體類> HousesList=query.list();
代碼以下(Query query = session.createQuery(hql);
query.setParameter(0, userId);
query.setMaxResults(maxCount);
query.setFirstResult(firstResult);
return query.list();
)
(8)ssh整合步驟:
1.導入struts2的jar包以及struts2-spring-plugin-2.0.11.2.jar;
2.在web.xml中分別配置struts2與spring相關信息;
3.struts中原有的Action須要繼承ActionSupport;
4.在Spring配置Action Bean;
5.在Struts2的配置文件中,調用Spring中配置的Bean;
6.Spring與Hibernate整合,只須要在Spring配置文件配置SessionFactory便可
(9)Spring的隔離級別:Default默認的事務隔離級別
READ_UNCOMMITTED讀未提交,一個事務能夠操做另一個未提交的事務,不能避免髒讀,不可重複讀,幻讀,隔離級別最低,併發性 能最高
READ_COMMITTED讀已提交,一個事務不能夠操做另一個未提交的事務, 能防止髒讀,不能避免不可重複讀,幻讀。
repeatable_read可以避免髒讀,不可重複讀,不能避免幻讀
SERIALIZABLE隔離級別最高,消耗資源最低,代價最高,可以防止髒讀, 不可重複讀,幻讀。
4二、談談Spring和Spring MVC的流程和事務;spring配置文件都寫什麼?
(1)spring提供兩種管理事務的方式:一種是聲明式事務,一種是編程式事務。
Spring的聲明式事務管理,基於Spring的AOP,基於Spring AOP實現,幾乎就是xml文件的配置,再也不須要不停地寫commit,rollback,(但Spring仍然沒有放棄編程式的事務管理策略)。
Spring的編程式事務管理,統一的事務編碼風格,幾乎是一個模板化的。
爲咱們提供了一個TransactionTemplate,使用回調機制,將應用代碼從樣板式的資源獲取和釋放代碼中解放出來,再也不有大量的try/catch/finally/try/catch代碼塊
(2)springMVC的流程和事務:動態注入,讓一個對象的建立不用new了,能夠自動的生產,這其實就是利用java裏的反射 ,反射其實就是在運行時動態的去建立、調用對象,Spring就是在運行時,跟xml Spring的配置文件來動態的建立對象,和調用對象裏的方法的 。
Spring還有一個核心就是AOP這個就是面向切面編程,能夠爲某一類對象 進行監督和控制(也就是在調用這類對象的具體方法的先後去調用你指定的 模塊)從而達到對一個模塊擴充的功能。這些都是經過 配置類達到的。Spring目的:就是讓對象與對象(模塊與模塊)之間的關係沒有經過代碼來關聯,都是經過配置類說明管理的(Spring根據這些配置 內部經過反射去動態的組裝對象)
要記住:Spring是一個容器,凡是在容器裏的對象纔會有Spring所提供的這些服務和功能。
(3)spring的配置文件:1、引用外部屬性文件;2、經常使用數據源的配置;3、配置事務管理器;4、context:component-scan<!-- 對包中的全部類進行掃描,以完成Bean建立和自動依賴注入的功能 -->;5、aop註解支持;6、緩存配置;7、<!-- Spring、MyBatis的整合,須要在 Spring 應用上下文中定義至少兩樣東西:一個SqlSessionFactory和至少一個數據映射器類(UserMapper->iocContext.xml)。 -->;
4三、SSH和SSM的區別
(1)基於MVC三層架構,使用ssh框架 or ssm框架 or ssi框架,採用面向接口的方式編程。
共同點是struts、spring,不一樣點是hibernate和mybatis、ibatis。
(2)相對Hibernate「O/R」而言,iBATIS 是一種「Sql Mapping」的ORM實現。
(3)因爲hibernate是徹底面向對象的編程,在實現dao中就很是的方便,並且不重複;當mybatis在.java代碼中也是能夠作到不重複,麻煩一點的是,每一個映射文件都必須編寫幾乎相同的配置,除了resultType不同。
(4)hibernate在實際編程中能夠把基礎的CRUD封裝,好比BaseDao類。其它類只要去繼承BaseDao就能執行全部的基礎的CRUD。這樣就很是方便。這個帶來的好處還有,能夠創建BaseService和BaseAction。
因爲mybatis的映射文件中,雖然SQL語句中的表名能夠經過parameterType指定,可是resultType必須定死,不能以參數 的形式給予指定。致使的結果就是全部的DAO類的每一個CRUD都必須和指定的映射文件綁定在一塊兒,以致於不可能存在BaseDao類。固然也就不能創建 BaseService和BaseAction。
4四、數據庫對象關係映射
1.對「對象關係映射」的理解
[java]
Department
int
id;
String
name
;
Set
employees=new HashSet();
Employee
int
id;
String
name
;
Department dept;
[sql]
create
department(
id
int
primary
key
,
name
varchar
(20)
);
[sql]
create
employee(
id
int
primary
key
,
name
varchar
(20),
dept_id
int
,
constraint
dept_id_FK
foreign
key
(dept_id)
references
department(id)
);
[sql]
create
table
teacher(
id
int
primary
key
,
name
varchar
(20)
);
create
table
student(
id
int
primary
key
,
name
varchar
(20)
);
[sql]
create
table
student_teacher(
student_id
int
,
teacher_id
int
,
constraint
student_teacher_PK
primary
key
(student_id,teacher_id),
constraint
student_id_FK
foreign
key
(student_id)
references
student(id),
constraint
teacher_id_FK
foreign
key
(teacher_id)
references
teacher(id)
);
[java]
Person
int
id;
String
name
;
IdCard ic;
IdCard
int
id;
String address;
[sql]
create
table
person(
id
int
primary
key
,
name
varchar
(20)
);
create
table
idcard(
id
int
primary
key
,
address
varchar
(40),
constraint
id_FK
foreign
key
(id)
references
person(id)
);
注:對於一對一關係的兩張表,分主表與從表,從表的存在必須依賴於主表,主表能夠不依賴於從表。從表的設計上其主鍵字段同時也是外鍵字段。
備註:有時在設計表時,會特地把兩張表合在一張表中,雖然會形成數據冗餘,可是卻能夠不由於聯表查詢而形成查詢性能有所下降。這是用空間來換時間的作法。
線程安全
若是你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。若是每次運行結果和單線程運行的結果是同樣的,並且其餘的變量的值也和預期的是同樣的,就是線程安全的。 或者說:一個類或者程序所提供的接口對於線程來講是原子操做或者多個線程之間的切換不會致使該接口的執行結果存在二義性,也就是說咱們不用考慮同步的問題。 線程安全問題都是由全局變量及靜態變量引發的。
若每一個線程中對全局變量、靜態變量只有讀操做,而無寫操做,通常來講,這個全局變量是線程安全的;如有多個線程同時執行寫操做,通常都須要考慮線程同步,不然就可能影響線程安全。
關於線程安全:
1) 常量始終是線程安全的,由於只存在讀操做。
2)每次調用方法前都新建一個實例是線程安全的,由於不會訪問共享的資源。
3)局部變量是線程安全的。由於每執行一個方法,都會在獨立的空間建立局部變量,它不是共享的資源。局部變量包括方法的參數變量和方法內變量。
有狀態和無狀態對象
有狀態就是有數據存儲功能。有狀態對象(Stateful Bean),就是有實例變量的對象 ,能夠保存數據,是非線程安全的。在不一樣方法調用間不保留任何狀態。
無狀態就是一次操做,不能保存數據。無狀態對象(Stateless Bean),就是沒有實例變量的對象 .不能保存數據,是不變類,是線程安全的。
無狀態對象通常沒有實例變量,或者有實例變量,不能改寫,如private的,對外只暴露只讀操做,無寫操做。
單例類能夠是有狀態的(stateful),也能夠是無狀態的。無狀態的單例模式,是線程安全的。有狀態的單例模式,是非線程安全的。
spring中的有狀態(Stateful)和無狀態(Stateless)
1.經過上面的分析,相信你們已經對有狀態和無狀態有了必定的理解。無狀態的Bean適合用不變模式,技術就是單例模式,這樣能夠共享實例,提升性能。有狀態的Bean,多線程環境下不安全,那麼適合用Prototype原型模式。Prototype: 每次對bean的請求都會建立一個新的bean實例。
2.默認狀況下,從Spring bean工廠所取得的實例爲singleton(scope屬性爲singleton),容器只存在一個共享的bean實例。
3.理解了二者的關係,那麼scope選擇的原則就很容易了:有狀態的bean都使用prototype做用域,而對無狀態的bean則應該使用singleton做用域。
4.如Service層、Dao層用默認singleton就行,雖然Service類也有dao這樣的屬性,但dao這些類都是沒有狀態信息的,也就是 至關於不變(immutable)類,因此不影響。Struts2中的Action由於會有User、BizEntity這樣的實例對象,是有狀態信息 的,在多線程環境下是不安全的,因此Struts2默認的實現是Prototype模式。在Spring中,Struts2的Action中,scope 要配成prototype做用域。
4六、
4七、
4八、
4九、
50、