Java-核心技術-面試整理


【前方高能,是這半年BAT,京東,遠景,華為,中興以及蘇研發中心被問到的Java公共問題的一個整理】

-----------------------------------------------------------------------------------------------------------------------------------------------

1、.java源文件:

一個以”.java“為后綴的源文件:只能有一個與文件名相同的類,可以包含其他類。

2、類方法:

類方法:類中用static修飾的方法(非static為實例方法)

在類方法中調用本類的類方法時,可以直接調用。

在類方法中不能有this關鍵字,直接調用類方法即可。

類方法中可以通過創建實例對象調用類的實例方法。

3、super和this關鍵字

在子類構造器中使用super()顯示調用父類的構造方法,super()必須寫在子類構造方法的第一行,否則編譯不通過;

this:

屬性:this屬性表示找到本類的屬性,如果本類沒有找到則繼續查找父類;

方法:this方法表示找到本類的方法,如果本類沒有找到則繼續查找父類;

構造:必須放在構造方法的首行,不能與super關鍵字同時出現;

特殊:表示當前對象;

super:

屬性:super屬性直接在子類之中查找父類中的指定屬性,不再查找子類本身屬性;

方法:super方法直接在子類之中查找父類中的指定方法,不再查找子類本身方法;

構造:必須放在構造方法首行,不能與this關鍵字同時出現。

super和this關鍵字

1)調用super()必須寫在子類構造方法的第一行,否則編譯不通過。每個子類構造方法的第一條語句,都是隱含地調用super(),如果父類沒有這種形式的構造函數,那么在編譯的時候就會報錯。

2)super從子類中調用父類的構造方法,this()在同一類內調用其它方法。

3)super()和this()均需放在構造方法內第一行。

4)盡管可以用this調用一個構造器,但卻不能調用兩個。

5)this和super不能同時出現在一個構造函數里面,因為this必然會調用其它的構造函數,其它的構造函數必然也會有super語句的存在,所以在同一個構造函數里面有相同的語句,就失去了語句的意義,編譯器也不會通過。

6)this()和super()都指的是對象,所以,均不可以在static環境中使用。包括:static變量,static方法,static語句塊。

7)從本質上講,this是一個指向本對象的指針, 然而super是一個Java關鍵字。

4、抽象類

 1、抽象類不能被實例化,實例化的工作應該交由它的子類來完成,它只需要有一個引用即可。

 2、抽象方法必須由子類來進行重寫。

 3、只要包含一個抽象方法的類,該類必須要定義成抽象類,不管是否還包含有其他方法。

 4、抽象類中可以包含具體的方法,當然也可以不包含抽象方法。

 5、子類中的抽象方法不能與父類的抽象方法同名。

 6、abstract不能與final並列修飾同一個類。(abstract需要子類去實現,而final表示不能被繼承,矛盾。)

 7、abstract 不能與private、static、final或native並列修飾同一個方法。

A、final修飾的類為終態類,不能被繼承,而抽象類是必須被繼承的才有其意義的,因此,final是不能用來修飾抽象類的。

B、 final修飾的方法為終態方法,不能被重寫。而繼承抽象類,必須重寫其方法。

C、抽象方法是僅聲明,並不做實現的方法。

5、訪問權限:

(1)訪問權限修飾詞:

1)public(公共的):表明該成員變量或方法對所有類或對象都是可見的,所有類或對象都可以直接訪問;

2)protected(受保護的):表明成員變量或方法對該類本身&與它在同一個包中的其它類&在其它包中的該類的子類都可見;

3)default(默認的,不加任何訪問修飾符):表明成員變量或方法只有自己&其位於同一個包內的類可見;

4)private(私有的):表明該成員變量或方法是私有的,只有當前類對其具有訪問權限。

由大到小:public(接口訪問權限)、protected(繼承訪問權限)、包訪問權限(沒有使用任何訪問權限修飾詞)、private(私有無法訪問)

protected表示就類用戶而言,這是private的,但對於任何繼承於此類的導出類或其他任何位於同一個包內的類來說,卻是可以訪問的。(protected也提供了包內訪問權限)

private和protected一般不用來修飾外部類,而public、abstract或final可以用來修飾外部類(如果用private和protected修飾外部類,會使得該類變得訪問性受限)。

(2)訪問權限注意點:

1、類的訪問權限,只能是包訪問權限(默認無訪問修飾符即可)或者public。若把一個類中的構造器指定為private,則不能訪問該類,若要創建該類的對象,則需要再該類的static成員內部創建,如單例模式。

2、如果沒能為類訪問權限指定一個訪問修飾符,默認得到包訪問權限,則該類的對象可以由包內任何其他類創建,但是包外不可以。

