我所據說過的技術名詞總結:java
1.熟悉的:Java、SVN、Maven、Agile、Scrum、Spring、mysql
2.正在瞭解的:Jetty、MongoDB、redis、Lucene、程序員
3.不熟悉的:Autonomy、Quova、面試
4.工具:Eclipse、MyEclipse、Navicat、Plsql、springsourcetoolsuite、redis
須要鞏固的知識:Spring、SpringMVC、Mybatis;Java、Mysql、Oracle、HTML、CSS、JS算法
須要瞭解的東西:HTTP協議、單元測試技術、J2EE體系結構、高併發大數據量的項目瞭解spring
第一部分:Mysql和Oracle面試問題總結sql
varchar與char的區別,char是一種固定長度的類型,varchar則是一種可變長度的類型。數據庫
varchar(50)中50的涵義,最多存放50個字節。服務器
事務是如何經過日誌來實現的。隔離性: 經過 鎖 實現。原子性、一致性和持久性是經過 redo和undo來完成的。
// 你如何肯定 MySQL 是否處於運行狀態?
命令:service mysql status
//如何開啓或中止 MySQL 服務?
命令:service mysqld start || service mysqld stop
//如何經過 Shell 登入 MySQL?
命令:mysql -u root -p
//如何列出全部數據庫?
命令:show databases;
//如何切換到某個數據庫並在上面工做?
命令:use database_name;
//如何列出某個數據庫內全部表?
命令:show tables;
//刪除數據庫、刪除表
命令:drop database database_name; drop table table_name;
//建立數據庫
命令:creat database database_name;
//建立新表
命令:creat table_name(col1_name varchar [not null] [primary key], col2_name varchar [not null]...);
//增長一個列
命令:Alter table table_name add column col_name type;
//添加主鍵
命令:Alter table table_name add primary key(col);
//選擇語句
select * from table_name where...
select sum(uid) from table_name where...
什麼是存儲過程?用什麼來調用?
答:存儲過程是一個預編譯的SQL語句,優勢是容許模塊化的設計,就是說只需建立一次,之後在該程序中就能夠調用屢次。若是某次操做須要執行屢次SQL,使用存儲過程比單純SQL語句執行要快。能夠用一個命令對象來調用存儲過程。
索引的做用?和它的優勢缺點是什麼?
答:索引就一種特殊的查詢表,數據庫的搜索引擎能夠利用它加速對數據的檢索。它很相似與現實生活中書的目錄,不須要查詢整本書內容就能夠找到想要的數據。索引能夠是惟一的,建立索引容許指定單個列或者是多個列。缺點是它減慢了數據錄入的速度,同時也增長了數據庫的尺寸大小。
什麼是內存泄漏?
答:通常咱們所說的內存泄漏指的是堆內存的泄漏。堆內存是程序從堆中爲其分配的,大小任意的,使用完後要顯示釋放內存。當應用程序用關鍵字new等建立對象時,就從堆中爲它分配一塊內存,使用完後程序調用free或者delete釋放該內存,不然就說該內存就不能被使用,咱們就說該內存被泄漏了。
第二部分:J2EE體系結構圖
第三部分,單元測試技術
Junit單元測試,一個bug被隱藏的時間越長,修復這個bug的代價就越大。Junit是一個迴歸測試框架(regression testing framework),供Java開發人員編寫單元測試。Junit測試是程序員測試,即所謂白盒測試。
黑盒測試:是經過使用整個軟件或某種軟件功能來嚴格地測試, 而並無經過檢查程序的源代碼或者很清楚地瞭解該軟件的源代碼程序具體是怎樣設計的。測試人員經過輸入他們的數據而後看輸出的結果從而瞭解軟件怎樣工做。在測試時,把程序看做一個不能打開的黑盆子,在徹底不考慮程序內部結構和內部特性的狀況下,測試者在程序接口進行測試,它只檢查程序功能是否按照需求規格說明書的規定正常使用,程序是否能適當地接收和正確的輸出。
白盒測試:是經過程序的源代碼進行測試而不使用用戶界面。這種類型的測試須要從代碼句法發現內部代碼在算法,溢出,路徑,條件等等中的缺點或者錯誤,進而加以修正。
接下來咱們講講Junit的使用:
正常的規範的代碼開發步驟:天天早上,先檢索SVN,而後單元測試,若是沒問題了。而後作本身的開發任務,作完以後,執行單元測試,若是沒有問題,則提交服務器。測試中用到了Java中的一個關鍵字assert斷言。
// 先下載junit.jar包放到eclipse的項目中 // 好比新建了一個類,以下: package com.sunrun; public class Calculate{ public int add(int a , int b){ return a+b; } public int min(int a, int b){ return a-b; } } //定義測試類的時候,常有以下規範:package包名與被測試類結構一致,這樣的好處是不須要導入類的包,並且被編譯後的.class文件是放在一塊兒的。類名經常是TestXxx package com.sunrun; //不須要導入類哦!!!
import org.junit.Test;
import org.junit.Before;
import org.junit.Assert; //Junit4纔會有
public class TestCalculate{
Calculate cal;
@Before //執行任意一個方法以前,都會執行這段代碼
public void setUp(){
}
@Test
public int testAdd(){
int rel = cal.add(2, 7);
Assert.assertEquals("加法有問題", rel, 9); //(出錯提示信息, 預期值, 實際值)
} } //Junit3和Junit4的差異很大 1.在Junit3中,測試類必須繼承TestCase; 測試方法必須以testXxx開頭,若是但願在執行某個方法執行,都必須執行某個初始化方法,則該初始化方法必須命名爲setUp;若是但願在某個方法運行以後,都必須運行某個方法(如釋放資源),則必須使用tear down.
2.在Junit4中,一個POJO類就是一個測試類,測試方法軍用@Test來標識。初始化方法用@Before來標石,釋放資源的方法用@After來標識。
3.Junit4總提供了一個類叫作Assert,它提供了大量的方法進行斷言處理。Junit3中繼承了TestCase類,類中提供了大量的assert方法。
總結:可是爲了Junit4中的測試類在Junit3中也可使用,習慣於把初始化方法命名爲setUp,釋放資源的方法命名爲tearDown;測試方法也一樣以test開頭(保持兼容)
根據上面講的,咱們引出了兩個問題:第一,單元測試其中某一個方法的失敗,並不會影響其餘方法的測試(最致命的優勢).第二,若是測試除法,是否能考慮到全部的測試用例。我想這就是從單元測試像自動化測試的轉變。
//插播一下異常測試和性能測試 //若是拋出異常,則測試經過;不拋異常則測試不經過。適用於用戶名和密碼校驗的應用場景 @Test(expected=ArithmetricException.class) public void testDivided(int a, int b){ int real = cal.divided(20, 0); } //300毫秒執行完畢,纔算正常。用於簡單的性能測試。 @Test(timeout=300) public void testTime(){ try{ Thread.sleep(500); } catch(Exception e){ e.printStackTrace(); } }
回顧一下Spring的事務(原子、一致、隔離、持久)
小回顧Spring事務管理的API,它提供了三個接口:
platformTransactionManager(平臺事務管理器)
TransactionDefinition(事務定義信息:隔離、傳播、超時、只讀)
TransactionStatus(事務具體運行狀態)
/* *platformTransactionManager(平臺事務管理器) *TransactionDefinition(事務定義信息:隔離、傳播、超時、只讀) *TransactionStatus(事務具體運行狀態) */ //事務管理器 platformTransactionManager是一個接口,它有好多個實現類,咱們要掌握的就兩個,一個是支持Hibernate的,另一個是支持JDBC和Mybatis的。 Hibernate: HibernateTransactionManager (org.springframework.orm.hibernate2.HibernateTransactionManager) JDBC/Mybatis: DataSourceTransactionManager (org.springframework.jdbc.datasource.DataSourceTransactionManager)
//事務定義信息
TransactionDefinition,它提供了事務的隔離級別和傳播特性。
模式篇--代理模式:(基本概念及其應用場景、幾種實現方式)
代理模式定義,爲其餘對象提供代理,以控制對這個對象的訪問。代理對象起到中介的做用,能夠新增額外服務,取消部分功能服務。(如:火車站代售處是火車站的代理;至關於一箇中介的做用,它提供了電話訂票服務(這是火車站沒有的)同時取消了退票服務(火車站有的))。
常見的集中代理模式:遠程代理,爲不一樣地理的對象提供局域網的表明對象。(相似於客戶端和服務器)。虛擬代理,根據須要將資源消耗很大的對象進行延遲,真正須要的時候再去建立。(相似於新聞頁中的圖片,新聞頁的圖片是真是圖片的一個縮影,真正須要專門去看圖片的時候纔會去加載真正圖片,你看一下兩個圖片大小就知道了。)保護代理,用於提供權限控制。
/* * 代理的兩種實現方式: * 1.靜態代理 * 2.動態代理 */
靜態代理:代理和被代理對象在代理以前是肯定的。它們都實現相同的接口或者繼承相同的抽象類。(繼承方式和聚合方式)
動態打理:
1 // 首先定義接口 2 public interface Moveable { 3 void run(); 4 } 5 6 //定義了被代理類 7 public class Car implements MOveable { 8 9 @Overide 10 public void run() { 11 try{ 12 Thread.sleep(new Random().nextInt(1000)); 13 }catch (InterruptException e){ 14 e.printStackTrace(); 15 } 16 } 17 18 } 19 20 //在好久好久之前,咱們若是要記錄汽車的行駛時間 21 public class Car implements MOveable { 22 long startTime = System.currentTimeMills(); 23 @Override 24 public void run() { 25 try{ 26 Thread.sleep(new Random().nextInt(1000)); 27 }catch (InterruptException e){ 28 e.printStackTrace(); 29 } 30 } 31 long endTime= System.currentTimeMills(); 32 System.out.println("汽車行駛時間:"+(endTime - startTime) +"毫秒!"); 33 } 34 35 //接下來演示一下使用繼承方式和聚合方式來實現靜態代理: 36 37 //?Demo1,使用繼承方式實現靜態代理 38 public class Car2 extends Car { 39 @Override 40 public void move(){ 41 long startTime = System.currentTimeMills(); 42 super.move(); 43 long endTime= System.currentTimeMills(); 44 System.out.println("汽車行駛時間:"+(endTime - startTime) +"毫秒!"); 45 } 46 } 47 48 //?Demo2,使用聚合方式實現靜態代理(聚合:一個類中調用另外一個對象) 49 public class Car3 implements Moveable { 50 private Car car; 51 public Car3(Car car){ 52 super(); 53 this.car = car; 54 } 55 @Override 56 public void move(){ 57 long startTime = System.currentTimeMills(); 58 car.move(); 59 long endTime= System.currentTimeMills(); 60 System.out.println("汽車行駛時間:"+(endTime - startTime) +"毫秒!"); 61 } 62 }
聚合方式比繼承方式更適合代理模式
分析以下:好比我如今有以下功能的疊加:時間處理;增長權限管理;增長日誌處理。
/* * 咱們先來看若是使用繼承方式 */ // 需求1:先記錄日誌,再記錄汽車行駛的時間 /* * 日誌記錄開始 * 汽車行駛開始 * 汽車行駛中 * 汽車行駛結束 * 日誌記錄結束 */ // 需求2:先記錄汽車行駛的時間,再記錄日誌 /* * 汽車行駛開始 * 日誌記錄開始 * 汽車行駛中 * 日誌記錄結束 * 汽車行駛結束 */ 像上面這樣,隨着應用場景的疊加,代理類膨脹的函數達到n的階乘(N!) /* * 咱們再來看若是使用聚合方式 * 聚合方式,代理類和被代理類實現相同的接口 * 使用聚合方式,會很是靈活 */ // 公共接口 public interface Moveable { void run(){ } } // 被代理類 public class Car implements Moveable{ @Override public void run () { try{ Thread.sleep(); } catch (InterruptException e){ e.printStackTrace(); } } } //代理類一,實現時間處理 public class CarTimeProxy implements Moveable { private Moveable m; public CarTimeProxy (Moveable m){ super(); this.m = m; } @Override public void run(Moveable m) { long startTime = System.currentTimeMills(); m.move(); long endTime = System.currentTimeMills(); System.out.println("運行時間:" + (endTime - startTime) + "毫秒!"); } } //代理類二,實現日誌的代理 (注意這裏實現代理類的疊加) public class CarLogProxy implements Moveable { private Moveable m; public CarLogProxy (Moveable m){ super(); this.m = m; } @Override public void run(Moveable m) { System.out.println("日誌開始"); m.move(); System.out.println("日誌結束"); } } //接下來,咱們使用測試類看看聚合代理的靈活性 public class TestCar extends TestCase { public static void main(String args[]){ Car car = new Car(); /* * 功能疊加Demo 1 * 先時間處理,後日志疊加 */ CarTimeProxy ctp = new CarTimeProxy(car); CarLogProxy clp = new CarLogProxy(ctp); clp.move(); /* * 功能疊加Demo 2 * 先記錄日誌,後時間處理功能疊加 */ CarLogProxy clp = new CarLogProxy(car); CarTimeProxy ctp = new CarTimeProxy(clp); ctp.move(); } }
總結一下上面的問題,解決了靜態代理功能擴展的靈活性。那麼若是咱們寫火車、飛機、坦克的相應繼承了Moveable的類,能不能複用上面的那些代理類呢?就是說一個TimeProxy同時實現了對火車、汽車、自行車的代理呢?接下來就引伸出來了動態代理。咱們來分析一下:
1 /* 2 * 動態代理但是一個高逼格的東西,包括JDK和Spring框架都是以它爲基礎構建的,咱們先來分析一下JDK中的動態代理。 3 * 動態的產生代理,實現對不一樣類,不一樣方法的代理。 4 */
如上圖所示,ProxySubject是代理類,RealSubject是被代理類;ProxyHandler是實現了InvocationHandler接口的一個類(JDK提供),Proxy是動態產生的代理類。奉上代碼:
// Demo展現 import java.lang.reflect.InvocationHandler; public class TimeHandler implements InvocationHandler { private Object target; public TimeHandler(Object target){ super();//調用父類構造方法 this.target = target; } /* * 參數說明 * Proxy 被代理對象 * Method 被代理對象的方法 * args[] 方法的參數 * * 返回值 * Object 方法的返回值 **/ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ long startTime = System.currentTimeMills(); method.invoke(target); long endTime = System.currentTimeMills(); System.out.println("運行時間:" + (startTime - endTime)); return null; } } // 來一個測試用例,生成動態代理類 public class Test { Car car = new Car(); //這部分省略了,固然Car是繼承了Moveable接口的 InvocationHandler h = new TimeHandler(); Class<?> cls = car.getClass(); /* * 參數說明(loader, interface, innovationHandler) * loader 類加載器 * interface 實現接口 * innovationHandler **/ Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterface(), h); m.move(); }
總結,所謂動態代理是這樣一種類,它在運行的時候產生了一個class對象。該class須要實現一組interface,使用動態代理時,必須實現InvocationHandler接口。
說一下Lucene的搜索引擎機制:
//如搜索「數據結構 清華大學」 (content like '%數據結構%') or (content like '%清華大學%') 使用上面的like的方法,檢索起來超級慢的,把用戶都嚇跑了
Java基礎回顧
1 1.Java爲何要單繼承?既然單繼承爲何又要實現多個接口? 2 一個類只能繼承一個其餘的類: 3 在Java語言中禁止多重繼承:一個類能夠具備多個直接父類。多重繼承不合法的緣由是容易引起意義不明確。例如,有一個類C,若是容許它同時繼承A類與B類(class C extends A,B{}),假如A、B兩個類都有同一種方法fun(),若是定義: 4 C c = new C(); 5 那麼c.fun()應該調用哪個父類的fun()方法?沒法給出答案,所以Java語言禁止多重繼承。 但C++倒是能夠的,因此C++比起java在語法上卻難了些。 6 7 但一個類能夠實現多個接口,這又是爲何? 8 這一特性和上一特性結合使用,能夠得到和多重繼承類似的效果。 9 現假如類C實現了A與B兩個接口(class c implements A,c{}),且這兩個接口都有一個抽象fun()方法,如今調用方法時沒有任務不明確的地方,由於接口中的全部方法都是抽象,而且超類的任何方法都需在子類中地覆蓋實現,因此調用時實際上是調用本身自己的實現方法,沒有什麼調用不明確的說法。 10 2.Static、final迅速作出區分? 11 三個維度來看:基本類型變量,引用類型變量,方法、類。 12 final,修飾基本類型變量,變量不可變;修飾引用類型變量,內容能夠變,不能再指向其餘內容;修飾方法,指方法不可被繼承;修飾類,類不能被繼承。 13 static,修飾基本類型變量,就是全局變量;修飾引用類型變量,也是全局的;修飾方法;初始化一次;修飾類,通常內部類才申明爲靜態的,靜態內部類。靜態的不能調用非靜態的。