【刷题2022/5/3 用时160min】
1、
解析
HashMap的底層是由數(shù)組加鏈表實現(xiàn)的,對于每一個key值,都需要計算哈希值,然后通過哈希值來確定順序,并不是按照加入順序來存放的,因此可以認為是無序的,但不管是有序還是無序,它都一個自己的順序。故A錯。
最開始有Hashtable,Hashtable是不允許key和value的值為空的,但后來開發(fā)者認為有時候也會有key值為空的情況,因為可以允許null為空,通過查看HashMap的源代碼就知道:if(key = null) {putForNullKey(value);};
Map底層都是用key/value鍵值對的形式存放的
2、
解析
答案:C
A,我們寫java程序的時候只是設(shè)定事物的隔離級別,而不是去實現(xiàn)它
B,Hibernate是一個java的數(shù)據(jù)持久化框架,方便數(shù)據(jù)庫的訪問
C,事物隔離級別由數(shù)據(jù)庫系統(tǒng)實現(xiàn),是數(shù)據(jù)庫系統(tǒng)本身的一個功能
D,JDBC是java database connector,也就是java訪問數(shù)據(jù)庫的驅(qū)動
補充:
在數(shù)據(jù)庫操作中,為了有效保證并發(fā)讀取數(shù)據(jù)的正確性,提出的事務(wù)隔離級別;為了解決更新丟失,臟讀,不可重讀(包括虛讀和幻讀)等問題在標準SQL規(guī)范中,定義了4個事務(wù)隔離級別,分別為未授權(quán)讀取,也稱為讀未提交(read uncommitted);授權(quán)讀取,也稱為讀提交(read committed);可重復(fù)讀取(repeatable read);序列化(serializable).
3、
解析
答案:A
short類型轉(zhuǎn)為byte類型出錯
a1a2結(jié)果為int類型,轉(zhuǎn)為byte類型出錯(數(shù)值型變量在默認情況下為Int型,byte和short型在計算時會自動轉(zhuǎn)換為int型計算,結(jié)果也是int 型。所以a1a2的結(jié)果是int 型的)
4、
解析:
5、(歧義)
6、
下標越界問題:數(shù)組中有4個元素,小標范圍為0~3
A: x[5-3],小標為2 √
B: x[k], k的范圍0~3 √
C: x[k+5], 小標范圍為5~8 越界×
D: x[0], 小標為0 √
7、
Java單繼承多實現(xiàn),一個類只能繼承一個類,但是可以實現(xiàn)多個接口,也可以在繼承一個類的同時實現(xiàn)多個接口。單繼承(類),多實現(xiàn)(接口)
8、
解析
A選項是函數(shù)重載的體現(xiàn),一個類可以有多個參數(shù)列表不同的構(gòu)造方法。A選項正確。
B選項,構(gòu)造方法在對象被初始化時調(diào)用。B選項錯誤。
C選項,構(gòu)造方法只能在對象被初始化時調(diào)用,不能由其他方法調(diào)用。
D選項,構(gòu)造方法必須與類名相同。
9、
變量名稱 字節(jié) 位數(shù)
byte 1 8
short 2 16
int 4 32
long 8 64
float 4 32
double 8 64
char 2 16
boolean 1 8
10、
答案是C
在java中,數(shù)組是一個對象, 不是一種原生類,對象所以存放在堆中,又因為數(shù)組特性,是連續(xù)的,只有C不對
11、
解析
A選項:Java基本數(shù)據(jù)類型共有八大類,這八大數(shù)據(jù)類型又可分為四小類,分別是整數(shù)類型(byte/short/int/long)、浮點類型(float、double)、字符類型(char)和布爾類型(boolean),其中并不包括String。
B選項中是C語言當(dāng)中的String,Java的String雖然也是char類型的數(shù)組char[]實現(xiàn)的,但并不以“\0”結(jié)尾。
C選項正確,String類重寫了Object類的equals()方法,使用equals()方法可以用于比較兩個String是否內(nèi)容一樣。
D選項, char 類型的編碼是Unicode 編碼。
12、
13、
方法重載要求函數(shù)名完全相同,參數(shù)列表不同(數(shù)量,類型或位置均可),返回值類型不影響。
A和C的函數(shù)名與原來函數(shù)名不相同。
B的參數(shù)列表與原函數(shù)列表相同。
14、
\ 將下一字符標記為特殊字符、文本、反向引用或八進制轉(zhuǎn)義符。例如,“n"匹配字符"n”?!癨n"匹配換行符。序列”\“匹配”“,”(“匹配”(“。
^ 匹配輸入字符串開始的位置。如果設(shè)置了 RegExp 對象的 Multiline 屬性,^ 還會與”\n"或"\r"之后的位置匹配。
$ 匹配輸入字符串結(jié)尾的位置。如果設(shè)置了 RegExp 對象的 Multiline 屬性,$ 還會與"\n"或"\r"之前的位置匹配。
- 零次或多次匹配前面的字符或子表達式。例如,zo* 匹配"z"和"zoo"。* 等效于 {0,}。
- 一次或多次匹配前面的字符或子表達式。例如,"zo+"與"zo"和"zoo"匹配,但與"z"不匹配。+ 等效于 {1,}。
? 零次或一次匹配前面的字符或子表達式。例如,"do(es)?“匹配"do"或"does"中的"do”。? 等效于 {0,1}。
{n} n 是非負整數(shù)。正好匹配 n 次。例如,"o{2}"與"Bob"中的"o"不匹配,但與"food"中的兩個"o"匹配。
{n,} n 是非負整數(shù)。至少匹配 n 次。例如,"o{2,}“不匹配"Bob"中的"o”,而匹配"foooood"中的所有 o。"o{1,}“等效于"o+”。"o{0,}“等效于"o*”。
{n,m} m 和 n 是非負整數(shù),其中 n <= m。匹配至少 n 次,至多 m 次。例如,"o{1,3}"匹配"fooooood"中的頭三個 o?!畂{0,1}’ 等效于 ‘o?’。注意:您不能將空格插入逗號和數(shù)字之間。
? 當(dāng)此字符緊隨任何其他限定符(、+、?、{n}、{n,}、{n,m})之后時,匹配模式是"非貪心的"。“非貪心的"模式匹配搜索到的、盡可能短的字符串,而默認的"貪心的"模式匹配搜索到的、盡可能長的字符串。例如,在字符串"oooo"中,“o+?“只匹配單個"o”,而"o+“匹配所有"o”。
. 匹配除”\r\n"之外的任何單個字符。若要匹配包括”\r\n"在內(nèi)的任意字符,請使用諸如"[\s\S]“之類的模式。
(pattern) 匹配 pattern 并捕獲該匹配的子表達式??梢允褂?9 屬性從結(jié)果"匹配"集合中檢索捕獲的匹配。若要匹配括號字符 ( ),請使用”(“或者”)“。
(?:pattern) 匹配 pattern 但不捕獲該匹配的子表達式,即它是一個非捕獲匹配,不存儲供以后使用的匹配。這對于用"or"字符 (|) 組合模式部件的情況很有用。例如,'industr(?:y|ies) 是比 ‘industry|industries’ 更經(jīng)濟的表達式。
(?=pattern) 執(zhí)行正向預(yù)測先行搜索的子表達式,該表達式匹配處于匹配 pattern 的字符串的起始點的字符串。它是一個非捕獲匹配,即不能捕獲供以后使用的匹配。例如,‘Windows (?=95|98|NT|2000)’ 匹配"Windows 2000"中的"Windows”,但不匹配"Windows 3.1"中的"Windows"。預(yù)測先行不占用字符,即發(fā)生匹配后,下一匹配的搜索緊隨上一匹配之后,而不是在組成預(yù)測先行的字符后。
(?!pattern) 執(zhí)行反向預(yù)測先行搜索的子表達式,該表達式匹配不處于匹配 pattern 的字符串的起始點的搜索字符串。它是一個非捕獲匹配,即不能捕獲供以后使用的匹配。例如,‘Windows (?!95|98|NT|2000)’ 匹配"Windows 3.1"中的 “Windows”,但不匹配"Windows 2000"中的"Windows"。預(yù)測先行不占用字符,即發(fā)生匹配后,下一匹配的搜索緊隨上一匹配之后,而不是在組成預(yù)測先行的字符后。
x|y 匹配 x 或 y。例如,‘z|food’ 匹配"z"或"food"。‘(z|f)ood’ 匹配"zood"或"food"。
[xyz] 字符集。匹配包含的任一字符。例如,“[abc]“匹配"plain"中的"a”。
[^xyz] 反向字符集。匹配未包含的任何字符。例如,”[^abc]“匹配"plain"中"p”,“l(fā)”,“i”,“n”。
[a-z] 字符范圍。匹配指定范圍內(nèi)的任何字符。例如,“[a-z]“匹配"a"到"z"范圍內(nèi)的任何小寫字母。
[^a-z] 反向范圍字符。匹配不在指定的范圍內(nèi)的任何字符。例如,”[^a-z]“匹配任何不在"a"到"z"范圍內(nèi)的任何字符。
\b 匹配一個字邊界,即字與空格間的位置。例如,“er\b"匹配"never"中的"er”,但不匹配"verb"中的"er”。
\B 非字邊界匹配。“er\B"匹配"verb"中的"er”,但不匹配"never"中的"er”。
\cx 匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回車符。x 的值必須在 A-Z 或 a-z 之間。如果不是這樣,則假定 c 就是"c"字符本身。
\d 數(shù)字字符匹配。等效于 [0-9]。
\D 非數(shù)字字符匹配。等效于 [^0-9]。
\f 換頁符匹配。等效于 \x0c 和 \cL。
\n 換行符匹配。等效于 \x0a 和 \cJ。
\r 匹配一個回車符。等效于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、換頁符等。與 [ \f\n\r\t\v] 等效。
\S 匹配任何非空白字符。與 [^ \f\n\r\t\v] 等效。
\t 制表符匹配。與 \x09 和 \cI 等效。
\v 垂直制表符匹配。與 \x0b 和 \cK 等效。
\w 匹配任何字類字符,包括下劃線。與"[A-Za-z0-9_]“等效。
\W 與任何非單詞字符匹配。與”[^A-Za-z0-9_]“等效。
\xn 匹配 n,此處的 n 是一個十六進制轉(zhuǎn)義碼。十六進制轉(zhuǎn)義碼必須正好是兩位數(shù)長。例如,”\x41"匹配"A"?!癨x041"與”\x04"&"1"等效。允許在正則表達式中使用 ASCII 代碼。
num 匹配 num,此處的 num 是一個正整數(shù)。到捕獲匹配的反向引用。例如,"(.)\1"匹配兩個連續(xù)的相同字符。
n 標識一個八進制轉(zhuǎn)義碼或反向引用。如果 n 前面至少有 n 個捕獲子表達式,那么 n 是反向引用。否則,如果 n 是八進制數(shù) (0-7),那么 n 是八進制轉(zhuǎn)義碼。
nm 標識一個八進制轉(zhuǎn)義碼或反向引用。如果 nm 前面至少有 nm 個捕獲子表達式,那么 nm 是反向引用。如果 nm 前面至少有 n 個捕獲,則 n 是反向引用,后面跟有字符 m。如果兩種前面的情況都不存在,則 nm 匹配八進制值 nm,其中 *n 和 m 是八進制數(shù)字 (0-7)。
\nml 當(dāng) n 是八進制數(shù) (0-3),m 和 l 是八進制數(shù) (0-7) 時,匹配八進制轉(zhuǎn)義碼 nml。
\un 匹配 n,其中 n 是以四位十六進制數(shù)表示的 Unicode 字符。例如,\u00A9 匹配版權(quán)符號 (?)。
15、
解析
HashMap可以插入null的key或value,插入的時候,檢查是否已經(jīng)存在相同的key,如果不存在,則直接插入,如果存在,則用新的value替換舊的value,在本題中,第一條put語句,會將key/value對插入HashMap,而第二條put,因為已經(jīng)存在一個key為name的項,所以會用新的value替換舊的value,因此,兩條put之后,HashMap中只有一個key/value鍵值對。那就是(name,jack)。所以,size為1.
16、
&運算符:兩個數(shù)都轉(zhuǎn)為二進制,然后從兩個數(shù)的最高位進行與運算,兩個都為真(1),結(jié)果才為真(1),否則為假(0)
13:01101
17:10001
結(jié)果:00001,既為1
17、
18、
解析
A錯誤,類的實例方法是與該類的實例對象相關(guān)聯(lián)的,不能直接調(diào)用,只能通過創(chuàng)建超類的一個實例對象,再進行調(diào)用
B錯誤,當(dāng)父類的類方法定義為private時,對子類是不可見的,所以子類無法調(diào)用
C錯誤,子類具體的實例方法對父類是不可見的,所以無法直接調(diào)用, 只能通過創(chuàng)建子類的一個實例對象,再進行調(diào)用
D正確,實例方法可以調(diào)用自己類中的實例方法
19、(歧義)
20、
中間件是一種獨立的系統(tǒng)軟件或服務(wù)程序,分布式應(yīng)用軟件借助這種軟件在不同的技術(shù)之間共享資源。中間件位于客戶機/ 服務(wù)器的操作系統(tǒng)之上,管理計算機資源和網(wǎng)絡(luò)通訊。是連接兩個獨立應(yīng)用程序或獨立系統(tǒng)的軟件。相連接的系統(tǒng),即使它們具有不同的接口,但通過中間件相互之間仍能交換信息。執(zhí)行中間件的一個關(guān)鍵途徑是信息傳遞。通過中間件,應(yīng)用程序可以工作于多平臺或OS環(huán)境。
(簡單來說,中間件并不能提高內(nèi)核的效率,一般只是負責(zé)網(wǎng)絡(luò)信息的分發(fā)處理)
a,中間件位于操作系統(tǒng)之上,應(yīng)用軟件之下,而不是操作系統(tǒng)內(nèi)核中
21、
靜態(tài)方法是依據(jù)類而直接使用
普通方法,運用的是動態(tài)單分配,是根據(jù)new的類型確定對象,從而確定調(diào)用的方法;
靜態(tài)方法,運用的是靜態(tài)多分派,即根據(jù)靜態(tài)類型確定對象,因此不是根據(jù)new的類型確定調(diào)用的方法
public class Father {
public void say(){
System.out.println(“father”);
}
public static void action(){
System.out.println(“爸爸打兒子!”);
}
}
public class Son extends Father{
public void say() {
System.out.println(“son”);
}
public static void action(){
System.out.println(“打打!”);
}
public static void main(String[] args) {
Father f=new Son();
f.say();
f.action();
}
}
輸出:son
爸爸打兒子!
當(dāng)調(diào)用say方法執(zhí)行的是Son的方法,也就是重寫的say方法
而當(dāng)調(diào)用action方法時,執(zhí)行的是father的方法。
普通方法,運用的是動態(tài)單分配,是根據(jù)new的類型確定對象,從而確定調(diào)用的方法;
靜態(tài)方法,運用的是靜態(tài)多分派,即根據(jù)靜態(tài)類型確定對象,因此不是根據(jù)new的類型確定調(diào)用的方法
22、
1、必須實現(xiàn)接口中所有的方法。
在實現(xiàn)類中實現(xiàn)接口時,方法的名字、返回值類型、參數(shù)的個數(shù)及類型必須與接口中的完全一致,并且必須實現(xiàn)接口中的所有方法。
2、接口實現(xiàn)類相當(dāng)于子類,子類的訪問權(quán)限是不能比父類小的。
接口中所有方法默認都是public,至于為什么要是public,原因在于如果不是public,那么只能在同個包下被實現(xiàn),可訪問權(quán)限就降低很多了,那么在實現(xiàn)類中,實現(xiàn)的類相當(dāng)于子類,子類的訪問權(quán)限是不能比父類小的,而在java中一個類如果沒有權(quán)限的修飾符,默認是friendly(同一個包內(nèi)的其它類才可訪問),所以在實現(xiàn)類中一定要寫public
3、實現(xiàn)類可以獲取接口中的屬性。
B 方法在類不寫訪問權(quán)限修飾,默認則是為default,與接口中public 不一致
C 方法的返回類型與接口不一致
D 方法必須被實現(xiàn)
23、
CountDownLatch : 一個線程(或者多個), 等待另外N個線程完成某個事情之后才能執(zhí)行。
CyclicBarrier: N個線程相互等待,任何一個線程完成之前,所有的線程都必須等待。
這樣應(yīng)該就清楚一點了,對于CountDownLatch來說,重點是那個“一個線程”, 是它在等待, 而另外那N的線程在把“某個事情”做完之后可以繼續(xù)等待,可以終止。
而對于CyclicBarrier來說,重點是那N個線程,他們之間任何一個沒有完成,所有的線程都必須等待。
CountDownLatch 是計數(shù)器, 線程完成一個就記一個, 就像 報數(shù)一樣, 只不過是遞減的。
而CyclicBarrier更像一個水閘, 線程執(zhí)行就想水流, 在水閘處都會堵住, 等到水滿(線程到齊)了, 才開始泄流。
24、
Math.floor() 表示向下取整,返回double類型 (floor—地板)
Math.ceil() 表示向上取整,返回double類型 (ceil—天花板)
Math.round() 四舍五入,返回int類型(如果傳入的是double類型,則返回long; 如果是float 類型,則返回int)
25、
對于線程而言,start是讓線程從new變成runnable。run方法才是執(zhí)行體的入口。
但是在Thread中,run方法是個空方法,沒有具體實現(xiàn)。
Bground繼承了Thread,但是沒有重寫run方法,那么調(diào)用run方法肯定是無輸出。
26、
存根類是一個類,它實現(xiàn)了一個接口,它的作用是:如果一個接口有很多方法,如果要實現(xiàn)這個接口,就要實現(xiàn)所有的方法。但是一個類從業(yè)務(wù)來說,可能只需要其中一兩個方法。如果直接去實現(xiàn)這個接口,除了實現(xiàn)所需的方法,還要實現(xiàn)其他所有的無關(guān)方法。而如果通過繼承存根類就實現(xiàn)接口,就免去了這種麻煩。
RMI 采用stubs 和 skeletons 來進行遠程對象(remote object)的通訊。stub 充當(dāng)遠程對象的客戶端代理,有著和遠程對象相同的遠程接口,遠程對象的調(diào)用實際是通過調(diào)用該對象的客戶端代理對象stub來完成的。
每個遠程對象都包含一個代理對象stub,當(dāng)運行在本地Java虛擬機上的程序調(diào)用運行在遠程Java虛擬機上的對象方法時,它首先在本地創(chuàng)建該對象的代理對象stub, 然后調(diào)用代理對象上匹配的方法。每一個遠程對象同時也包含一個skeleton對象,skeleton運行在遠程對象所在的虛擬機上,接受來自stub對象的調(diào)用。這種方式符合等到程序要運行時將目標文件動態(tài)鏈接的思想。
27、
28、
簡單記憶線程安全的集合類: 喂! SHE ! 喂是指 vector , S 是指 stack , H 是指 hashtable , E 是指: Eenumeration
線程安全概念:
如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結(jié)果和單線程運行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線程安全的。
線程安全問題都是由全局變量及靜態(tài)變量引起的。
若每個線程中對全局變量、靜態(tài)變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執(zhí)行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。
LinkedList 和 ArrayList 都是不同步的,線程不安全;
Vector 和 Stack 都是同步的,線程安全;
Set是線程不安全的;
Hashtable的方法是同步的,線程安全;
HashMap的方法不是同步的,線程不安全;
29、
30、
A.StringBuilder線程不安全,StringBuffer線程安全。
B.同時用 abstract和final就會自相矛盾。
C.Hashmap中的value可以之null,get(key)==null有兩種情況,一是key不存在,二是該key中存的是null,所以應(yīng)該使用map.containskey(key)返回的true/false來判斷是否存在這個key。
D.volatile關(guān)鍵字有兩個作用:
1.并發(fā)環(huán)境可見性:volatile修飾后的變量能夠保證該變量在線程間的可見性,線程進行數(shù)據(jù)的讀寫操作時將繞開工作內(nèi)存(CPU緩存)而直接跟主內(nèi)存進行數(shù)據(jù)交互,即線程進行讀操作時直接從主內(nèi)存中讀取,寫操作時直接將修改后端變量刷新到主內(nèi)存中,這樣就能保證其他線程訪問到的數(shù)據(jù)是最新數(shù)據(jù)
2.并發(fā)環(huán)境有序性:通過對volatile變量采取內(nèi)存屏障(Memory barrier)的方式來防止編譯重排序和CPU指令重排序,具體方式是通過在操作volatile變量的指令前后加入內(nèi)存屏障,來實現(xiàn)happens-before關(guān)系,保證在多線程環(huán)境下的數(shù)據(jù)交互不會出現(xiàn)紊亂。
31、
按照流是否直接與特定的地方(如磁盤、內(nèi)存、設(shè)備等)相連,分為節(jié)點流和處理流兩類。
節(jié)點流:可以從或向一個特定的地方(節(jié)點)讀寫數(shù)據(jù)。如FileReader.
**處理流:是對一個已存在的流的連接和封裝,通過所封裝的流的功能調(diào)用實現(xiàn)數(shù)據(jù)讀寫。**如BufferedReader.處理流的構(gòu)造方法總是要帶一個其他的流對象做參數(shù)。一個流對象經(jīng)過其他流的多次包裝,稱為流的鏈接。
JAVA常用的節(jié)點流:
文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件進行處理的節(jié)點流。
字符串 StringReader StringWriter 對字符串進行處理的節(jié)點流。
數(shù) 組 ByteArrayInputStream ByteArrayOutputStreamCharArrayReader CharArrayWriter 對數(shù)組進行處理的節(jié)點流(對應(yīng)的不再是文件,而是內(nèi)存中的一個數(shù)組)。
管 道 PipedInputStream PipedOutputStream PipedReaderPipedWriter對管道進行處理的節(jié)點流。
常用處理流(關(guān)閉處理流使用關(guān)閉里面的節(jié)點流)
緩沖流:BufferedInputStrean BufferedOutputStream BufferedReader BufferedWriter 增加緩沖功能,避免頻繁讀寫硬盤。
轉(zhuǎn)換流:InputStreamReader OutputStreamReader 實現(xiàn)字節(jié)流和字符流之間的轉(zhuǎn)換。
數(shù)據(jù)流 DataInputStream DataOutputStream 等-提供將基礎(chǔ)數(shù)據(jù)類型寫入到文件中,或者讀取出來.
流的關(guān)閉順序
一般情況下是:先打開的后關(guān)閉,后打開的先關(guān)閉
另一種情況:看依賴關(guān)系,如果流a依賴流b,應(yīng)該先關(guān)閉流a,再關(guān)閉流b。例如,處理流a依賴節(jié)點流b,應(yīng)該先關(guān)閉處理流a,再關(guān)閉節(jié)點流b
可以只關(guān)閉處理流,不用關(guān)閉節(jié)點流。處理流關(guān)閉的時候,會調(diào)用其處理的節(jié)點流的關(guān)閉方法。
32、(?)
get方法是獲得user對象下前面指定好的屬性的值,而獲取static屬性時get()括號里的對象可以寫成null
33、
以java8為準,switch支持10種類型 基本類型:byte char short int 對于包裝類 :Byte,Short,Character,Integer String enum
在Java7之前,switch只能支持 byte、short、char、int或者其對應(yīng)的封裝類以及Enum類型。在Java7中,也支持了String類型
String byte short int char Enum 類型
34、
A,“任何對象”鎖定,太絕對了,你能鎖住你沒有權(quán)限訪問的對象嗎?
B,前半句話講的是創(chuàng)建線程的方式,后半句講的是鎖定,驢頭不對馬嘴。
C,正確。
D,線程調(diào)度分為協(xié)同式調(diào)度和搶占式調(diào)度,Java使用的是搶占式調(diào)度,也就是每個線程將由操作系統(tǒng)來分配執(zhí)行時間,線程的切換不由線程本身來決定(協(xié)同式調(diào)度)。這就是平***立的原因。
以上,選CD
線程的互斥鎖機制:synchronized,lock,condition
35、
主要考核了這幾個知識點:
1.靜態(tài)內(nèi)部類才可以聲明靜態(tài)方法
2.靜態(tài)方法不可以使用非靜態(tài)變量
3.抽象方法不可以有函數(shù)體
這是我學(xué)習(xí)Java內(nèi)部類的筆記
1.為什么使用內(nèi)部類?
使用內(nèi)部類最吸引人的原因是:每個內(nèi)部類都能獨立地繼承一個(接口的)實現(xiàn),所以無論外圍類是否已經(jīng)繼承了某個(接口的)實現(xiàn),
對于內(nèi)部類都沒有影響
1.1.使用內(nèi)部類最大的優(yōu)點就在于它能夠非常好的解決多重繼承的問題,使用內(nèi)部類還能夠為我們帶來如下特性:
(1)、內(nèi)部類可以用多個實例,每個實例都有自己的狀態(tài)信息,并且與其他外圍對象的信息相互獨。
(2)、在單個外圍類中,可以讓多個內(nèi)部類以不同的方式實現(xiàn)同一個接口,或者繼承同一個類。
(3)、創(chuàng)建內(nèi)部類對象的時刻并不依賴于外圍類對象的創(chuàng)建。
(4)、內(nèi)部類并沒有令人迷惑的“is-a”關(guān)系,他就是一個獨立的實體。
(5)、內(nèi)部類提供了更好的封裝,除了該外圍類,其他類都不能訪問。
2.內(nèi)部類分類:
(一).成員內(nèi)部類:
public class Outer{
private int age = 99;
String name = “Coco”;
public class Inner{
String name = “Jayden”;
public void show(){
System.out.println(Outer.this.name);
System.out.println(name);
System.out.println(age);
}
}
public Inner getInnerClass(){
return new Inner();
}
public static void main(String[] args){
Outer o = new Outer();
Inner in = o.new Inner();
in.show();
}
}
1.Inner 類定義在 Outer 類的內(nèi)部,相當(dāng)于 Outer 類的一個成員變量的位置,Inner 類可以使用任意訪問控制符,
如 public 、 protected 、 private 等
2.Inner 類中定義的 show() 方法可以直接訪問 Outer 類中的數(shù)據(jù),而不受訪問控制符的影響,
如直接訪問 Outer 類中的私有屬性age
3.定義了成員內(nèi)部類后,必須使用外部類對象來創(chuàng)建內(nèi)部類對象,而不能直接去 new 一個內(nèi)部類對象,
即:內(nèi)部類 對象名 = 外部類對象.new 內(nèi)部類( );
4.編譯上面的程序后,會發(fā)現(xiàn)產(chǎn)生了兩個 .class 文件: Outer.class,Outer$Inner.class{}
5.成員內(nèi)部類中不能存在任何 static 的變量和方法,可以定義常量:
(1).因為非靜態(tài)內(nèi)部類是要依賴于外部類的實例,而靜態(tài)變量和方法是不依賴于對象的,僅與類相關(guān),
簡而言之:在加載靜態(tài)域時,根本沒有外部類,所在在非靜態(tài)內(nèi)部類中不能定義靜態(tài)域或方法,編譯不通過;
非靜態(tài)內(nèi)部類的作用域是實例級別
(2).常量是在編譯器就確定的,放到所謂的常量池了
★★友情提示:
1.外部類是不能直接使用內(nèi)部類的成員和方法的,可先創(chuàng)建內(nèi)部類的對象,然后通過內(nèi)部類的對象來訪問其成員變量和方法;
2.如果外部類和內(nèi)部類具有相同的成員變量或方法,內(nèi)部類默認訪問自己的成員變量或方法,如果要訪問外部類的成員變量,
可以使用 this 關(guān)鍵字,如:Outer.this.name
(二).靜態(tài)內(nèi)部類: 是 static 修飾的內(nèi)部類,
1.靜態(tài)內(nèi)部類不能直接訪問外部類的非靜態(tài)成員,但可以通過 new 外部類().成員 的方式訪問
2.如果外部類的靜態(tài)成員與內(nèi)部類的成員名稱相同,可通過“類名.靜態(tài)成員”訪問外部類的靜態(tài)成員;
如果外部類的靜態(tài)成員與內(nèi)部類的成員名稱不相同,則可通過“成員名”直接調(diào)用外部類的靜態(tài)成員
3.創(chuàng)建靜態(tài)內(nèi)部類的對象時,不需要外部類的對象,可以直接創(chuàng)建 內(nèi)部類 對象名 = new 內(nèi)部類();
public class Outer{
private int age = 99;
static String name = “Coco”;
public static class Inner{
String name = “Jayden”;
public void show(){
System.out.println(Outer.name);
System.out.println(name);
}
}
public static void main(String[] args){
Inner i = new Inner();
i.show();
}
}
(三).方法內(nèi)部類:其作用域僅限于方法內(nèi),方法外部無法訪問該內(nèi)部類
(1).局部內(nèi)部類就像是方法里面的一個局部變量一樣,是不能有 public、protected、private 以及 static 修飾符的
(2).只能訪問方法中定義的 final 類型的局部變量,因為:
當(dāng)方法被調(diào)用運行完畢之后,局部變量就已消亡了。但內(nèi)部類對象可能還存在,
直到?jīng)]有被引用時才會消亡。此時就會出現(xiàn)一種情況,就是內(nèi)部類要訪問一個不存在的局部變量;
==>使用final修飾符不僅會保持對象的引用不會改變,而且編譯器還會持續(xù)維護這個對象在回調(diào)方法中的生命周期.
局部內(nèi)部類并不是直接調(diào)用方法傳進來的參數(shù),而是內(nèi)部類將傳進來的參數(shù)通過自己的構(gòu)造器備份到了自己的內(nèi)部,
自己內(nèi)部的方法調(diào)用的實際是自己的屬性而不是外部類方法的參數(shù);
防止被篡改數(shù)據(jù),而導(dǎo)致內(nèi)部類得到的值不一致
/*
使用的形參為何要為 final???
在內(nèi)部類中的屬性和外部方法的參數(shù)兩者從外表上看是同一個東西,但實際上卻不是,所以他們兩者是可以任意變化的,
也就是說在內(nèi)部類中我對屬性的改變并不會影響到外部的形參,而然這從程序員的角度來看這是不可行的,
畢竟站在程序的角度來看這兩個根本就是同一個,如果內(nèi)部類該變了,而外部方法的形參卻沒有改變這是難以理解
和不可接受的,所以為了保持參數(shù)的一致性,就規(guī)定使用 final 來避免形參的不改變
*/
public class Outer{
public void Show(){
final int a = 25;
int b = 13;
class Inner{
int c = 2;
public void print(){
System.out.println(“訪問外部類:” + a);
System.out.println(“訪問內(nèi)部類:” + c);
}
}
Inner i = new Inner();
i.print();
}
public static void main(String[] args){
Outer o = new Outer();
o.show();
}
}
(3).注意:在JDK8版本之中,方法內(nèi)部類中調(diào)用方法中的局部變量,可以不需要修飾為 final,匿名內(nèi)部類也是一樣的,主要是JDK8之后增加了 Effectively final 功能
http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html
反編譯jdk8編譯之后的class文件,發(fā)現(xiàn)內(nèi)部類引用外部的局部變量都是 final 修飾的
(四).匿名內(nèi)部類:
(1).匿名內(nèi)部類是直接使用 new 來生成一個對象的引用;
(2).對于匿名內(nèi)部類的使用它是存在一個缺陷的,就是它僅能被使用一次,創(chuàng)建匿名內(nèi)部類時它會立即創(chuàng)建一個該類的實例,
該類的定義會立即消失,所以匿名內(nèi)部類是不能夠被重復(fù)使用;
(3).使用匿名內(nèi)部類時,我們必須是繼承一個類或者實現(xiàn)一個接口,但是兩者不可兼得,同時也只能繼承一個類或者實現(xiàn)一個接口;
(4).匿名內(nèi)部類中是不能定義構(gòu)造函數(shù)的,匿名內(nèi)部類中不能存在任何的靜態(tài)成員變量和靜態(tài)方法;
(5).匿名內(nèi)部類中不能存在任何的靜態(tài)成員變量和靜態(tài)方法,匿名內(nèi)部類不能是抽象的,它必須要實現(xiàn)繼承的類或者實現(xiàn)的接口的所有抽象方法
(6).匿名內(nèi)部類初始化:使用構(gòu)造代碼塊!利用構(gòu)造代碼塊能夠達到為匿名內(nèi)部類創(chuàng)建一個構(gòu)造器的效果
public class OuterClass {
public InnerClass getInnerClass(final int num,String str2){
return new InnerClass(){
int number = num + 3;
public int getNumber(){
return number;
}
}; /* 注意:分號不能省 */
}
public static void main(String[] args) {
OuterClass out = new OuterClass();
InnerClass inner = out.getInnerClass(2, “chenssy”);
System.out.println(inner.getNumber());
}
}
interface InnerClass {
int getNumber();
}
總結(jié)
以上是生活随笔為你收集整理的【刷题2022/5/3 用时160min】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 滤波电路(上),无源滤波器
- 下一篇: 高级项目进度表