3、訪問權限的控制,也稱為具體實現的隱藏。制定規則(如使用訪問權限,設定成員所遵守的界限),是防止客戶端程序員對類隨心所欲而為。

(3)控制對成員的訪問權限的兩個原因:

·       使用戶不要碰觸那些不該碰觸的部分,對類內部的操作是必要的,不屬於客戶端程序員所需接口的一部分;

·       讓類庫設計者可以更改類的內部工作方式,而不會對客戶端程序員產生重大影響;訪問權限控制可以確保不會有任何客戶端程序員依賴於類的底層實現的任何部分。

(4)對某成員的訪問權的唯一途徑:

·       1.該成員為public;

·       2.通過不加訪問權限修飾詞並將其他類放置在同一個包內的方式給成員賦予包訪問權。

·       3.繼承技術,訪問protected成員

·       4.提供訪問器和變異器(get/set方法),以讀取和改變數值。

6、值傳遞與引用傳遞

值傳遞:Java中原始數據類型都是值傳遞,傳遞的是值的副本,形參的改變不會影響實際參數的值;

引用傳遞: 傳遞的是引用類型數據,包括String,數組,列表,map,類對象等類型,形參與實參指向的是同一內存地址,因此形參改變會影響實參的值。

7、封裝:

把數據和方法包裝進類中,以及實現的隱藏,共同稱作封裝。結果是一個同時帶有特征和行為的數據類型。

8、組合、繼承:

(1)組合:

定義:只需在新的類中產生現有類的對象,由於新的類是由現有類的對象所組成, 稱為組合。組合技術知識將對象引用置於新類中即可。

缺點:將一個成員對象置於所要構造的類中(組合),在新類中暴露這個成員對象的所有方法(繼承),需要折中(代理),可以選擇只提供在成員對象中的方法的某個子集。

特點:

·       1.has-a關系用組合;

·       2.組合技術通常用於想在新類中使用現有類的功能而非它的接口這種情形。在新類中嵌入某個對象,讓其實現所需要的功能,但新類的用戶看到的只是為新類所定義的接口,而非所嵌入對象的接口。

(2)繼承:

定義:按照現有類的類型來創建新類 ,無需改變現有類的形式,采用現有類的形式並在其增加新代碼,稱為繼承。通過關鍵字extends實現。

特點:

·       1.當創建一個類時,總在繼承。(除非明確指明繼承類,否則都是隱式第繼承根類Object)

·       2.為了繼承,一般將所有的數據成員都指定為private,將所有的方法指定為public。

·       3.可以將繼承視作是對類的復用;

·       4.is-a關系用繼承;

·       5.繼承允許對象視為自身的類型或其基類型加以處理;

·       6.如果向上轉型,不能調用那些新的方法(如Animal an = new Cat(),an是不能調用Cat中有的而Animal中沒有的方法,會返回一條編譯時出錯消息),所以向上轉型會丟失具體的類型信息;

注意:

1.構造方法不能被繼承;方法和屬性可以被繼承;

2.子類的構造方法隱式地調用父類的不帶參數的構造方法;

3.當父類沒有不帶參數的構造方法時,子類需要使用super來顯示調用父類的構造方法,super指的是對父類的引用

4.super關鍵字必須是構造方法中的第一行語句。特例如下

當兩個方法形成重寫關系時,可在子類方法中通過super.run()形式調用父類的run()方法,其中super.run()不必放在第一行語句,因此此時父類對象已經構造完畢,先調用父類的run()方法還是先調用子類的run()方法是根據程序的邏輯決定的。

總結:

代理使用時,可以擁有更多的控制力,可以選擇只提供在成員對象中的方法的某個子集;

組合和繼承都允許在新的類中放置子對象,組合是顯式地放置,繼承是隱式的做;

組合和繼承都能從現有類型中生成新類,組合一般是將現有類型作為新類型底層實現的一部分加以復用,而繼承復用的是接口。優先使用組合。

9、final關鍵字

1)使用范圍:數據、方法和類

2)final關鍵字:final可以修飾屬性、方法、類。

3)final修飾類:當一個類被final所修飾時,表示該類是一個終態類,即不能被繼承。

4)final修飾方法:當一個方法被final所修飾時,表示該方法是一個終態方法,即不能被重寫(Override)。

5)final修飾屬性:當一個屬性被final所修飾時,表示該屬性不能被改寫。

(1)final數據:

·       1.編譯時常量:是使用static和 final修飾的常量,全用大寫字母命名,且字與字之間用下划線隔開。(不能因為數據是final的就認為在編譯時就知道值,在運行時也可以用某數值來初始化某一常量)

·       2.final修飾基本數據類型和對象引用:對於基本類型,final修飾的數值是恆定不變;而final修飾對象引用,則引用恆定不變(一旦引用被初始化指向一個對象,就不能改為指向另一個對象),但是對象本身的內容可以修改。

