1.接口和抽象類的區別
相似點:
(1)接口和抽象類都不能被實例化
(2)實現接口或繼承抽象類的普通子類都必須實現這些抽象方法
不同點:
(1)抽象類可以包含普通方法和代碼塊,接口里只能包含抽象方法,靜態方法和默認方法,
(2)抽象類可以有構造方法,而接口沒有
(3)抽象類中的成員變量可以是各種類型的,接口的成員變量只能是 public static final 類****型的,并且必須賦值
2.重載和重寫的區別
方法的重載和重寫都是實現多態的方式,
重載實現的是編譯時的多態性,
而重寫實現的是運行時的多態性。
重載發生在同一個類中,方法名相同、參數列表、返回類型、權限修飾符可以不同
重寫發生在子類中,方法名相、參數列表、返回類型都相同,權限修飾符要大于父類方法,聲明異常范圍要小于父類方法,但是final和private修飾的方法不可重寫
3.==和equals的區別
==比較基本類型,比較的是值,
==比較引用類型,比較的是內存地址
equlas是Object類的方法,本質上與==一樣,但是有些類重寫了equals方法,比如String的equals被重寫后,比較的是字符值,另外重寫了equlas后,也必須重寫hashcode()方法
疑問?
>為什么重寫equal了必須重寫hashcode?
equals() 方法和 hashcode() 方法是 java.lang.Object 類的兩個重要的方法,Java中多數類都會重寫 Object 類的 equals() 方法。
在實際應用中,如果我們自定義的類需要進行比較操作,就一定也需要重寫 equals() 方法。那么為什么重寫 equals()方法時,必須要求重寫 hashCode() 方法呢?
首先, equals() 方法和 hashcode() 方法間的關系是這樣的:
1、如果兩個對象相同(即:用 equals 比較返回true),那么它們的 hashCode 值一定要相同;
2、如果兩個對象的 hashCode 相同,它們并不一定相同(即:用 equals 比較返回 false);
上面這兩句話,如果明白【散列表】的結構,就一定會很明白,這里只簡單提一句:散列表同時運用了數組和鏈表。
《Effective java》一書中這樣說到:在每個覆蓋了 equals() 方法的類中,也必須覆蓋 hashCode() 方法,如果不這樣做的話,就會違反 Object.hashCode 的通用的約定,從而導致該類無法結合所有基于散列的集合一起正常運作,這樣的集合包括HashMap,HashSet 和 HashTable。
如果只重寫了 equals 方法,那么默認情況下,Set 進行去重操作時,會先判斷兩個對象的 hashCode 是否相同,此時因為沒有重寫 hashCode 方法,所以會直接執行 Object 中的 hashCode 方法,而 Object 中的 hashCode 方法對比的是兩個不同引用地址的對象,所以結果是 false,那么 equals 方法就不用執行了,直接返回的結果就是 false:兩個對象不是相等的,于是就在 Set 集合中插入了兩個相同的對象。?
但是,如果在重寫 equals 方法時,也重寫了 hashCode 方法,那么在執行判斷時會去執行重寫的 hashCode 方法,此時對比的是兩個對象的所有屬性的 hashCode 是否相同,于是調用 hashCode 返回的結果就是 true,再去調用 equals 方法,發現兩個對象確實是相等的,于是就返回 true 了,因此 Set 集合就不會存儲兩個一模一樣的數據了,于是整個程序的執行就正常了。
總結
hashCode 和 equals 兩個方法是用來協同判斷兩個對象是否相等的,采用這種方式的原因是可以提高程序插入和查詢的速度,如果在重寫 equals 時,不重寫 hashCode,就會導致在某些場景下,例如將兩個相等的自定義對象存儲在 Set 集合時,就會出現程序執行的異常,為了保證程序的正常執行,所以我們就需要在重寫 equals 時,也一并重寫 hashCode 方法才行。
答案來源
4.Java異常處理機制
4.1Error和Exception的區別:
Error和Exception都有一個共同的根類是Throwable類。
Error是系統中的錯誤,程序員是不能改變的和處理的,一般是指與虛擬機相關的問題,如系統崩潰,虛擬機錯誤,內存空間不足,方法調用棧溢等。對于這類錯誤的導致的應用程序中斷,僅靠程序本身無法恢復和和預防,遇到這樣的錯誤,建議讓程序終止。因此我們編寫程序時不需要關心這類錯誤。
Exception,也就是我們經常見到的一些異常情況,表示程序可以處理的異常,可以捕獲且可能恢復。遇到這類異常,應該盡可能處理異常,使程序恢復運行,而不應該隨意終止異常。
異常分類
總體上我們根據Javac對異常的處理要求,將異常類分為2類。
我們常說的異常是狹義上的:就是指Exception及其子類,但是廣義上的異常是包括Exception和Error;
Java的異常(包括Exception和Error)從廣義上分為檢查異常(checked exceptions)和非檢查的異常(unchecked exceptions)。
其中根據Exception異常進行劃分,可分為運行時異常和非運行時異常。
需要明確的是:檢查和非檢查是對于javac來說的,這樣就很好理解和區分了。
檢查異常
What:什么是檢查異常(checked exception)?
就是編譯器要求你必須處置的異常。不知道你編程的時候有沒有遇到過,你寫的某段代碼,編譯器要求你必須要對這段代碼try…catch,或者throws exception,如果你遇見過,沒錯,這就是檢查異常,也就是說,你代碼還沒運行呢,編譯器就會檢查你的代碼,會不會出現異常,要求你對可能出現的異常必須做出相應的處理。
javac強制要求程序員為這樣的異常做預備處理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch語句捕獲它并處理,要么用throws子句聲明拋出它,否則編譯不會通過。這樣的異常一般是由程序的運行環境導致的。因為程序可能被運行在各種未知的環境下,而程序員無法干預用戶如何使用他編寫的程序,于是程序員就應該為這樣的異常時刻準備著。如SQLException , IOException,ClassNotFoundException 等。
比如:我們調用日期格式化類解析字符串的時候;
How:怎樣處理檢查異常(checked exception)?
1、繼續拋出,消極的方法,一直可以拋到java虛擬機來處理,就是通過throws Exception拋出。2、用try...catch捕獲注意,對于檢查的異常必須處理,或者必須捕獲或者必須拋出
Where:檢查異常有哪些呢?
除了RuntimeException與其子類,以及錯誤(Error),其他的都是檢查異常(絕對的大家族)。
非檢查異常
What:什么是非檢查異常(unchecked exceptions)?
編譯器不要求強制處置的異常,雖然你有可能出現錯誤,但是編譯器不會在編譯的時候檢查,沒必要,也不可能。
javac在編譯時,不會提示和發現這樣的異常,不要求在程序處理這些異常。所以如果愿意,我們可以編寫代碼處理(使用try…catch…finally)這樣的異常,也可以不處理。
對于這些異常,我們應該修正代碼,而不是去通過異常處理器處理。這樣的異常發生的原因多半是代碼寫的有問題。如除0錯誤ArithmeticException,錯誤的強制類型轉換錯誤ClassCastException,數組索引越界ArrayIndexOutOfBoundsException,使用了空對象NullPointerException等等。
How:對非檢查的異常(unchecked exception )怎樣處理?
1、用try...catch捕獲2、繼續拋出3、不處理4、通過代碼處理一般我們是通過代碼處理的,因為你很難判斷會出什么問題,而且有些異常你也無法運行時處理,比如空指針,需要人手動的去查找。而且,捕捉異常并處理的代價遠遠大于直接拋出。
Why:為什么有非檢查異常?
你想想非檢查異常都有哪些?
NullPointerException,IndexOutOfBoundsException,VirtualMachineError等,這些異常你編譯的時候檢查嗎?再說了,明明可以運行時檢查,都在編譯的時候檢查,你寫的代碼還能看嗎?而且有些異常只能在運行時才能檢查出來,比如空指針,堆溢出等。
Where:非檢查異常有哪些?
RuntimeException與其子類,以及錯誤(Error)。
Exception異常劃分
Exception異常進行劃分,它可分為運行時異常和編譯期異常。
運行時異常:
是RuntimeException類及其子類異常,如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標越界異常)等,這些異常是非檢查異常,程序中可以選擇捕獲處理,也可以不處理。這些異常一般是由程序邏輯錯誤引起的,程序應該從邏輯角度盡可能避免這類異常的發生。
運行時異常的特點是Java編譯器不會檢查它,也就是說,當程序中可能出現這類異常,即使沒有用try-catch語句捕獲它,也沒有用throws子句聲明拋出它,也會編譯通過。
編譯期異常:
是RuntimeException以外的異常,類型上都屬于Exception類及其子類。從程序語法角度講是必須進行處理的異常,如果不處理,程序就不能編譯通過。如IOException、SQLException等以及用戶自定義的Exception異常,一般情況下不要自定義檢查異常。
4.2常見異常
java.lang.RuntimeException: 運行時異常
ClassCastException: 類類型轉換異常,當試圖將對象強制轉換為不是實例的子類時,拋出該異常;
ArrayIndexOutOfBoundsException: 數組下標越界異常,當你使用不合法的索引訪問數組時會拋出該異常;
NullPointerException: 空指針異常,通過null進行方法和屬性調用會拋出該異常;
ArithmeticException: 算術運算異常,除數為0,拋出該異常;
NumberFormatException: 數字轉換異常,當試圖將一個String轉換為指定的數字類型,而該字符串確不滿足數字類型要求的格式時,拋出該異常;
InputMismatchException: 輸入不匹配異常,輸入的值數據類型與設置的值數據類型不能匹配。
4.3異常處理的處理機制
在編寫程序時,經常要在可能出現錯誤的地方加上檢測的代碼,如進行x/y運算時,要檢測分母為0,數據為空,輸入的不是數據而是字符等。過多的if-else分支會導致程序的代碼加長、臃腫,可讀性差。因此采用異常處理機制。
在編寫代碼處理異常時,對于檢查異常/非檢查異常,都有2種不同的處理方式:
1、使用try...catch...finally語句塊處理它。2、在函數簽名中使用throws 聲明交給函數調用者caller去解決。
比如現有一輛車,這個車你可以是方法,這輛車在可能存在各種風險,那么對于這些風險的處理方式,就相當于異常的處理方式:
1、使用try...catch...finally語句塊處理它。我們把這輛車可能出現的問題都考慮清楚了,并提供了備選方案(出現問題怎么做),如果沒有出現問題,那么用不到備選方案;如果出現了問題,根據問題去找對應的備選方案,以保證車的正常運行;如果出現了問題,但是又沒備選方案,那么車就跑不了;2、在函數簽名中使用throws 聲明交給函數調用者caller去解決。我知道車可能又問題,但是我不處理,誰來使用了,告訴調用者,這里可能有問題;那么調用者可以處理這個問題,也可以不處理;如果它不處理,還是會出現問題,如果處理了,肯定沒問題;A -》 B -》 C
Java采用的異常處理機制,是將異常處理的程序代碼集中在一起,與正常的程序代碼分開,使得程序簡潔、優雅,并易于維護。
Java提供的是異常處理的抓拋模型。
Java程序的執行過程中如出現異常,會生成一個異常類對象,該異常對象將被提交給Java運行時系統,這個過程稱為拋出(throw)異常。
異常對象的生成:由虛擬機自動生成:程序運行過程中,虛擬機檢測到程序發生了問題,如果在當前代碼中沒有找到相應的處理程序,就會在后臺自動創建一個對應異常類的實例對象并拋出——自動拋出。由開發人員手動創建:Exception exception = new ClassCastException();創建好的異常對象不拋出對程序沒有任何影響,和創建一個普通對象一樣。
異常的拋出機制:
如果一個方法內拋出異常,該異常對象會被拋給調用者方法中處理。如果異常沒有在調用者方法中處理,它繼續被拋給這個調用方法的上層方法。這個過程將一直繼續下去,直到異常被處理。這一過程稱為捕獲(catch)異常。
如果一個異常回到main()方法,并且main()也不處理,則程序運行終止。
程序員通常只能處理Exception,而對Error無能為力。
異常處理機制一:try-catch-finally
語法格式:
try{...... //可能產生異常的代碼}catch( ExceptionName1 e ){...... //當產生ExceptionName1型異常時的處置措施}catch( ExceptionName2 e ){...... //當產生ExceptionName2型異常時的處置措施}[ finally{...... //無論是否發生異常,都無條件執行的語句} ]
語法解釋:
try:
捕獲異常的第一步是用try{…}語句塊選定捕獲異常的范圍,將可能出現異常的代碼放在try語句塊中。
如果發生異常,則嘗試去匹配catch塊,catch塊可以有多個(因為try塊可以出現多個不同類型異常);
如果執行完try不管有沒有發生異常,則接著去執行finally塊和finally后面的代碼(如果有的話)。
catch (Exceptiontype e):
在catch語句塊中是對異常對象進行處理的代碼。每個try語句塊可以伴隨一個或多個catch語句,用于處理可能產生的不同類型的異常對象。
每一個catch塊用于捕獲并處理一個特定的異常,或者這異常類型的子類。Java可以將多個異常聲明在一個catch中。 catch(Exception1 | Exception2 | Exception3 e)
catch后面的括號定義了異常類型和異常參數。如果異常與之匹配且是最先匹配到的,則虛擬機將使用這個catch塊來處理異常。
在catch塊中可以使用這個塊的異常參數來獲取異常的相關信息。異常參數是這個catch塊中的局部變量,其它塊不能訪問。與其它對象一樣,可以訪問一個異常對象的成員變量或調用它的方法。
①、getMessage() 獲取異常信息,返回字符串。②、printStackTrace() 獲取異常類名和異常信息,以及異常出現在程序中的位置。返回值void。
如果當前try塊中發生的異常在后續的所有catch中都沒捕獲到,則先去執行finally,然后到這個函數的外部caller中去匹配異常處理器。
如果try中沒有發生異常,則所有的catch塊將被忽略。
注意:如果明確知道產生的是何種異常,
可以用該異常類作為catch的參數;
也可以用其父類作為catch的參數。比如:可以用 ArithmeticException 類作為參數的地方,
就可以用RuntimeException類作為參數,
或者用所有異常的父類Exception類作為參數。但不能是與ArithmeticException類無關的異常,如NullPointerException(catch中的語句將不會執行)。
finally:
finally塊通常是可選的。捕獲異常的最后一步是通過finally語句為異常處理提供一個統一的出口,使得在控制流轉到程序的其它部分以前,能夠對程序的狀態作統一的管理。
不論在try代碼塊中是否發生了異常事件,catch語句是否執行,catch語句是否有異常,catch語句中是否有return,finally塊中的語句都會被執行。
一個try至少要有一個catch塊,否則, 至少要有1個finally塊。但是finally不是用來處理異常的,finally不會捕獲異常。
finally主要做一些清理工作,如流的關閉,數據庫連接的關閉等。
public class Test_Input_01 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);/** 當我們只寫一個try{}的時候,會報錯:* Syntax error, insert "Finally" to complete TryStatement* 語法錯誤,插入“Finally”來完成Try塊* * 總結: try不能單獨存在,必須結合catch或finally來使用
* try塊中沒有異常,會執行finally(如果有)* try塊中有異常,會執行對應的catch塊(如果有),try中異常發生點之后的代碼將不會執行*/try{//try塊中放可能發生異常的代碼。//如果執行完try且不發生異常,則接著去執行finally塊和finally后面的代碼(如果有的話)。//如果發生異常,則嘗試去匹配catch塊。異常點之后的代碼不會運行//這行代碼有可能出錯int num1 = sc.nextInt(); //這行代碼如果出現異常,那么后面的輸出語句就不執行int num2 = sc.nextInt();System.out.println(num1+"\t"+num2);System.out.println(num1/num2);String str = null;System.out.println(str.charAt(0));}catch(InputMismatchException | NullPointerException e) { // catch(異常對象) 當異常發生了,catch就會捕獲對應的異常
// 每一個catch塊用于捕獲并處理一個特定的異常,或者這異常類型的子類。
//Java7中可以將多個異常聲明在一個catch中。
// catch(Exception1 | Exception2 | Exception3 e)
// catch后面的括號定義了異常類型和異常參數。
//如果異常與之匹配且是最先匹配到的,則虛擬機將使用這個catch塊來處理異常。// 在catch塊中可以使用這個塊的異常參數來獲取異常的相關信息。//異常參數是這個catch塊中的局部變量,其它塊不能訪問。// 如果當前try塊中發生的異常在后續的所有catch中都沒捕獲到,//則先去執行finally,然后到這個函數的外部caller中去匹配異常處理器。// 如果try中沒有發生異常,則所有的catch塊將被忽略。System.out.println("catch塊 - try里面發生了異常 - 空指針和輸入不匹配異常都走這個Catch");}catch(java.lang.ArithmeticException e){e.getMessage();System.out.println("算數異常:除數不能為0");}catch(Exception e){System.out.println("程序發生未知異常");}finally {// finally塊通常是可選的。// 無論異常是否發生,異常是否匹配被處理,finally都會執行。// 一個try至少要有一個catch塊,否則, 至少要有1個finally塊。//但是finally不是用來處理異常的,finally不會捕獲異常。// finally主要做一些清理工作,如流的關閉,數據庫連接的關閉等。 System.out.println("finally塊");}System.out.println("異常捕獲之后的代碼");}
}
需要注意的地方
1、try塊中的局部變量和catch塊中的局部變量(包括異常變量),以及finally中的局部變量,他們之間不可共享使用。
2、每一個catch塊用于處理一個異常。異常匹配是按照catch塊的順序從上往下尋找的,只有第一個匹配的catch會得到執行。匹配時,不僅運行精確匹配,也支持父類匹配,因此,如果同一個try塊下的多個catch異常類型有父子關系,應該將子類異常放在前面,父類異常放在后面,這樣保證每個catch塊都有存在的意義。
3、java中,異常處理的任務就是將執行控制流從異常發生的地方轉移到能夠處理這種異常的地方去。也就是說:當一個函數的某條語句發生異常時,這條語句的后面的語句不會再執行,它失去了焦點。執行流跳轉到最近的匹配的異常處理catch代碼塊去執行,異常被處理完后,執行流會接著在“處理了這個異常的catch代碼塊”后面接著執行。
有的編程語言當異常被處理后,控制流會恢復到異常拋出點接著執行,
這種策略叫做:resumption model of exception handling(恢復式異常處理模式)
而Java則是讓執行流恢復到處理了異常的catch塊后接著執行,
這種策略叫做:termination model of exception handling(終結式異常處理模式)
public static void main(String[] args){try {foo();}catch(ArithmeticException ae) {System.out.println("處理異常");}
}
public static void foo(){int a = 5/0; //異常拋出點System.out.println("Look me!!!"); //不會執行
}
finally塊不管異常是否發生,只要對應的try執行了,則它一定也執行。
只有一種方法讓finally塊不執行:System.exit()。
因此finally塊通常用來做資源釋放操作:關閉文件,關閉數據庫連接等等。
良好的編程習慣是:在try塊中打開資源,在finally塊中清理釋放這些資源。
需要注意的地方:
1、finally塊沒有處理異常的能力。處理異常的只能是catch塊。
2、在同一try…catch…finally塊中 ,如果try中拋出異常,且有匹配的catch塊,則先執行catch塊,再執行finally塊。如果沒有catch塊匹配,則先執行finally,然后去外面的調用者中尋找合適的catch塊。
3、在同一try…catch…finally塊中 ,try發生異常,且匹配的catch塊中處理異常時也拋出異常,那么后面的finally也會執行:首先執行finally塊,然后去外圍調用者中尋找合適的catch塊。
這是正常的情況,但是也有特例。關于finally有很多惡心,偏、怪、難的問題.
具體在最后一節:finally塊和return 講解
不捕獲異常時的情況:
前面使用的異常都是RuntimeException類或是它的子類,這些類的異常的特點是:即使沒有使用try和catch捕獲,Java自己也能捕獲,并且編譯通過( 但運行時會發生異常使得程序運行終止 )。
如果拋出的異常是IOException等類型的非運行時異常,則必須捕獲,否則編譯錯誤。也就是說,我們必須處理編譯時異常,將異常進行捕捉,轉化為運行時異常。
import java.io.*;public class IOExp {public static void main(String[] args) {try {FileInputStream in = new FileInputStream("hello.txt");int b;b = in.read();while (b != -1) {System.out.print((char) b);b = in.read();}in.close();} catch (IOException e) {System.out.println(e);} finally {System.out.println(" It’s ok!");}}
}
異常處理機制二:throws
throws是另一種處理異常的方式,它不同于try…catch…finally,throws僅僅是將函數中可能出現的異常向調用者聲明,而自己則不具體處理。
throws聲明:如果一個方法內部的代碼會拋出檢查異常(checked exception),而方法自己又沒有完全處理掉或并不能確定如何處理這種異常,則javac保證你必須在方法的簽名上使用throws關鍵字聲明這些可能拋出的異常,表明該方法將不對這些異常進行處理,而由該方法的調用者負責處理,否則編譯不通過。
在方法聲明中用throws語句可以聲明拋出異常的列表,throws后面的異常類型可以是方法中產生的異常類型,也可以是它的父類。
采取這種異常處理的原因可能是:方法本身不知道如何處理這樣的異常,或者說讓調用者處理更好,調用者需要為可能發生的異常負責。
語法格式:
修飾符 返回值類型 方法名() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN{
//方法內部可以拋出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 類的異常,或者他
們的子類的異常對象。
}
import java.io.*;public class ThrowsTest {public static void main(String[] args) {ThrowsTest t = new ThrowsTest();try {t.readFile();} catch (IOException e) {e.printStackTrace();}}public void readFile() throws IOException {FileInputStream in = new FileInputStream("hello.txt");int b;b = in.read();while (b != -1) {System.out.print((char) b);b = in.read();}in.close();}
}
4.4手動拋出異常:throw
Java異常類對象除在程序執行過程中出現異常時由系統自動生成并拋出,也可根據需要使用人工創建并拋出。
首先要生成異常類對象,然后通過throw語句實現拋出操作(提交給Java運行環境)。
throw exceptionObject
程序員也可以通過throw語句手動顯式的拋出一個異常。throw語句的后面可以拋出的異常必須是Throwable或其子類的實例。下面的語句在編譯時將會產生語法錯誤:
throw new String(“你拋我試試.”);
throw 語句必須寫在函數中,執行throw 語句的地方就是一個異常拋出點,它和由JRE自動形成的異常拋出點沒有任何差別。
public class StudentTest {public static void main(String[] args) {try {Student s = new Student();s.regist(-1001);System.out.println(s);} catch (Exception e) {System.out.println(e.getMessage());}}
}class Student {private int id;public void regist(int id) throws Exception {if (id > 0) {this.id = id;} else {// System.out.println("您輸入的數據非法!");//手動拋出異常對象// throw new RuntimeException("您輸入的數據非法!");throw new Exception("您輸入的數據非法!");//錯誤的// throw new String("不能輸入負數");}}@Overridepublic String toString() {return "Student [id=" + id + "]";}
}
throws和throw的區別:
throw是語句拋出一個異常。
語法:throw (異常對象);
throw e;
throws是方法可能拋出異常的聲明。(用在聲明方法時,表示該方法可能要拋出異常)
語法:(修飾符)(方法名)([參數列表])[throws(異常類)]{…}
public void doA(int a) throws Exception1,Exception3{…}
throw語句用在方法體內,表示拋出異常,由方法體內的語句處理。
throws出現在方法函數頭,表示在拋出異常,由該方法的調用者來處理。
throws主要是聲明這個方法會拋出這種類型的異常,使它的調用者知道要捕獲這個異常。
throw是具體向外拋異常的動作,所以它是拋出一個異常實例。throws說明你有那個可能,傾向。
throw的話,那就是你把那個傾向變成真實的了。
兩者都是消極處理異常的方式(這里的消極并不是說這種方式不好),只是拋出或者可能拋出異常,但是不會由函數去處理異常,真正的處理異常由函數的上層調用處理。
原文鏈接:鏈接描述
5.理解OOP面向對象
面向對象有哪些特性?
封裝,繼承,多態
1、封裝就是將類的信息隱藏在類內部,不允許外部程序直接訪問,而是通過該類的方法實現對隱藏信息的操作和訪問。 良好的封裝能夠減少耦合。
2、繼承是從已有的類中派生出新的類,新的類繼承父類的屬性和行為,并能擴展新的能力,大大增加程序的重用性和易維護性。在Java中是單繼承的,也就是說一個子類只有一個父類。
3、多態是同一個行為具有多個不同表現形式的能力。在不修改程序代碼的情況下改變程序運行時綁定的代碼。實現多態的三要素:繼承、重寫、父類引用指向子類對象。
靜態多態性:通過重載實現,相同的方法有不同的參數列表,可以根據參數的不同,做出不同的處理。
動態多態性:在子類中重寫父類的方法。運行期間判斷所引用對象的實際類型,根據其實際類型調用相應的方法。
6.Java的特點
Java是一門面向對象的編程語言。
Java具有平臺獨立性和移植性。
Java有一句口號:Write once, run anywhere,一次編寫、到處運行。這也是Java的魅力所在。而實現這種特性的正是Java虛擬機JVM。已編譯的Java程序可以在任何帶有JVM的平臺上運行。你可以在windows平臺編寫代碼,然后拿到linux上運行。只要你在編寫完代碼后,將代碼編譯成.class文件,再把class文件打成Java包,這個jar包就可以在不同的平臺上運行了。
Java具有穩健性。
Java是一個強類型語言,它允許擴展編譯時檢查潛在類型不匹配問題的功能。Java要求顯式的方法聲明,它不支持C風格的隱式聲明。這些嚴格的要求保證編譯程序能捕捉調用錯誤,這就導致更可靠的程序。
異常處理是Java中使得程序更穩健的另一個特征。異常是某種類似于錯誤的異常條件出現的信號。使用try/catch/finally語句,程序員可以找到出錯的處理代碼,這就簡化了出錯處理和恢復的任務。
Java是如何實現跨平臺的?
Java是通過JVM(Java虛擬機)實現跨平臺的。
JVM可以理解成一個軟件,不同的平臺有不同的版本。我們編寫的Java代碼,編譯后會生成.class 文件(字節碼文件)。Java虛擬機就是負責將字節碼文件翻譯成特定平臺下的機器碼,通過JVM翻譯成機器碼之后才能運行。不同平臺下編譯生成的字節碼是一樣的,但是由JVM翻譯成的機器碼卻不一樣。
只要在不同平臺上安裝對應的JVM,就可以運行字節碼文件,運行我們編寫的Java程序。
因此,運行Java程序必須有JVM的支持,因為編譯的結果不是機器碼,必須要經過JVM的翻譯才能執行。
Java 與 C++ 的區別
Java 是純粹的面向對象語言,所有的對象都繼承自 java.lang.Object,
C++ 兼容 C ,不但支持面向對象也支持面向過程。Java 通過虛擬機從而實現跨平臺特性, C++ 依賴于特定的平臺。Java 沒有指針,它的引用可以理解為安全指針,而 C++ 具有和 C 一樣的指針。Java 支持自動垃圾回收,而 C++ 需要手動回收。Java 不支持多重繼承,只能通過實現多個接口來達到相同目的,而 C++ 支持多重繼承。
7.JDK/JRE/JVM三者的關系
JVM
英文名稱(Java Virtual Machine),就是我們耳熟能詳的 Java 虛擬機。Java 能夠跨平臺運行的核心在于 JVM 。
所有的java程序會首先被編譯為.class的類文件,這種類文件可以在虛擬機上執行。也就是說class文件并不直接與機器的操作系統交互,而是經過虛擬機間接與操作系統交互,由虛擬機將程序解釋給本地系統執行。
針對不同的系統有不同的 jvm 實現,有 Linux 版本的 jvm 實現,也有Windows 版本的 jvm 實現,但是同一段代碼在編譯后的字節碼是一樣的。這就是Java能夠跨平臺,實現一次編寫,多處運行的原因所在。
JRE
英文名稱(Java Runtime Environment),就是Java 運行時環境。我們編寫的Java程序必須要在JRE才能運行。它主要包含兩個部分,JVM 和 Java 核心類庫。
JRE是Java的運行環境,并不是一個開發環境,所以沒有包含任何開發工具,如編譯器和調試器等。
如果你只是想運行Java程序,而不是開發Java程序的話,那么你只需要安裝JRE即可。
JDK
英文名稱(Java Development Kit),就是 Java 開發工具包
學過Java的同學,都應該安裝過JDK。當我們安裝完JDK之后,目錄結構是這樣的
可以看到,JDK目錄下有個JRE,也就是JDK中已經集成了 JRE,不用單獨安裝JRE。
另外,JDK中還有一些好用的工具,如jinfo,jps,jstack等。
最后,總結一下JDK/JRE/JVM,他們三者的關系
JRE = JVM + Java 核心類庫JDK = JRE + Java工具 + 編譯器 + 調試器
8.面向對象和面向過程的區別?
面向對象和面向過程是一種軟件開發思想。
面向過程就是分析出解決問題所需要的步驟,然后用函數按這些步驟實現,使用的時候依次調用就可以了。
面向對象是把構成問題事務分解成各個對象,分別設計這些對象,然后將他們組裝成有完整功能的系統。
面向過程只用函數實現,面向對象是用類實現各個功能模塊。
9.八大數據類型
整數:byte ,short,int ,long
小數:float,double
字符:char
布爾型:boolean
byte,8bit
char,16bit
short,16bit
int,32bit
float,32bit
long,64bit
double,64bit
boolean,只有兩個值:true、false,可以使?用 1 bit 來存儲
為什么不能用浮點型表示金額?
由于計算機中保存的小數其實是十進制的小數的近似值,并不是準確值,所以,千萬不要在代碼中使用浮點數來表示金額等重要的指標。
建議使用BigDecimal或者Long來表示金額。
10.什么是值傳遞和引用傳遞?
值傳遞是對基本型變量而言的,傳遞的是該變量的一個副本,改變副本不影響原變量。
引用傳遞一般是對于對象型變量而言的,傳遞的是該對象地址的一個副本,并不是原對象本身,兩者指向同一片內存空間。所以對引用對象進行操作會同時改變原對象。
java中不存在引用傳遞,只有值傳遞。即不存在變量a指向變量b,變量b指向對象的這種情況。