一天沒顧得上吃飯,連續三面真的好累的,記錄一下面試過程當中的問題吧,也算是對本身學習過程當中的總結吧!java
一面很奇怪HR面,二面技術面,三面是綜合面,在這裏主要說說二面過程當中的問題吧!linux
和同窗一塊兒去的面試,大部分面了5分鐘結束,不知道面試官比較感興趣仍是怎麼了,就給面了30多分鐘,其中的問題就記得下面這些,固然還有好多不記得了。程序員
簡歷中寫了本身作過的兩個項目,開始是畫項目流程圖,還有爲何作這個項目,項目中遇到的最大問題是什麼,當時是怎麼解決的。面試
多態是同一個行爲具備多個不一樣表現形式或形態的能力。
多態性是對象多種表現形式的體現。
好比咱們說"寵物"這個對象,它就有不少不一樣的表達或實現,好比有小貓、小狗、蜥蜴等等。那麼我到寵物店說"請給我一隻寵物",服務員給我小貓、小狗或者蜥蜴均可以,咱們就說"寵物"這個對象就具有多態性。
接下來讓咱們經過實例來了解Java的多態。
public interface Vegetarian{} public class Animal{} public class Deer extends Animal implements Vegetarian{}
實現多態的兩種方式:重載和覆蓋
覆蓋,是指子類從新定義父類的虛函數的作法。數據庫
重載,是指容許存在多個同名函數,而這些函數的參數表不一樣(或許參數個數不一樣,或許參數類型不一樣,或許二者都不一樣)。數組
使用多態主要實現Java不能多繼承的問題。
面向對象的三個基本特徵是:封裝、繼承、多態。
Java語言的特性:面向對象、分佈式、解釋性、健壯、安全與系統無關、可移植、高性能、多線程和靜態的語言。
懶漢式,線程不安全 public class Singleton { private static Singleton instance; private Singleton (){ } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } 這段代碼簡單明瞭,並且使用了懶加載模式,可是卻存在致命的問題。當有多個線程並行調用 getInstance() 的時候,就會建立多個實例。也就是說在多線程下不能正常工做。 懶漢式,線程安全爲了解決上面的問題,最簡單的方法是將整個 getInstance() 方法設爲同步(synchronized)。 public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } 雖然作到了線程安全,而且解決了多實例的問題,可是它並不高效。由於在任什麼時候候只能有一個線程調用 getInstance() 方法。可是同步操做只須要在第一次調用時才被須要,即第一次建立單例實例對象時。這就引出了雙重檢驗鎖。 雙重檢驗鎖雙重檢驗鎖模式(double checked locking pattern),是一種使用同步塊加鎖的方法。程序員稱其爲雙重檢查鎖,由於會有兩次檢查 instance == null,一次是在同步塊外,一次是在同步塊內。爲何在同步塊內還要再檢驗一次?由於可能會有多個線程一塊兒進入同步塊外的 if,若是在同步塊內不進行二次檢驗的話就會生成多個實例了。 public static Singleton getSingleton() { if (instance == null) { //Single Checked synchronized (Singleton.class) { if (instance == null) { //Double Checked instance = new Singleton(); } } } return instance ; } 這段代碼看起來很完美,很惋惜,它是有問題。主要在於instance = new Singleton()這句,這並不是是一個原子操做,事實上在 JVM 中這句話大概作了下面 3 件事情。 1. 給 instance 分配內存 2. 調用 Singleton 的構造函數來初始化成員變量 3. 將instance對象指向分配的內存空間(執行完這步 instance 就爲非 null 了) 可是在 JVM 的即時編譯器中存在指令重排序的優化。也就是說上面的第二步和第三步的順序是不能保證的,最終的執行順序多是 1-2-3 也多是 1-3-2。若是是後者,則在 3 執行完畢、2 未執行以前,被線程二搶佔了,這時 instance 已是非 null 了(但卻沒有初始化),因此線程二會直接返回 instance,而後使用,而後瓜熟蒂落地報錯。 咱們只須要將 instance 變量聲明成 volatile 就能夠了。 public class Singleton { private volatile static Singleton instance; //聲明成 volatile private Singleton (){} public static Singleton getSingleton() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } 有些人認爲使用 volatile 的緣由是可見性,也就是能夠保證線程在本地不會存有 instance 的副本,每次都是去主內存中讀取。但實際上是不對的。使用 volatile 的主要緣由是其另外一個特性:禁止指令重排序優化。也就是說,在 volatile 變量的賦值操做後面會有一個內存屏障(生成的彙編代碼上),讀操做不會被重排序到內存屏障以前。好比上面的例子,取操做必須在執行完 1-2-3 以後或者 1-3-2 以後,不存在執行到 1-3 而後取到值的狀況。從「先行發生原則」的角度理解的話,就是對於一個 volatile 變量的寫操做都先行發生於後面對這個變量的讀操做(這裏的「後面」是時間上的前後順序)。 可是特別注意在 Java 5 之前的版本使用了 volatile 的雙檢鎖仍是有問題的。其緣由是 Java 5 之前的 JMM (Java 內存模型)是存在缺陷的,即時將變量聲明成 volatile 也不能徹底避免重排序,主要是 volatile 變量先後的代碼仍然存在重排序問題。這個 volatile 屏蔽重排序的問題在 Java 5 中才得以修復,因此在這以後才能夠放心使用 volatile。 相信你不會喜歡這種複雜又隱含問題的方式,固然咱們有更好的實現線程安全的單例模式的辦法。 餓漢式 static final field這種方法很是簡單,由於單例的實例被聲明成 static 和 final 變量了,在第一次加載類到內存中時就會初始化,因此建立實例自己是線程安全的。 public class Singleton{ //類加載時就初始化 private static final Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; } } 這種寫法若是完美的話,就不必在囉嗦那麼多雙檢鎖的問題了。缺點是它不是一種懶加載模式(lazy initialization),單例會在加載類後一開始就被初始化,即便客戶端沒有調用 getInstance()方法。餓漢式的建立方式在一些場景中將沒法使用:譬如 Singleton 實例的建立是依賴參數或者配置文件的,在 getInstance() 以前必須調用某個方法設置參數給它,那樣這種單例寫法就沒法使用了。 靜態內部類 static nested class我比較傾向於使用靜態內部類的方法,這種方法也是《Effective Java》上所推薦的。 public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } } 這種寫法仍然使用JVM自己機制保證了線程安全問題;因爲 SingletonHolder 是私有的,除了 getInstance() 以外沒有辦法訪問它,所以它是懶漢式的;同時讀取實例的時候不會進行同步,沒有性能缺陷;也不依賴 JDK 版本。 枚舉 Enum用枚舉寫單例實在太簡單了!這也是它最大的優勢。下面這段代碼就是聲明枚舉實例的一般作法。 public enum EasySingleton{ INSTANCE; } 咱們能夠經過EasySingleton.INSTANCE來訪問實例,這比調用getInstance()方法簡單多了。建立枚舉默認就是線程安全的,因此不須要擔憂double checked locking,並且還能防止反序列化致使從新建立新的對象。可是仍是不多看到有人這樣寫,多是由於不太熟悉吧。 總結通常來講,單例模式有五種寫法:懶漢、餓漢、雙重檢驗鎖、靜態內部類、枚舉。上述所說都是線程安全的實現,文章開頭給出的第一種方法不算正確的寫法。 就我我的而言,通常狀況下直接使用餓漢式就行了,若是明確要求要懶加載(lazy initialization)會傾向於使用靜態內部類,若是涉及到反序列化建立對象時會試着使用枚舉的方式來實現單例。
(1) final:修飾符(關鍵字),若是一個類被聲明爲final,意味着它不能再派生出新的子類,不能做爲父類被繼承。所以一個類不能既被聲明爲 abstract的,又被聲明爲final的。將變量或方法聲明爲final,能夠保證它們在使用中不被改變。被聲明爲final的變量必須在聲明時給定初值,而在之後的引用中只能讀取,不可修改。被聲明爲final的方法也一樣只能使用,不能重載 (2) finally:在異常處理時提供 finally 塊來執行任何清除操做。若是拋出一個異常,那麼相匹配的 catch 子句就會執行,而後控制就會進入 finally塊(若是有的話)。 (3) finalize:方法名。Java 技術容許使用 finalize() 方法在垃圾收集器將對象從內存中清除出去以前作必要的清理工做。這個方法是由垃圾收集器在肯定這個對象沒有被引用時對這個對象調用的。它是在 Object 類中定義的,所以全部的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者執行其餘清理工做。finalize() 方法是在垃圾收集器刪除對象以前對這個對象調用的。
接口的概念其實並不難理解, 接口關鍵字Interface, 在使用時能夠只定義函數體而不需求詳細的實現。 再類的繼承過程當中能夠實現多個接口而取代了類的多繼承。
在使用抽象類時須要注意幾點: 1、抽象類不能被實例化,實例化的工做應該交由它的子類來完成,它只須要有一個引用便可。 2、抽象方法必須由子類來進行重寫。 3、只要包含一個抽象方法的抽象類,該方法必需要定義成抽象類,無論是否還包含有其餘方法。 4、抽象類中能夠包含具體的方法,固然也能夠不包含抽象方法。 5、子類中的抽象方法不能與父類的抽象方法同名。 6、abstract不能與final並列修飾同一個類。 七、abstract 不能與private、static、final或native並列修飾同一個方法。
抽象類--抽象類是用來捕捉子類的通用特性的 。它不能被實例化,只能被用做子類的超類。抽象類是被用來建立繼承層級裏子類的模板
接口-- -接口是抽象方法的集合。若是一個類實現了某個接口,那麼它就繼承了這個接口的抽象方法。這就像契約模式,若是實現了這個接口,那麼就必須確保使用這些方法。接口只是一種形式,接口自身不能作任何事情。
何時使用抽象類和接口
若是你擁有一些方法而且想讓它們中的一些有默認實現,那麼使用抽象類吧。
若是你想實現多重繼承,那麼你必須使用接口。因爲Java不支持多繼承,子類不可以繼承多個類,但能夠實現多個接口。所以你就可使用接口來解決它。
若是基本功能在不斷改變,那麼就須要使用抽象類。若是不斷改變基本功能而且使用接口,那麼就須要改變全部實現了該接口的類。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; //用來存儲字符串轉換而來的字符數組 /** The offset is the first index of the storage that is used. */ private final int offset; //字符串起始字符在字符數組的位置 /** The count is the number of characters in the String. */ private final int count; //字符串分解成字符數組後字符的數目 }
1 增: 2 insert into 表名 values(0,'測試'); 3 注:如上語句,表結構中有自動增加的列,也必須爲其指定一個值,一般爲0 4 insert into 表名(id,name) values(0,'尹當')--同上 5 2.刪數據: 6 delete from 表名; 7 delete from 表名 where id=1; 8 刪除結構: 9 刪數據庫:drop database 數據庫名; 10 刪除表:drop table 表名; 11 刪除表中的列:alter table 表名 drop column 列名; 12 3. 改: 13 修改全部:updata 表名 set 列名='新的值,非數字加單引號' ; 14 帶條件的修改:updata 表名 set 列名='新的值,非數字加單引號' where id=6; 15 4.查: 16 查詢全部的數據:select *from 表名; 17 帶條件的查詢: 18 select *from 表名 where 列名=條件值; 19 Select * from 表名 where 列名 not like(like) '字符值' 20 分頁查詢:select *from 表名 limit 每頁數量 offset 偏移量;
order by 是按字段排序 group by 是按字段分類
1.ls – List ls會列舉出當前工做目錄的內容(文件或文件夾),就跟你在GUI中打開一個文件夾去看裏面的內容同樣。
2.mkdir – Make Directory mkdir <new-directory-name>常見一個新目錄
3.pwd – Print Working Directory pwd顯示當前工做目錄 4.cd – Change Directory 對於當前在終端運行的會中中,cd <directory>將給定的文件夾(或目錄)設置成當前工做目錄。 5.rmdir – Remove Directory rmdir <directory-name>刪除給定的目錄。 6.rm – Remove rm <file-name>會刪除給定的文件或文件夾,可使用rm -r <directory-name>遞歸刪除文件夾 7.cp – Copy cp <source-file> <destination-file>命令對文件或文件夾進行復制,可使用cp -r <source-folder> <destination-folder> 選項來遞歸複製文件夾。 8.mv – MoVe mv <source> <destination>命令對文件或文件夾進行移動,若是文件或文件夾存在於當前工做目錄,還能夠對文件或文件夾進行重命名。 9.cat – concatenate and print files cat <file>用於在標準輸出(監控器或屏幕)上查看文件內容。 10.tail – print TAIL (from last) > tail <file-name>默認在標準輸出上顯示給定文件的最後10行內容,可使用tail -n N <file-name>指定在標準輸出上顯示文件的最後N行內容。 11.less – print LESS less <file-name>按頁或按窗口打印文件內容。在查看包含大量文本數據的大文件時是很是有用和高效的。你可使用Ctrl+F向前翻頁,Ctrl+B向後翻頁。 12.grep grep "<string>" <file-name>在給定的文件中搜尋指定的字符串。grep -i "<string>" <file-name>在搜尋時會忽略字符串的大小寫,而grep -r "<string>" <file-name>則會在當前工做目錄的文件中遞歸搜尋指定的字符串。 13.Find 這個命令會在給定位置搜尋與條件匹配的文件。你可使用find <folder-to-search> -name <file-name>的-name選項來進行區分大小寫的搜尋,find <folder-to-search> -iname <file-name>來進行不區分大小寫的搜尋。 find <folder-to-search> -iname <file-name> 14.tar tar命令能建立、查看和提取tar壓縮文件。tar -cvf <archive-name.tar> <file1-OR-file2-OR-both-to-archive>是建立對應壓縮文件,tar -tvf <archive-to-view.tar>來查看對應壓縮文件,tar -xvf <archive-to-extract.tar>來提取對應壓縮文件。 15.gzip gzip <filename>命令建立和提取gzip壓縮文件,還能夠用gzip -d <filename>來提取壓縮文件。 16.unzip unzip <archive-to-extract.zip>對gzip文檔進行解壓。在解壓以前,可使用unzip -l <archive-to-extract.zip>命令查看文件內容。 17.help <command-name> --help會在終端列出全部可用的命令,可使用任何命令的-h或-help選項來查看該命令的具體用法。 18.whatis – What is this command whatis <command-name>會用單行來描述給定的命令。 19.man – Manual man <command-name>會爲給定的命令顯示一個手冊頁面。 20.exit exit用於結束當前的終端會話。 21.ping ping <remote-host-address>經過發送數據包ping遠程主機(服務器),經常使用與檢測網絡鏈接和服務器狀態。 22.who – Who Is logged in who能列出當前登陸的用戶名。 23.su – Switch User su <username>用於切換不一樣的用戶。即便沒有使用密碼,超級用戶也能切換到其它用戶。 24.uname uname會顯示出關於系統的重要信息,如內核名稱、主機名、內核版本、處理機類型等等,使用uname -a能夠查看全部信息。 25.free – Free memory free會顯示出系統的空閒內存、已經佔用內存、可利用的交換內存等信息,free -m將結果中的單位轉換成KB,而free –g則轉換成GB。 26.df – Disk space Free df查看文件系統中磁盤的使用狀況–硬盤已用和可用的存儲空間以及其它存儲設備。你可使用df -h將結果以人類可讀的方式顯示。 27.ps – ProcesseS ps顯示系統的運行進程。 28.Top – TOP processes top命令會默認按照CPU的佔用狀況,顯示佔用量較大的進程,可使用top -u <username>查看某個用戶的CPU使用排名狀況。 29.shutdown shutdown用於關閉計算機,而shutdown -r用於重啓計算機。