·       3.空白final:空白final是指被聲明為final但又未給定初值的域,無論什么情況,編譯器都保證空白final在使用被初始化。必須在域的定義處或每個構造器中用表達式對final進行賦值。

·       4.final參數:final修飾參數后,在方法體中不允許對參數進行更改,只可以讀final參數。主要用於向匿名類傳遞數據。

(2)final方法:

·       1.使用final修飾方法原因:將方法鎖定以及效率問題。將方法鎖定:防止任何繼承類修改final方法的含義,確保該方法行為保持不變,且不會被覆蓋;效率:早期Java實現中同意編譯器將針對該方法的所有調用轉為內嵌調用。

·       2.類中所有的private方法都隱式地指定為final的。

(3)final類:

·       1.將某個類整體定義為final時,則不繼承該類,不能有子類。

10、初始化及類的加載

1.加載的含義:通常,加載發生在創建類的第一個對象時,但訪問static域或static方法時,也會發生加載。static的東西只會初始化一次。

2.加載過程:加載一個類的時候,首先去加載父類的靜態域,然后再加載自身的靜態域,之后去初始化父類的成員變量,后加載父類的構造方法,最后初始化自身的成員變量,后加載自身的構造方法。(先初始化成員變量,后加載構造函數的原因是,構造函數中可能要用到這些成員變量)

父類靜態塊——子類靜態塊——父類塊——父類構造器——子類塊——子類構造器

最終版本:父類靜態域——父類靜態塊——子類靜態域——子類靜態塊——父類成員變量及代碼塊——父類構造器——子類成員變量及代碼塊——子類構造器。

3.加載次數:加載的動作只會加載一次,該類的靜態域或第一個實體的創建都會引起加載。

4.變量的初始化:變量的初始化總是在當前類構造器主體執行之前進行的,且static的成員比普通的成員變量先初始化。

11、多態

1.多態只發生在普通方法中,對於域和static方法,不發生多態。子類對象轉化為父類型引用時,對於任何域的訪問都是由編譯器解析。靜態方法是與類相關聯,而不與單個對象相關聯;

2.在繼承時,若被覆寫的方法不是private,則父類調用方法時,會調用子類的方法,常用的多態性就是當父類引用指向子類對象時。

3.多態就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時並不確定,而是在程序運行期間才確定,即一個引用變量到底指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。

4.多態是同一個行為具有多個不同表現形式或形態的能力。

5.多態就是同一個接口,使用不同的實例而執行不同操作,多態性是對象多種表現形式的體現。

12、構造器

1.為什么強制每個導出類部分都必須調用構造器的原因?(基類的構造器總是在導出類的構造過程中被調用)

只有基類的構造器才具有恰當的知識和權限對自己的元素進行初始化,因此必須令所有的構造器都得到調用。導出類只能訪問自己的成員,不能訪問基類中的成員(通常是private類型)。

2.編寫構造器原則:用盡可能的簡單的方法使對象進入正常狀態;如果可以的話,避免調用其他方法,因為調用這些方法,有可能會導致初始化未進行,調用的是0值,在構造器內唯一能夠安全調用的方法是基類中的final方法(調用不能被覆蓋的方法)。

13、基本數據類型與包裝類

所有的包裝類(8個)都位於java.lang包下,分別是Byte,Short,Integer,Long,Float,Double,Character,Boolean

基本數據類型:byte:8位;short:16位;int:32位;long:64位;float:32位;double:64位;char:16位;boolean:8位。

 

14、==與equals方法的區別:

(1)基本數據類型與引用數據類型

1.基本數據類型的比較:只能用==;

2.引用數據類型的比較:==是比較棧內存中存放的對象在堆內存地址,equals是比較對象的內容是否相同;

(2)特殊:String作為一個對象

例子一:通過構造函數創建對象時。對象不同,內容相同,"=="返回false,equals返回true

String s1 = newString("java");
String s2 = new String("java");

System.out.println(s1==s2);            //false
System.out.println(s1.equals(s2));   //true

例子二:同一對象,"=="和equals結果相同

String s1 = newString("java");
String s2 = s1;  //兩個不同的引用變量指向同一個對象

System.out.println(s1==s2);            //true
System.out.println(s1.equals(s2));   //true

如果值不相同,對象就不相同,所以"=="和equals結果一樣

String s1 = "java";
String s2 = "java";   //此時String常量池中有java對象,直接返回引用給s2;

System.out.println(s1==s2);            //true

System.out.println(s1.equals(s2));    //true

字面量形式創建對象時:

如果String緩沖池內不存在與其指定值相同的String對象,那么此時虛擬機將為此創建新的String對象,並存放在String緩沖池內。

