{eval=Array;=+count(Array);}
你好,我是大師兄,計(jì)算機(jī)專業(yè)的。做過兩年多的Java開發(fā)。我來給你回答吧。
對(duì)于新手來說,剛學(xué)習(xí)Java,是要多練習(xí)寫代碼的。但是你要說刷題的話,一般是指的算法類題目比較多。但是刷算法類的題目并不有助于你學(xué)習(xí)Java,因?yàn)檫@類題目的重點(diǎn)在算法上面。
新手小白想要學(xué)習(xí)Java,但一般不僅僅是涉及學(xué)習(xí)Java,還通常包括Web開發(fā),一般這一類的學(xué)習(xí)通常有很多的框架需要去學(xué),如果你想要通過它來找到一份好職業(yè),就必須要經(jīng)過一系列系統(tǒng)的學(xué)習(xí),才能穩(wěn)操勝券。
根據(jù)我個(gè)人的專業(yè)和學(xué)習(xí)經(jīng)驗(yàn),給你幾點(diǎn)學(xué)習(xí)的建議。
想要快速上手,加深各方面的技巧,通過相關(guān)的培訓(xùn)課程來學(xué)習(xí)之后,直接上手做小項(xiàng)目。
但是前期還是得先做些算法小題來熟悉java語法基礎(chǔ),比如你學(xué)完面向?qū)ο蠛蚃ava基本類型之后,可以嘗試去做一做LeetCode、牛客網(wǎng)上的一些題,或者一些面試題。
學(xué)習(xí)了swing之后(其實(shí)強(qiáng)烈不建議學(xué)習(xí)java的界面編程Swing AWT),可以做一些小項(xiàng)目了,比如記賬本、學(xué)生成績(jī)選課管理系統(tǒng)、打字小游戲、消消樂等等。在娛樂中編程,會(huì)體驗(yàn)更多的樂趣。
學(xué)習(xí)JDBC之后,就可以把記賬本、學(xué)生選課系統(tǒng)對(duì)接上了,剛開始做的是基本版,然后就可以做成連接數(shù)據(jù)庫(kù)的版本。
后面學(xué)習(xí)集合、并發(fā)編程、IO、網(wǎng)絡(luò)可以嘗試做一做書上的課后題,推薦李剛的瘋狂Java講義,后面有課后題。
之后在深入的學(xué)習(xí)反射、JVM、動(dòng)態(tài)代理、設(shè)計(jì)模式。
工欲善其事,必先利其器。Java最強(qiáng)大的地方,在于它的工具種類繁多,框架層出不窮,當(dāng)一個(gè)先進(jìn)的思想出現(xiàn)時(shí),往往Java就是最先成熟運(yùn)用的那一個(gè)。學(xué)習(xí)利用優(yōu)秀的框架(尤其是開源框架),對(duì)于開發(fā)非常有幫助,提升開發(fā)效率,避免重復(fù)造輪子。
Java相關(guān)的框架繁多,數(shù)不勝數(shù),比較有名(基本是必學(xué)的框架)的有:Spring家族(Spring、SpringMVC、SpringData、SpringBoot、SpringCloud等等)、Hibernate、Mybatis。
建議這一塊的學(xué)習(xí)通過一個(gè)完整的項(xiàng)目來練習(xí),比如開發(fā)一個(gè)在線購(gòu)物商城系統(tǒng)。
你的路還很遠(yuǎn),一入Java深似海,能不能走出來看造化了!哈哈。
如果你喜歡這篇文章,歡迎點(diǎn)贊、評(píng)論、轉(zhuǎn)發(fā)!
我會(huì)經(jīng)常分享科技、計(jì)算機(jī)編程等方面的知識(shí)、經(jīng)驗(yàn),感興趣的話點(diǎn)個(gè)關(guān)注吧!
本人計(jì)算機(jī)科學(xué)與技術(shù)專業(yè),從事java有4年了。分享下自己的學(xué)習(xí)網(wǎng)站吧。
1.牛客網(wǎng)
主要服務(wù)于國(guó)內(nèi)廣大程序員。產(chǎn)品規(guī)模很大,包括了it題庫(kù)、在線編程練習(xí)、線上課程、社區(qū)、筆試服務(wù)、還有競(jìng)賽。用戶基本覆蓋全國(guó)高校百萬的程序員學(xué)習(xí)者。在國(guó)內(nèi)互聯(lián)網(wǎng)公司有良好的口碑,為國(guó)內(nèi)眾多的互聯(lián)網(wǎng)公司提供了校園招聘,競(jìng)賽等服務(wù)。具備基本每個(gè)領(lǐng)域的筆試算法題,值得收藏。
2.利扣 leetcode
這個(gè)網(wǎng)站有國(guó)際版和國(guó)內(nèi)版,平常我們進(jìn)國(guó)內(nèi)版的就行了啊,當(dāng)然英文好的也可以使用國(guó)際版,這里非常建議大家使用國(guó)際版,交流的技術(shù)存在差異,但是題目基本一致,不需要擔(dān)心。
地址:leetcode-cn.com
利扣被國(guó)內(nèi)外程序員稱為刷題神器。甚至有人說,你如果掌握了百分之80左右,各互聯(lián)網(wǎng)公司提供的算法崗位你只要對(duì)比下誰的工資高就好了。
它基本覆蓋了全互聯(lián)網(wǎng)公司的算法題目,還有數(shù)據(jù)庫(kù)等技術(shù),并且提供了交流平臺(tái),國(guó)內(nèi)過各種大神將自己的解答想法分享出來,有些巧妙的解答確實(shí)會(huì)令人拍案叫絕。普遍都是國(guó)外人,但是國(guó)內(nèi)人也特別多,當(dāng)然是國(guó)際版才是這樣的。
如果單單是學(xué)習(xí)練習(xí)java編程的,這兩個(gè)網(wǎng)站可以滿足了,關(guān)鍵就是提升你的編程思維能力。
要學(xué)習(xí)java核心技術(shù)還是建議購(gòu)買java相關(guān)書籍或者在網(wǎng)上課堂學(xué)習(xí)。
如果是想找高質(zhì)量面試題的話不妨看看動(dòng)力節(jié)點(diǎn)官網(wǎng)上面試題也是非常全面新鮮的!
1、String類可以被繼承嗎?
String類在聲明時(shí)使用final關(guān)鍵字修飾,被final關(guān)鍵字修飾的類無法被繼承。
接下來我們可以看一下String類的源代碼片段:
public final class String implements java.io.Serializable, Comparable<String>,CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -6849794470754667710L;
● 為什么Java語言的開發(fā)者,把String類定義為final的呢?
因?yàn)橹挥挟?dāng)字符串是不可變的,字符串池才有可能實(shí)現(xiàn)。字符串池的實(shí)現(xiàn)可以在運(yùn)行時(shí)節(jié)約很多heap空間,因?yàn)椴煌淖址兞慷贾赶虺刂械耐粋€(gè)字符串。但如果字符串是可變的,那么String interning將不能實(shí)現(xiàn),因?yàn)檫@樣的話,如果變量改變了它的值,那么其它指向這個(gè)值的變量的值也會(huì)一起改變。如果字符串是可變的,那么會(huì)引起很嚴(yán)重的安全問題。譬如,數(shù)據(jù)庫(kù)的用戶名、密碼都是以字符串的形式傳入來獲得數(shù)據(jù)庫(kù)的連接,或者在socket編程中,主機(jī)名和端口都是以字符串的形式傳入。因?yàn)樽址遣豢勺兊模运闹凳遣豢筛淖兊模駝t黑客們可以鉆到空子,改變字符串指向的對(duì)象的值,造成安全漏洞。
因?yàn)樽址遣豢勺兊模允嵌嗑€程安全的,同一個(gè)字符串實(shí)例可以被多個(gè)線程共享。這樣便不用因?yàn)榫€程安全問題而使用同步。字符串自己便是線程安全的。
因?yàn)樽址遣豢勺兊模栽谒鼊?chuàng)建的時(shí)候HashCode就被緩存了,不需要重新計(jì)算。這就使得字符串很適合作為Map中的鍵,字符串的處理速度要快過其它的鍵對(duì)象。這就是HashMap中的鍵往往都使用字符串。
● final關(guān)鍵字除了修飾類之外,還有哪些用法呢?
final修飾的變量,一旦賦值,不可重新賦值;
final修飾的方法無法被覆蓋;
final修飾的實(shí)例變量,必須手動(dòng)賦值,不能采用系統(tǒng)默認(rèn)值;
final修飾的實(shí)例變量,一般和static聯(lián)用,用來聲明常量;
注意:final不能和abstract關(guān)鍵字聯(lián)合使用。
總之,final表示最終的、不可變的。
2、& 和 && 的區(qū)別?
● &運(yùn)算符是:邏輯與;&&運(yùn)算符是:短路與。
● &和&&在程序中最終的運(yùn)算結(jié)果是完全一致的,只不過&&存在短路現(xiàn)象,當(dāng)&&運(yùn)算符左邊的表達(dá)式結(jié)果為false的時(shí)候,右邊的表達(dá)式不執(zhí)行,此時(shí)就發(fā)生了短路現(xiàn)象。如果是&運(yùn)算符,那么不管左邊的表達(dá)式是true還是false,右邊表達(dá)式是一定會(huì)執(zhí)行的。這就是他們倆的本質(zhì)區(qū)別。
● 當(dāng)然,&運(yùn)算符還可以使用在二進(jìn)制位運(yùn)算上,例如按位與操作。
3、兩個(gè)對(duì)象值相同equals結(jié)果為true,但卻可有不同的 hashCode,這句話對(duì)不對(duì)?
不對(duì),如果兩個(gè)對(duì)象x和y滿足x.equals(y) == true,它們的哈希值(hashCode)應(yīng)當(dāng)相同。Java 對(duì)于equals方法和hashCode方法是這樣規(guī)定的:
(1)如果兩個(gè)對(duì)象相同(equals方法返回true),那么它們的hashCode值一定要相同;
(2)如果兩個(gè)對(duì)象的 hashCode相同,它們并不一定相同。當(dāng)然,你未必按照要求去做,但是如果你違背了上述原則就會(huì)發(fā)現(xiàn)在使用集合時(shí),相同的對(duì)象可以出現(xiàn)在Set 集合中,同時(shí)增加新元素的效率會(huì)大大降低(對(duì)于使用哈希存儲(chǔ)的系統(tǒng),如果哈希碼頻繁的沖突將會(huì)造成存取性能急劇下降)。
關(guān)于equals和hashCode方法,很多Java程序員都知道,但很多人也就是僅僅了解而已,在Joshua Bloch的大作《Effective Java》(《Effective Java》在很多公司,是Java程序員必看書籍,如果你還沒看過,那就趕緊去買一本吧)中是這樣介紹 equals 方法的:
首先equals方法必須滿足自反性(x.equals(x)必須返回true)、對(duì)稱性(x.equals(y)返回true 時(shí),y.equals(x)也必須返回true)、傳遞性(x.equals(y)和y.equals(z)都返回true時(shí),x.equals(z)也必須返回true)和一致性(當(dāng)x和y引用的對(duì)象信息沒有被修改時(shí),多次調(diào)用x.equals(y)應(yīng)該得到同樣的返回值),而且對(duì)于任何非null值的引用x,x.equals(null)必須返回false。實(shí)現(xiàn)高質(zhì)量的equals方法的訣竅包括:
使用==操作符檢查"參數(shù)是否為這個(gè)對(duì)象的引用";
使用 instanceof操作符檢查"參數(shù)是否為正確的類型";
對(duì)于類中的關(guān)鍵屬性,檢查參數(shù)傳入對(duì)象的屬性是否與之相匹配;
編寫完equals方法后,問自己它是否滿足對(duì)稱性、傳遞性、一致性;
重寫equals時(shí)總是要重寫hashCode;
不要將equals方法參數(shù)中的Object對(duì)象替換為其他的類型,在重寫時(shí)不要忘掉@Override注解。
4、在 Java 中,如何跳出當(dāng)前的多重嵌套循環(huán)?
在最外層循環(huán)前加一個(gè)標(biāo)記如outfor,然后用break outfor;可以跳出多重循環(huán)。例如以下代碼:
public class TestBreak {
public static void main(String[] args) {
outfor: for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
if (j == 5){
break outfor;
}
System.out.println("j = " + j);
}
}
}
}
運(yùn)行結(jié)果如下所示:
j = 0
j = 1
j = 2
j = 3
j = 4
5、重載(overload)和重寫(override)的區(qū)別?重載的方法能否根據(jù)返回類型進(jìn)行區(qū)分?
方法的重載和重寫都是實(shí)現(xiàn)多態(tài)的方式,區(qū)別在于前者實(shí)現(xiàn)的是編譯時(shí)的多態(tài)性,而后者實(shí)現(xiàn)的是運(yùn)行時(shí)的多態(tài)性。
重載發(fā)生在一個(gè)類中,同名的方法如果有不同的參數(shù)列表(類型不同、個(gè)數(shù)不同、順序不同)則視為重載。
重寫發(fā)生在子類與父類之間,重寫要求子類重寫之后的方法與父類被重寫方法有相同的返回類型,比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常(里氏代換原則)。重載對(duì)返回類型沒有特殊的要求。
● 方法重載的規(guī)則:
方法名一致,參數(shù)列表中參數(shù)的順序,類型,個(gè)數(shù)不同。
重載與方法的返回值無關(guān),存在于父類和子類,同類中。
可以拋出不同的異常,可以有不同修飾符。
● 方法重寫的規(guī)則:
參數(shù)列表、方法名、返回值類型必須完全一致;
構(gòu)造方法不能被重寫;
聲明為 final 的方法不能被重寫;
聲明為 static 的方法不存在重寫(重寫和多態(tài)聯(lián)合才有意義);
訪問權(quán)限不能比父類更低;
重寫之后的方法不能拋出更寬泛的異常;
6、當(dāng)一個(gè)對(duì)象被當(dāng)作參數(shù)傳遞到一個(gè)方法后,此方法可改變這個(gè)對(duì)象的屬性,并可返回變化后的結(jié)果,那么這里是值傳遞還是引用傳遞?
是值傳遞。Java 語言的方法調(diào)用只支持參數(shù)的值傳遞。當(dāng)一個(gè)對(duì)象實(shí)例作為一個(gè)參數(shù)被傳遞到方法中時(shí),參數(shù)的值就是對(duì)該對(duì)象的內(nèi)存地址。這個(gè)值(內(nèi)存地址)被傳遞后,同一個(gè)內(nèi)存地址指向堆內(nèi)存當(dāng)中的同一個(gè)對(duì)象,所以通過哪個(gè)引用去操作這個(gè)對(duì)象,對(duì)象的屬性都是改變的。
7、為什么方法不能根據(jù)返回類型來區(qū)分重載?
我們來看以下的代碼:
public void testMethod(){
doSome();
}
public void doSome(){
}
public int doSome(){
return 1;
}
在Java語言中,調(diào)用一個(gè)方法,即使這個(gè)方法有返回值,我們也可以不接收這個(gè)返回值,例如以上兩個(gè)方法doSome(),在testMethod()中調(diào)用的時(shí)候,Java編譯器無法區(qū)分調(diào)用的具體是哪個(gè)方法。所以對(duì)于編譯器來說,doSome()方法不是重載而是重復(fù)了,編譯器報(bào)錯(cuò)。所以區(qū)分這兩個(gè)方法不能依靠方法的返回值類型。
8、抽象類(abstract class)和接口(interface)有什么異同?
不同點(diǎn):
● 抽象類中可以定義構(gòu)造器,接口不能;
● 抽象類可以有抽象方法和具體方法,接口不能有具體方法;
● 接口中的成員全都是 public 的,抽象類中的成員可以使用private、public、protected、默認(rèn)等修飾;
● 抽象類中可以定義成員變量,接口中只能是常量;
● 有抽象方法的類必須被聲明為抽象類,而抽象類未必要有抽象方法;
● 抽象類中可以包含靜態(tài)方法,接口中不能有靜態(tài)方法;
● 一個(gè)類只能繼承一個(gè)抽象類,一個(gè)類可以實(shí)現(xiàn)多個(gè)接口;
相同點(diǎn):
● 不能夠?qū)嵗?/p>
● 可以將抽象類和接口類型作為引用類型;
● 一個(gè)類如果繼承了某個(gè)抽象類或者實(shí)現(xiàn)了某個(gè)接口都需要對(duì)其中的抽象方法全部進(jìn)行實(shí)現(xiàn),否則該類仍然需要被聲明為抽象類;
9、char 型變量中能不能存儲(chǔ)一個(gè)中文漢字,為什么?
char 類型可以存儲(chǔ)一個(gè)中文漢字,因?yàn)镴ava中使用的編碼是Unicode(不選擇任何特定的編碼,直接使用字符在字符集中的編號(hào),這是統(tǒng)一的唯一方法),一個(gè)char 類型占2個(gè)字節(jié)(16 比特),所以放一個(gè)中文是沒問題的。
補(bǔ)充:使用Unicode 意味著字符在JVM內(nèi)部和外部有不同的表現(xiàn)形式,在JVM內(nèi)部都是 Unicode,當(dāng)這個(gè)字符被從JVM內(nèi)部轉(zhuǎn)移到外部時(shí)(例如存入文件系統(tǒng)中),需要進(jìn)行編碼轉(zhuǎn)換。所以 Java 中有字節(jié)流和字符流,以及在字符流和字節(jié)流之間進(jìn)行轉(zhuǎn)換的轉(zhuǎn)換流,如 InputStreamReader和OutputStreamReader,這兩個(gè)類是字節(jié)流和字符流之間的適配器類,承擔(dān)了編碼轉(zhuǎn)換的任務(wù)。
10、抽象的(abstract)方法是否可同時(shí)是靜態(tài)的(static), 是否可同時(shí)是本地方法(native),是否可同時(shí)被 synchronized?
都不能。
● 抽象方法需要子類重寫,而靜態(tài)的方法是無法被重寫的,因此二者是矛盾的。
● 本地方法是由本地代碼(如 C++ 代碼)實(shí)現(xiàn)的方法,而抽象方法是沒有實(shí)現(xiàn)的,也是矛盾的。
● synchronized 和方法的實(shí)現(xiàn)細(xì)節(jié)有關(guān),抽象方法不涉及實(shí)現(xiàn)細(xì)節(jié),因此也是相互矛盾的。
1、面向?qū)ο蟀男┨匦裕趺蠢斫獾模?/strong>
(1)封裝:通常認(rèn)為封裝是把數(shù)據(jù)和操作數(shù)據(jù)的方法綁定起來,對(duì)數(shù)據(jù)的訪問只能通過已定義的接口。面向?qū)ο蟮谋举|(zhì)就是將現(xiàn)實(shí)世界描繪成一系列完全自治、封閉的對(duì)象。我們?cè)陬愔芯帉懙姆椒ň褪菍?duì)實(shí)現(xiàn)細(xì)節(jié)的一種封裝;我們編寫一個(gè)類就是對(duì)數(shù)據(jù)和數(shù)據(jù)操作的封裝。可以說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡(jiǎn)單的編程接口。
(2)繼承:繼承是從已有類得到繼承信息創(chuàng)建新類的過程。提供繼承信息的類被稱為父類(超類、基類);得到繼承信息的類被稱為子類(派生類)。繼承讓變化中的軟件系統(tǒng)有了一定的延續(xù)性,同時(shí)繼承也是封裝程序中可變因素的重要手段。
(3)多態(tài):多態(tài)性是指允許不同子類型的對(duì)象對(duì)同一消息作出不同的響應(yīng)。簡(jiǎn)單的說就是用同樣的對(duì)象引用調(diào)用同樣的方法但是做了不同的事情。多態(tài)性分為編譯時(shí)的多態(tài)性和運(yùn)行時(shí)的多態(tài)性。如果將對(duì)象的方法視為對(duì)象向外界提供的服務(wù),那么運(yùn)行時(shí)的多態(tài)性可以解釋為:當(dāng) A系統(tǒng)訪問B系統(tǒng)提供的服務(wù)時(shí),B 系統(tǒng)有多種提供服務(wù)的方式,但一切對(duì) A 系統(tǒng)來說都是透明的。方法重載(overload)實(shí)現(xiàn)的是編譯時(shí)的多態(tài)性(也稱為前綁定),而方法重寫(override)實(shí)現(xiàn)的是運(yùn)行時(shí)的多態(tài)性(也稱為后綁定)。運(yùn)行時(shí)的多態(tài)是面向?qū)ο笞罹璧臇|西,要實(shí)現(xiàn)多態(tài)需要做兩件事:
第一:方法重寫(子類繼承父類并重寫父類中已有的或抽象的方法);
第二:對(duì)象造型(用父類型引用指向子類型對(duì)象,這樣同樣的引用調(diào)用同樣的方法就會(huì)根據(jù)子類對(duì)象的不同而表現(xiàn)出不同的行為)。
(4)抽象:抽象是將一類對(duì)象的共同特征總結(jié)出來構(gòu)造類的過程,包括數(shù)據(jù)抽象和行為抽象兩方面。抽象只關(guān)注對(duì)象有哪些屬性和行為,并不關(guān)注這些行為的細(xì)節(jié)是什么。
2、訪問權(quán)限修飾符 public、private、protected, 以及不寫(默認(rèn))時(shí)的區(qū)別?
修飾符
當(dāng)前類
同包
子類
其他包
public
√
√
√
√
protected
√
√
√
×
默認(rèn)(缺省)
√
√
×
×
private
√
×
×
×
3、Java中為什么要用 clone?
在實(shí)際編程過程中,我們常常要遇到這種情況:有一個(gè)對(duì)象 A,在某一時(shí)刻 A 中已經(jīng)包含了一些有效值,此時(shí)可能會(huì)需要一個(gè)和 A 完全相同新對(duì)象 B,并且此后對(duì) B 任何改動(dòng)都不會(huì)影響到 A 中的值,也就是說,A 與 B 是兩個(gè)獨(dú)立的對(duì)象,但 B 的初始值是由 A 對(duì)象確定的。在 Java 語言中,用簡(jiǎn)單的賦值語句是不能滿足這種需求的。要滿足這種需求雖然有很多途徑,但clone()方法是其中最簡(jiǎn)單,也是最高效的手段。
● 說到對(duì)象的克隆,涉及到深克隆和淺克隆?
淺克隆:創(chuàng)建一個(gè)新對(duì)象,新對(duì)象的屬性和原來對(duì)象完全相同,對(duì)于非基本類型屬性,仍指向原有屬性所指向的對(duì)象的內(nèi)存地址。
深克隆:創(chuàng)建一個(gè)新對(duì)象,屬性中引用的其他對(duì)象也會(huì)被克隆,不再指向原有對(duì)象地址。
4、new一個(gè)對(duì)象的過程和clone一個(gè)對(duì)象的區(qū)別?
new 操作符的本意是分配內(nèi)存。程序執(zhí)行到 new 操作符時(shí),首先去看 new 操作符后面的類型,因?yàn)橹懒祟愋停拍苤酪峙涠啻蟮膬?nèi)存空間。分配完內(nèi)存之后,再調(diào)用構(gòu)造函數(shù),填充對(duì)象的各個(gè)域,這一步叫做對(duì)象的初始化,構(gòu)造方法返回后,一個(gè)對(duì)象創(chuàng)建完畢,可以把他的引用(地址)發(fā)布到外部,在外部就可以使用這個(gè)引用操縱這個(gè)對(duì)象。
clone 在第一步是和 new 相似的,都是分配內(nèi)存,調(diào)用 clone 方法時(shí),分配的內(nèi)存和原對(duì)象(即調(diào)用 clone 方法的對(duì)象)相同,然后再使用原對(duì)象中對(duì)應(yīng)的各個(gè)域,填充新對(duì)象的域,填充完成之后,clone方法返回,一個(gè)新的相同的對(duì)象被創(chuàng)建,同樣可以把這個(gè)新對(duì)象的引用發(fā)布到外部。
5、Java中實(shí)現(xiàn)多態(tài)的機(jī)制是什么?
Java中的多態(tài)靠的是父類或接口定義的引用變量可以指向子類或具體實(shí)現(xiàn)類的實(shí)例對(duì)象,而程序調(diào)用的方法在運(yùn)行期才動(dòng)態(tài)綁定,就是引用變量所指向的具體實(shí)例對(duì)象的方法,也就是內(nèi)存里正在運(yùn)行的那個(gè)對(duì)象的方法,而不是引用變量的類型中定義的方法。
6、談?wù)勀銓?duì)多態(tài)的理解?
多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量到底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的方法,必須在程序運(yùn)行期間才能決定。因?yàn)樵诔绦蜻\(yùn)行時(shí)才確定具體的類,這樣,不用修改源代碼,就可以讓引用變量綁定到各種不同的對(duì)象上,從而導(dǎo)致該引用調(diào)用的具體方法隨之改變,即不修改程序代碼就可以改變程序運(yùn)行時(shí)所綁定的具體代碼,讓程序可以選擇多個(gè)運(yùn)行狀態(tài),這就是多態(tài)性。
7、談?wù)勀銓?duì)面向?qū)ο蟮睦斫猓?/strong>
所謂對(duì)象就是由一組數(shù)據(jù)結(jié)構(gòu)和處理它們的方法組成的,重點(diǎn)“數(shù)據(jù)”包括對(duì)象的特性、狀態(tài)等的靜態(tài)信息;“方法” 也就是行為,包括該對(duì)象的對(duì)數(shù)據(jù)的操作、功能等能動(dòng)信息。把相同行為的對(duì)象歸納為類,類是一個(gè)抽象的概念,對(duì)象是類的具體。簡(jiǎn)單點(diǎn)說:對(duì)象就是類的實(shí)例。例如:小品演員就是一個(gè)類,趙本山就是一個(gè)對(duì)象。
面向?qū)ο蟮哪康模航鉀Q軟件系統(tǒng)的可擴(kuò)展性,可維護(hù)性和可重用性。
● 面向?qū)ο蟮娜筇匦裕悍庋b、多態(tài)和繼承:
(1)封裝(對(duì)應(yīng)可擴(kuò)展性):隱藏對(duì)象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對(duì)外公開接口,控制在程序中屬性的讀和修改的訪問級(jí)別。封裝是通過訪問控制符(public protected private)來實(shí)現(xiàn)。一個(gè)類就可看成一個(gè)封裝。
(2)繼承(重用性和擴(kuò)展性):子類繼承父類,可以繼承父類的方法和屬性。可以對(duì)父類方向進(jìn)行覆蓋(實(shí)現(xiàn)了多態(tài))。但是繼承破壞了封裝,因?yàn)樗菍?duì)子類開放的,修改父類會(huì)導(dǎo)致所有子類的改變,因此繼承一定程度上又破壞了系統(tǒng)的可擴(kuò)展性,只有明確的IS-A關(guān)系才能使用。繼承要慎用,盡量?jī)?yōu)先使用組合。
(3)多態(tài)(可維護(hù)性和可擴(kuò)展性):接口的不同實(shí)現(xiàn)方式即為多態(tài)。接口是對(duì)行為的抽象,剛才在封裝提到,找到變化部分并封裝起來,但是封裝起來后,怎么適應(yīng)接下來的變化?這正是接口的作用,接口的主要目的是為不相關(guān)的類提供通用的處理服務(wù),我們可以想象一下。比如鳥會(huì)飛,但是超人也會(huì)飛,通過飛這個(gè)接口,我們可以讓鳥和超人,都實(shí)現(xiàn)這個(gè)接口。
面向?qū)ο缶幊蹋∣OP)其實(shí)就是一種設(shè)計(jì)思想,在程序設(shè)計(jì)過程中把每一部分都盡量當(dāng)成一個(gè)對(duì)象來考慮,以實(shí)現(xiàn)軟件系統(tǒng)的可擴(kuò)展性,可維護(hù)性和可重用性。
1、final、finally、finalize 的區(qū)別?
● final:用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,被其修飾的類不可繼承。
● finally:異常處理語句結(jié)構(gòu)的一部分,表示總是執(zhí)行。
● finalize:Object 類的一個(gè)方法,所以Java對(duì)象都有這個(gè)方法,當(dāng)某Java對(duì)象沒有更多的引用指向的時(shí)候,會(huì)被垃圾回收器回收,該對(duì)象被回收之前,由垃圾回收器來負(fù)責(zé)調(diào)用此方法,通常在該方法中進(jìn)行回收前的準(zhǔn)備工作。該方法更像是一個(gè)對(duì)象生命周期的臨終方法,當(dāng)該方法被系統(tǒng)調(diào)用則代表該對(duì)象即將“死亡”,但是需要注意的是,我們主動(dòng)行為上去調(diào)用該方法并不會(huì)導(dǎo)致該對(duì)象“死亡”,這是一個(gè)被動(dòng)的方法(其實(shí)就是回調(diào)方法),不需要我們調(diào)用。
按照異常需要處理的時(shí)機(jī)分為編譯時(shí)異常(也叫受控異常)也叫 CheckedException 和運(yùn)行時(shí)異常(也叫非受控異常)也叫 UnCheckedException。Java認(rèn)為Checked異常都是可以被處理的異常,所以Java程序必須顯式處理Checked異常。如果程序沒有處理Checked 異常,該程序在編譯時(shí)就會(huì)發(fā)生錯(cuò)誤無法編譯。這體現(xiàn)了Java 的設(shè)計(jì)哲學(xué):沒有完善錯(cuò)誤處理的代碼根本沒有機(jī)會(huì)被執(zhí)行。對(duì)Checked異常處理方法有兩種:
● 第一種:當(dāng)前方法知道如何處理該異常,則用try...catch塊來處理該異常。
● 第二種:當(dāng)前方法不知道如何處理,則在定義該方法時(shí)聲明拋出該異常。
運(yùn)行時(shí)異常只有當(dāng)代碼在運(yùn)行時(shí)才發(fā)行的異常,編譯的時(shí)候不需要try…catch。Runtime如除數(shù)是0和數(shù)組下標(biāo)越界等,其產(chǎn)生頻繁,處理麻煩,若顯示申明或者捕獲將會(huì)對(duì)程序的可讀性和運(yùn)行效率影響很大。所以由系統(tǒng)自動(dòng)檢測(cè)并將它們交給缺省的異常處理程序。當(dāng)然如果你有處理要求也可以顯示捕獲它們。
Error類和Exception類的父類都是Throwable類,他們的區(qū)別如下:
● Error類一般是指與虛擬機(jī)相關(guān)的問題,如系統(tǒng)崩潰,虛擬機(jī)錯(cuò)誤,內(nèi)存空間不足,方法調(diào)用棧溢出等。對(duì)于這類錯(cuò)誤的導(dǎo)致的應(yīng)用程序中斷,僅靠程序本身無法恢復(fù)和預(yù)防,遇到這樣的錯(cuò)誤,建議讓程序終止。
● Exception類表示程序可以處理的異常,可以捕獲且可能恢復(fù)。遇到這類異常,應(yīng)該盡可能處理異常,使程序恢復(fù)運(yùn)行,而不應(yīng)該隨意終止異常。
●Exception類又分為未檢查異常(UnCheckedException)和受檢查的異常(CheckedException)。運(yùn)行時(shí)異常ArithmeticException,IllegalArgumentException編譯能通過,但是一運(yùn)行就終止了,程序不會(huì)處理運(yùn)行時(shí)異常,出現(xiàn)這類異常,程序會(huì)終止。而受檢查的異常,要么用 try…catch 捕獲,要么用throws字句聲明拋出,交給它的父類處理,否則編譯不會(huì)通過。
1. public int getNum() {
2. try {
3. int a = 1 / 0;
4. return 1;
5. } catch (Exception e) {
6. return 2;
7. } finally {
8. return 3;
9. }
10.}
代碼走到第3行的時(shí)候遇到了一個(gè)MathException,這時(shí)第4行的代碼就不會(huì)執(zhí)行了,代碼直接跳轉(zhuǎn)到catch語句中,走到第 6 行的時(shí)候,異常機(jī)制有一個(gè)原則:如果在catch中遇到了return或者異常等能使該函數(shù)終止的話那么有finally就必須先執(zhí)行完finally代碼塊里面的代碼然后再返回值。因此代碼又跳到第8行,可惜第8行是一個(gè)return語句,那么這個(gè)時(shí)候方法就結(jié)束了,因此第6行的返回結(jié)果就無法被真正返回。如果finally僅僅是處理了一個(gè)釋放資源的操作,那么該道題最終返回的結(jié)果就是2。因此上面返回值是3。
Java對(duì)異常進(jìn)行了分類,不同類型的異常分別用不同的Java類表示,所有異常的根類為 java.lang.Throwable,Throwable下面又派生了兩個(gè)子類:Error和Exception。
Error表示應(yīng)用程序本身無法克服和恢復(fù)的一種嚴(yán)重問題。
Exception表示程序還能夠克服和恢復(fù)的問題,其中又分為系統(tǒng)異常和普通異常。
系統(tǒng)異常是軟件本身缺陷所導(dǎo)致的問題,也就是軟件開發(fā)人員考慮不周所導(dǎo)致的問題,軟件使用者無法克服和恢復(fù)這種問題,但在這種問題下還可以讓軟件系統(tǒng)繼續(xù)運(yùn)行或者讓軟件死掉,例如,數(shù)組下標(biāo)越界(ArrayIndexOutOfBoundsException),空指針異常(NullPointerException)、類轉(zhuǎn)換異常(ClassCastException)。
普通異常是運(yùn)行環(huán)境的變化或異常所導(dǎo)致的問題,是用戶能夠克服的問題,例如,網(wǎng)絡(luò)斷線,硬盤空間不夠,發(fā)生這樣的異常后,程序不應(yīng)該死掉。
Java為系統(tǒng)異常和普通異常提供了不同的解決方案,編譯器強(qiáng)制普通異常必須try..catch處理或用throws聲明繼續(xù)拋給上層調(diào)用方法處理,所以普通異常也稱為checked異常,而系統(tǒng)異常可以處理也可以不處理,所以編譯器不強(qiáng)制用try..catch處理或用throws聲明,所以系統(tǒng)異常也稱為unchecked異常。
● java.lang.NullPointerException 空指針異常;出現(xiàn)原因:調(diào)用了未經(jīng)初始化的對(duì)象或者是不存在的對(duì)象。
● java.lang.ClassNotFoundException 指定的類找不到;出現(xiàn)原因:類的名稱和路徑加載錯(cuò)誤;通常都是程序試圖通過字符串來加載某個(gè)類時(shí)可能引發(fā)異常。
● java.lang.NumberFormatException 字符串轉(zhuǎn)換為數(shù)字異常;出現(xiàn)原因:字符型數(shù)據(jù)中包含非數(shù)字型字符。
● java.lang.IndexOutOfBoundsException 數(shù)組角標(biāo)越界異常,常見于操作數(shù)組對(duì)象時(shí)發(fā)生。
● java.lang.IllegalArgumentException 方法傳遞參數(shù)錯(cuò)誤。
● java.lang.ClassCastException 數(shù)據(jù)類型轉(zhuǎn)換異常。
● java.lang.NoClassDefFoundException 未找到類定義錯(cuò)誤。
● SQLException SQL 異常,常見于操作數(shù)據(jù)庫(kù)時(shí)的 SQL 語句錯(cuò)誤。
● java.lang.InstantiationException 實(shí)例化異常。
● java.lang.NoSuchMethodException 方法不存在異常。
● throw:
throw 語句用在方法體內(nèi),表示拋出異常,由方法體內(nèi)的語句處理。
throw是具體向外拋出異常的動(dòng)作,所以它拋出的是一個(gè)異常實(shí)例,執(zhí)行throw一定是拋出了某種異常。
● throws:
throws語句是用在方法聲明后面,表示如果拋出異常,由該方法的調(diào)用者來進(jìn)行異常的處理。
throws主要是聲明這個(gè)方法會(huì)拋出某種類型的異常,讓它的使用者要知道需要捕獲的異常的類型。
● throws表示出現(xiàn)異常的一種可能性,并不一定會(huì)發(fā)生這種異常。
核心推薦:LintCode / LeetCode / 牛客網(wǎng)
不是什么程序員,但是大一大二大三自己都是自學(xué)過來一直學(xué)到JavaEE的,還是有些經(jīng)驗(yàn)的。
JavaSE階段,找個(gè)牛逼點(diǎn)的基礎(chǔ)視頻課聽過后,建議找一些小游戲編著玩,貪吃蛇啊2048啊坦克大戰(zhàn)啊,學(xué)習(xí)一下怎么一步步搭出一個(gè)小游戲。可以找網(wǎng)上的視頻課,網(wǎng)易云課堂還有一些培訓(xùn)機(jī)構(gòu)都有做小游戲的視頻,聽老師一步步講思路后,自己嘗試一下他的思路是要怎么做,敲完后再比對(duì)一下。
基本做了三個(gè)小游戲下來,Java就不是很陌生的東西了,這時(shí)候建議上LintCode或者LeetCode刷題,每天兩到三小時(shí)在這上面。里面的題都是最常規(guī)的API解決各種面試用算法題。沒系統(tǒng)學(xué)過算法?也不要緊,建議買本《算法》橙皮書,然后先從LeetCode之類的簡(jiǎn)單題做起,不懂就看discuss或者別人博客是怎么想的,看懂后自己不看別人代碼實(shí)現(xiàn)一遍。
其中如果牽涉到某個(gè)算法,比如動(dòng)態(tài)規(guī)劃,你從未接觸過,不要怕,這道題放著,翻開橙皮書現(xiàn)學(xué)唄,看不懂慢慢看,看完后盲敲示例代碼,這樣對(duì)基本代碼素養(yǎng)有很大幫助。啃完這個(gè)知識(shí)點(diǎn),再回去繼續(xù)刷題。
私以為,JavaSE階段最重要的不是IO操作啊什么的,還是LeetCode里面向招聘的算法題。
如果你很想加強(qiáng)Java文件流和網(wǎng)絡(luò),網(wǎng)上找視頻做個(gè)JavaSE聊天項(xiàng)目或者文件收發(fā)項(xiàng)目是最簡(jiǎn)單的,跟學(xué)一次練一次就沒有大問題了。
線程很重要。多線程是很復(fù)雜的,其中牽涉到的知識(shí)還得專門看諸如《并發(fā)編程實(shí)戰(zhàn)》之類書來提升,建議前期了解基本的同步操作就夠了,等到學(xué)到JavaEE階段,會(huì)用SSMH這些框架后,再來開始邊做項(xiàng)目,邊研究線程同步這種問題。
剛?cè)腴T的話推薦你去慕課網(wǎng),還有B站上有黑馬,尚硅谷的java教學(xué)視頻,視頻質(zhì)量都是很不錯(cuò)的。
可以去找些面試的題目來練手。或者繼續(xù)學(xué)習(xí)算法,然后拿算法題練手。如果會(huì)前端,還可以自己開發(fā)個(gè)網(wǎng)站,或者微信小程序,服務(wù)端用JAVA.
0
回答0
回答0
回答10
回答0
回答0
回答0
回答0
回答0
回答8
回答