如果String緩沖池內存在與其指定值相同的String對象,那么此時虛擬機將不為此創建新的String對象,而直接返回已存在的String對象的引用。

(3)String的字面量形式和構造函數創建對象

1)String s = "aaa";采用字面值方式賦值

1.查找StringPool中是否存再“aaa”這個對象,如果不存在,則在StringPool中創建一個“aaa”對象,然后將String Pool中的這個“aaa”對象的地址返回來,賦給引用變量s,這樣s會指向String Pool中的這個“aaa”字符串對象;

2.如果存在,則不創建任何對象,直接將String Pool中的這個“aaa”對象地址返回來,賦給s引用。

2)String s = new String("aaa");

1.首先在StringPool中查找有沒有"aaa"這個字符串對象,如果有,則不在String Pool中再去創建"aaa"這個對象,直接在堆中創建一個"aaa"字符串對象,然后將堆中的這個"aaa"對象的地址返回來,賦給s引用,導致s指向了堆中創建的這個"aaa"字符串對象;

2.如果沒有,則首先在String Pool中創建一個"aaa"對象,然后再去堆中創建一個"aaa"對象,然后將堆中的這個"aaa"對象的地址返回來,賦給s引用,導致s指向了堆中所創建的這個"aaa"對象。

15、Object類的公有方法

clone()(protected的)、toString()、equals(Object obj)、hashCode()、getClass()、finialize()(protected的)、notify()/notifyAll()、wait()/wait(long timeout)、wait(long timeout,intnaos)

16、try-catch-finally

·       1.finally里面的代碼一定會執行的;

·       2.當try和catch中有return時,先執行return中的運算結果但是先不返回,然后保存下來計算結果,接着執行finally,最后再返回return的值。

·       3.finally中最好不要有return,否則,直接返回,而先前的return中計算后保存的值得不到返回。

17、面向對象的三大基本特征

封裝、繼承和多態

(1)封裝

隱藏一切可以隱藏的消息,只向外界提供最簡單的編程接口;類就是對數據和方法的封裝;方法就是對具體實現細節的封裝;

(2)繼承

從已有的類繼承得到繼承信息,創建新類的過程,並無需重新編寫與原來的類相同的方法或成員變量情況下就可以對這些功能進行擴展。

(3)多態

允許父類型的引用指向子類型的對象。

實現方式:方法重載(編譯器綁定,前綁定)和方法重寫(運行期綁定,后綁定)

18、靜態類和非靜態類

(1)靜態類

靜態類中的字段與方法都必須是static的,靜態類不需要實例化就可以使用;

(2)非靜態類

非靜態類中可以有static的字段與方法,也可以由非static的字段與方法,訪問static的字段與方法不需要實例化,但是訪問非static的字段與方法時需要實例化。

19、for和foreach循環效率:

for可以不逐個遍歷,如每隔一個遍歷;也可以從前向后遍歷,從后向前遍歷;有條件判斷,使用已知次數的循環遍歷;

foreach只能逐個遍歷;只能從前向后遍歷;沒有執行條件限制,不能向迭代變量賦值;適合集合的遍歷;

如果遍歷集合或數組時,如果需要訪問集合或數組的下標,則最好使用舊式的方式來實現循環或遍歷,而不要使用增強的for循環,因為它丟失了下標信息。

20、JNIjava native interface

設計作用:主要實現和其他語言的通信,c和c++。標准的Java類庫中可能不支持程序所需的特性,或已經有了一個用其他語言編寫的庫或程序,但是現在希望用到Java程序中,則需要使用JNI。

使用場景:JDBC實現連接數據庫,Thread.sleep()方法。

21、pach和classpath的區別

path是windows的環境屬性,用於指定可執行命令的路徑;classpath是指在Java程序執行的時候,用於指定類的加載路徑。

22、final、finally、finalize的區別

final是Java的一個關鍵字,用於定義不能被繼承的類,不能被覆寫的方法,不能修改的常量。

finally是Java的一個關鍵字,是異常處理操作的統一出口。

finalize是Object類中所提供的一個方法,用於在對象回收之前進行收尾操作。

final

修飾符(關鍵字)如果一個類被聲明為final,意味着它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被聲明為 abstract的,又被聲明為final的。將變量或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變量必須在聲明時給定初值,而在以后的引用中只能讀取,不可修改。被聲明為final的方法不可以重寫(父子類繼承關系),但是可以重載(同一個類中)。

finally

異常處理時提供 finally 塊來執行任何清除操作。如果拋出一個異常,那么相匹配的 catch 子句就會執行,然后控制就會進入 finally 塊(如果有的話)。一般異常處理塊需要。

finalize

·       方法名,Java技術允許使用 finalize() 方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者執行其他清理工作。finalize() 方法是在垃圾收集器刪除對象之前對這個對象調用的。 

·       Java中所有類都從Object類中繼承finalize()方法。

·       當垃圾回收器(garbage colector)決定回收某對象時,就會運行該對象的finalize()方法。值得C++程序員注意的是,finalize()方法並不能等同與析構函數。Java中是沒有析構函數的。C++的析構函數是在對象消亡時運行的。由於C++沒有垃圾回收,對象空間手動回收,所以一旦對象用不到時,程序員就應當把它delete()掉。所以析構函數中經常做一些文件保存之類的收尾工作。但是在Java中很不幸,如果內存總是充足的,那么垃圾回收可能永遠不會進行,也就是說filalize()可能永遠不被執行,顯然指望它做收尾工作是靠不住的。

·       那么finalize()究竟是做什么的呢?它最主要的用途是回收特殊渠道申請的內存。Java程序有垃圾回收器,所以一般情況下內存問題不用程序員操心。但有一種JNI(JavaNative Interface)調用non-Java程序(C或C++),finalize()的工作就是回收這部分的內存。

23、Java實現可移植性的原理

Java程序最終通過字節碼文件運行,運行的時候字節碼需要JVM支持,但是在不同的操作系統中有不同的JVM,程序不用關心操作系統,只關心JVM,只要JVM不改變,程序可以在操作系統間任意移植。

24、Java的數據類型划分

1)當若干個變量參與運算時,結果類型取決於這些變量中表示范圍最大的那個變量類型,如有整型int,有雙精度浮點型double,有短整型short,則最后的結果類型為double。

 

2)取模

 

數據類型

默認值

基本數據類型

 

數值型:整型:byte、short、int、long

浮點型:float、double

0

字符型:char

'\u0000'

布爾型:boolean

false

引用數據類型

 

數組、類、接口

null

25、&和&&、|和||的區別

·       &(普通與)和|(普通或)是指所有條件都需要判斷;

·       &&稱為邏輯與(短路與)是如果前面的條件不滿足false,則后面的不再進行判斷;||稱為邏輯或(短路或)如果前面的條件滿足true則后面的不再判斷;

·       在開發之中為了性能的提高,不需要所有條件進行判斷,所以使用短路與和短路或操作;

·       &和|除了用於邏輯運算以外,還進行位運算的操作。

·       

26、String對象的兩種實例化方式的區別

1.首先String對象的實例化有兩種:直接賦值和構造方法完成。

2.直接賦值:在常量池中創建該字符串;

3.構造方法:先判斷在字符串常量池中是否包含該字符串,若包含該字符串,則在堆中直接創建這個字符串對象並返回該對象引用;若不包含,則先在堆上創建,然后在字符串常量池中也創建,最后把返回堆上對象引用。

27、throw和throws區別

1.throw是語句拋出一個異常。

語法:throw (異常對象);

          throw e;

throws是方法可能拋出異常的聲明。(用在聲明方法時,表示該方法可能要拋出異常)

語法:[(修飾符)](返回值類型)(方法名)([參數列表])[throws(異常類)]{......}

           public void doA(int a) throws Exception1,Exception3{......}

2.throw語句用在方法體內,表示拋出異常,由方法體內的語句處理;throws語句用在方法聲明后面,表示再拋出異常,由該方法的調用者來處理。

3.throw是具體向外拋異常的動作,已經發生異常,被捕獲到,要拋出該異常,所以它是拋出一個異常實例;throws主要是聲明這個方法會拋出這種類型的異常,使它的調用者知道要捕獲這個異常,傾向於發生,但不一定發生。

28、枚舉(Enums)

1.當使用“enum”定義枚舉類型時,實質上是繼承java.lang.Enum類型;

2.每個枚舉的成員其實就是定義的枚舉類型的一個實例,他們都被預設為final,所以無法改變他們,也是static成員,所以可以通過類型名稱直接使用它們,且他們是公開的public的。

3.特性:final static public的。

4.在編譯時期就確定該枚舉類型具有幾個實例,分別是什么。在運行期間我們無法再使用該枚舉類型創建新的實例,這些實例在編譯期間就已經完全確定下來。

29、遞歸

  Recursion,就是方法調用自身,對於遞歸來說,一定有一個出口,讓遞歸結束,只有這樣才能保證不出現死循環。

30、可變參數

1.可變參數本質上就是一個數組,對於某個聲明了可變參數的方法來說,既可以傳遞離散的值,也可以傳遞數組對象。

2.如果將方法中的參數定義為數組,則只能傳遞數組對象而不能傳遞離散的值。

3.可變參數必須要作為方法參數的最后一個參數,即一個方法不可能具有兩個或以上的可變參數。

31、靜態導入

1.使用靜態導入import static時,要一直導入到類中的靜態成員變量或靜態方法。

如:

import static com.ljy.exercise.Person.age;

import staticcom.ljy.exercise.Person.printlnPersonName;

32、集合的元素

集合中存放的依然是對象的引用,而不是對象本身。

集合無法放置原生數據類型,所以需要使用原生數據類型的包裝類將其轉換為真正的類型。

33、一個類不能既是final的,又是abstract的

因為abstract的主要目的是定義一種約束:讓子類去實現這種約定,而final表示該類不能被繼承,這樣abstract希望該類可以被繼承與之矛盾。

34、靜態方法

1.static修飾方法,可以通過類名.靜態方法名的方式訪問,靜態方法只能繼承,不能重寫(Override)。

2.不能在靜態方法中使用this關鍵字;

3.靜態的只能訪問靜態的(因為靜態的代碼塊在構造方法之前就已經開始初始化,而此時非靜態的還未開始初始化,如果靜態能訪問非靜態的就會出現發生錯誤),非靜態的可以訪問一切。

35、局部變量和成員變量

局部變量使用前必須聲明並賦初值;成員變量使用前必須要聲明,但可以不賦初值。

 

36、引用類型

reference type,引用類型用在對象上,一個對象可以被多個引用所指向,但同一時刻,每個引用只能指向唯一的對象,如果一個對象被多個引用所指向,那么無論哪個引用對對象的屬性進行修改,都會反映到其他的引用中去。

37、方法和類的定義

(1)類的定義

修飾符 class 類的名字{

//類的內容(包含了屬性與方法)

}

(2)方法的定義

修飾符 返回類型 方法名稱([參數1,參數2,參數3...]){

//方法體

}

1)方法定義不能嵌套,一個方法中不能定義另一個方法,方法只能定義在類中。

2)形式參數:方法定義時的參數。

3)實際參數:方法調用時所賦予的具體值。

38、break和continue

1)break語句:經常用在循環語句中,用於跳出整個循環,執行循環后面的代碼。(如果雙重循環,在內循環中使用break,跳出內循環)

2)continue語句:經常用在循環語句中,用於跳出本次循環,開始下一次循環的執行。

3)break與continue可以搭配標簽使用。

39、變量的自增與自減運算

1)關於int b = a++,作用:先將a賦給b,然后再讓a自增1。

2)關於int b = ++a,作用:先將a的值自增1,然后再將自增后的a賦給b。

總結:哪個在前,就先做哪一步。

40、Arrays.sort底層實現

基本類型:采用調優的快速排序:當待排序元素小於7個的時候,采用插入排序。

對象類型:采用改進的歸並排序;

41、什么是跨平台性?原理是什么?

 

1)跨平台性:通過Java語言編寫的應用程序在不同的系統平台上都可以運行。

2)原理:只要在需要運行Java應用程序的操作系統上,先安裝一個Java虛擬機(JVM Java Virtual Machine)即可,由JVM來負責Java程序在該系統中的運行。因為有了JVM,所以同一個Java程序在三個不同的操作系統中都可以執行,這樣實現Java程序的跨平台性,也稱為Java具有良好的可移植性。

42、JRE與JDK

1)JRE:Java Runtime Environment,Java運行環境,包括JVM和Java程序所需的核心類庫等。

2)JDK:Java Development Kit,Java開發工具包,JDK是提供給Java開發人員使用的,其中包含了Java的開發工具(編譯工具javac.exe和打包工具jar.exe等),也包括了JRE。所以安裝JDK,就不用單獨安裝JRE。

3)如果是命令行模式:編譯器javac進行編譯:javac 源文件名.java——編譯通過后,對class字節碼文件運行:java 類名

4)運行與工作原理

 

5)path環境變量配置的作用:程序開發過程中,不能將源代碼寫入JDK的安裝目錄,因此需要將源程序保存到任意位置的指定目錄(英文目錄),所以需要使javac指令在任意目錄下可以運行。通過配置path環境變量,將javac指令所在目錄及JDK安裝目錄下的bin目錄配置到path變量下,即可使javac指令在任意目錄下運行。

6)使classpath目錄中的.class文件可以在任意目錄運行。

7)path和classpath的區別:path環境變量里面記錄的是可執行性文件,如.exe文件,對可執行文件先在當前路徑去找,如果沒找到就去path環境變量中配置的路徑去找。而classpath環境變量里記錄的是java類的運行文件所在的目錄。

43、反射

(1)反射機制

1)定義:JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。要想解剖一個類,必須先要獲取到該類的字節碼文件對象。而解剖使用的就是Class類中的方法.所以先要獲取到每一個字節碼文件對應的Class類型的對象.

2)獲取Class對象的三種方式

第一種方式:

Person p = new Person();

Class c = p.getClass();

第二種方式:任意類都具備一個class靜態屬性

Class c2 = Person.class;

第三種方式:將類名作為字符串傳遞給Class類的靜態方法forName

Class c3 =Class.forName("Person");

(2)動態代理

1)在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler接口,通過使用這個類和接口就可以生成動態代理對象。JDK提供的代理只能針對接口做代理。我們有更強大的代理cglib

2)Proxy類中的方法創建動態代理類對象

public static Object newProxyInstance(ClassLoaderloader,Class<?>[] interfaces,InvocationHandler h)

最終會調用InvocationHandler的方法

Proxy類中創建動態代理對象的方法的三個參數;

·       ClassLoader對象,定義了由哪個ClassLoader對象來對生成的代理對象進行加載;

·       Interface對象的數組,表示的是我將要給我需要代理的對象提供一組什么接口,如果我提供了一組接口給它,那么這個代理對象就宣稱實現了該接口(多態),這樣我就能調用這組接口中的方法了;

·       InvocationHandler對象,表示的是當我這個動態代理對象在調用方法的時候,會關聯到哪一個InvocationHandler對象上。

3)InvocationHandler

Object invoke(Object proxy,Method method,Object[] args)

每一個動態代理類都必須要實現InvocationHandler這個接口,並且每個代理類的實例都關聯到了一個handler,當我們通過代理對象調用一個方法的時候,這個方法的調用就會被轉發為由InvocationHandler這個接口的invoke 方法來進行調用。

InvocationHandler接口中invoke方法的三個參數:

·       proxy:代表動態代理對象

·       method:代表正在執行的方法

·       args:代表調用目標方法時傳入的實參

4)Proxy.newProxyInstance

創建的代理對象是在jvm運行時動態生成的一個對象,它並不是我們的InvocationHandler類型,也不是我們定義的那組接口的類型,而是在運行是動態生成的一個對象,並且命名方式都是這樣的形式,以$開頭,proxy為中,最后一個數字表示對象的標號。System.out.println(u.getClass().getName());

44、異常

(1)異常介紹

1)編譯時異常

除了RuntimeException及其子類,Exception中所有的子類都是,這種異常必須要處理,要不編譯通不過

2)運行時異常

RuntimeException及其子類都是,這種異常不用處理,編譯會通過,不過這樣的程序會有安全隱患,遇到這種異常是需要改代碼的

3)嚴重錯誤問題

用Error進行描述,這個問題發生后,一般不編寫針對代碼進行處理,而是要對程序進行修正.通常都是由虛擬機拋出的問題

(2)Throwable中方法

getMessage()

獲取異常信息,返回字符串。

toString()

獲取異常類名和異常信息,返回字符串。

printStackTrace()

獲取異常類名和異常信息,以及異常出現在程序中的位置。返回值void。

printStackTrace(PrintStream s)

通常用該方法將異常內容保存在日志文件中,以便查閱。

(3)throws和throw的區別

1)throws

·       用在方法聲明后面,跟的是異常類名;

·       可以跟多個異常類名,用逗號隔開;

·       表示拋出異常,由該方法的調用者來處理;

·       throws表示出現異常的一種可能性,並不一定會發生這些異常。

2)throw

·       用在方法體內,跟的是異常對象名;

·       只能拋出一個異常對象名;

·       表示拋出異常,由方法體內的語句處理;

·       throw則是拋出了異常,執行throw則一定拋出了某種異常 。

(4)try和throws區別

如果該功能內部可以將問題處理,用try,如果處理不了,則交由調用者處理,用throws進行拋出異常。

區別:后序程序需要運行,則用try;后序程序不需要繼續運行,則用throws;

45、面向對象:

1)思想:是站在現實世界的角度去抽象和解決問題,把數據和行為都看作是對象的一部分,可以讓程序員以符合現實世界的思維方式來編寫和組織程序。

2)原則:

單一職責:一個類只做它該做的事(高內聚);

開放封閉:對擴展開放,對修改關閉;

里氏替換:任何時候都可用子類型替換父類型;

依賴倒置:面向接口編程(抽象類型可被任何一個子類所替代);

合成聚和復用:優先使用聚合或合成關系復用代碼;

接口隔離:一個接口只應描述一種能力,接口應該是高內聚的(小而專一);

迪米特法則:最少知識原則,一個對象應對其他對象盡可能少的了解。

46、數組和容器的區別

1)效率:數組是一種效率最高的存儲和隨機訪問對象引用序列的方式,數組就是一個簡單的線性序列,這使得元素訪問非常快速,可以通過整型索引值訪問元素;

2)大小:數組對象的大小被固定,並且在其生命周期中不可改變;容器如ArrayList可以動態擴容,通過創建一個新實例,然后把舊實例中所有的引用移到新實例中,從而實現更多空間的自動分配;

3)數據類型:數組可以持有基本類型,數組持有某種具體類型,通過編譯器檢查,防止插入錯誤類型和抽取不當類型;容器通過泛型,指定並檢查它們所持有對象的類型,並且有了自動包裝機制,好像是能夠持有基本數據類型。

注意:數組的比較是是通過equals()方法,用來比較整個數組,同樣,此方法針對所有基類類型與Object都做了重載,數組相等的條件是元素個數必須相等,並且對應位置的元素也相等,這可以通過對每一個元素使用equals()作比較判斷。

47、Arrays的方法

java.util類庫中的Arrays類,有一套用於數組的static實用方法。有6個基本方法+1個asList()方法。

1)Arrays.asList():接收任意的序列或數組作為其參數,並將其轉變為List容器;

2)equals():用於比較兩個數組是否相等(deepEquals()用於多維數組);

3)fill():是用同一個數值進行填充數組的各個位置,針對對象而言,就是復制同一個引用進行填充;

4)sort():用於對數組排序;(對於數值排序,小於8的使用插入排序,大於等於8個元素使用快速排序;對於對象排序,使用合並排序);

5)binarySearch():用於在已經排序的數組中查找元素;

6)toString():差生數組的String表示;

7)hashCode():產生數組的散列碼;

48、equals()方法的5個條件

1)自反性。對任意x,x.equals(x)一定返回true;

2)對稱性。對任意x和y,如果y.equals(x)返回true,則x.equals(y)也返回true;

3)傳遞性。對任意x、y、z,如果有x.equals(y)返回true,y.equals(z)返回true,則x.equals(z)一定返回true;

4)一致性。對任意x和y,如果對象中用於等價比較的信息沒有改變,那么無論調用x.equals(y)多少次,返回的結果應該保持一致,要么一直是true,要么一直是false;

5)對任何不是null的x,x.equals(null)一定返回false。

默認的Object.equals()只是比較對象的地址。

49、public staticvoid main(String[] args)方法的必要性

1)是Java程序的入口方法,JVM在運行程序時,會首先查找main()方法;

2)public是權限修飾符,表明任何類或對象都可以訪問這個方法;

3)static表明main()方法是一個靜態方法,即方法中的代碼是存儲在靜態存儲區的,只要類加載后,就可以使用該方法而不需要通過實例化對象來訪問,可以直接通過類名。

4)main()不能用abstract修飾,但可以用final和synchronized修飾,且public與static的順序可以顛倒。

50、Java程序初始化的順序

(1)遵循3個原則:

1)靜態對象(變量)優先於非靜態對象(變量)初始化;

2)父類優先於子類進行初始化;

3)按照成員變量的定義順序進行初始化,

(2)初始化順序

父類靜態變量、父類靜態代碼塊、子類靜態變量、子類靜態代碼塊、父類非靜態變量、父類非靜態代碼塊、父類構造函數、子類非靜態變量、子類非靜態代碼塊、子類構造函數

51、Java變量類型

(1)變量類型

靜態變量、成員變量、局部變量

(2)變量類型的范圍

1)靜態變量:被static修飾的成員變量稱為靜態變量,靜態變量不依賴於特定的實例,而是被所有實例所共享,只要一個類被加載,JVM就會給類的靜態變量分配存儲空間,可以通過類名和實例變量名訪問靜態變量。

2)成員變量:作用范圍與類的實例化對象的作用范圍相同,當類被實例化時,成員變量就會在內存中分配空間並初始化,直到這個被實例化對象的生命周期結束時,成員變量的聲明周期才結束。

3)局部變量:作用域與可見性為它所在的花括號內。

52、ArrayList和LinkedList

1)實現接口:都實現了List接口;

2)底層:ArrayList底層是由數組支持;LinkedList底層是由雙向鏈表實現;

3)內存:ArrayList比LinkedList申請少的內存,因為LinkedList中的每個對象包含數據的同時還包含指向鏈表中前一個與后一個元素的引用;

4)操作:ArrayList不適合插入或刪除,需要移動后面的元素,但適合快速訪問;而LinkedList適合插入和刪除,因為開銷是固定的;

53、快速報錯機制

1)出現原因:在迭代遍歷某個容器的過程中,另一個進程介入其中,並且插入、刪除或修改此容器內的某個對象,則會出現問題:也許迭代過程已經處理過容器中得到該元素了,也許還沒處理,也許在調用size()之后容器的尺寸收縮了。

2)快速報錯(fail-fast)機制:探查容器上除了你的進程所進行的操作以外的所有變化,一旦發現其他進程修改容器,立即拋出ConcurrentModificationException異常,即不是使用復雜的算法在事后來檢查問題。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM