国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
1、==
2、equals()方法詳解
3、hashcode()淺談
2. int、char、long 各占多少字節(jié)數(shù)
3. int和Integer的區(qū)別
2.多態(tài)中成員的特點(diǎn)
3.instanceof關(guān)鍵字
4.多態(tài)的轉(zhuǎn)型
5.多態(tài)案例:
5. String、StringBuffer和StringBuilder區(qū)別
1、長度是否可變
2、執(zhí)行效率
2、應(yīng)用場景
1、是否線程安全
6. 什么是內(nèi)部類?內(nèi)部類的作用
內(nèi)部類的定義
內(nèi)部類的作用:
7. 抽象類別和介面的差異
8. 抽象類別的意義
9. 抽象類別與介面的應(yīng)用場景
1.介面(interface)的應(yīng)用場合:
2.抽象類別(abstract.class)的應(yīng)用場合:
10. ?抽象類別是否可以沒有方法和屬性?
11. 接口的意義
12. Java泛型中的extends和super理解
13. 父類的靜態(tài)方法能否被子類重寫
14. 執(zhí)行緒與行程的差異
15. final,finally,finalize的區(qū)別
16. 序列化Serializable和Parcelable的區(qū)別
17. 靜態(tài)屬性和靜態(tài)方法是否可以被繼承?是否可以被重寫?以及原因?
18 .java中靜態(tài)內(nèi)部類的設(shè)計(jì)意圖
內(nèi)部類別
靜態(tài)內(nèi)部類別
首頁 Java Java面試題 2020全新java基礎(chǔ)面試題彙總

2020全新java基礎(chǔ)面試題彙總

Oct 21, 2020 pm 04:51 PM
java 面試題

2020全新java基礎(chǔ)面試題彙總

java==和equals和hashCode的區(qū)別

(更多面試題推薦:java面試題及答案

1、==

java中的資料類型,可分為兩類:

  1. #基本資料類型,也稱為原始資料類型 byte,short,char,int,long,float,double,boolean ?他們之間的比較,應(yīng)用雙等號(==),比較的是他們的值。

  2. 引用型別(類別、介面、陣列) 當(dāng)他們用(==)進(jìn)行比較的時(shí)候,比較的是他們在記憶體中的存放位址,所以,除非是同一個(gè)new出來的對象,他們的比較後的結(jié)果為true,否則比較後結(jié)果為false。物件是放在堆中的,堆疊中存放的是物件的參考(位址)。先看下虛擬機(jī)器記憶體圖和程式碼:

public?class?testDay?{
????public?static?void?main(String[]?args)?{
????????String?s1?=?new?String("11");
????????String?s2?=?new?String("11");
????????System.out.println(s1?==?s2);
????????System.out.println(s1.equals(s2));
????}
}

結(jié)果是:

false
true

2020全新java基礎(chǔ)面試題彙總

s1和s2都分別儲存的是對應(yīng)物件的位址。所以如果用 s1== s2時(shí),比較的是兩個(gè)物件的位址值(即比較引用是否相同),為false。而呼叫equals方向的時(shí)候比較的是對應(yīng)位址裡面的值,所以值為true。這裡就需要詳細(xì)描述下equals()了。

2、equals()方法詳解

equals()方法是用來判斷其他的物件是否和該物件相等。其再Object裡面就有定義,所以任何一個(gè)物件都有equals()方法。差別在於是否重寫了該方法。

先看下原始碼:

public?boolean?equals(Object?obj)?{????return?(this?==?obj);
}

很明顯Object定義的是兩個(gè)物件的位址值的比較(即比較引用是否相同)。但為什麼String裡面呼叫equals()卻是比較的不是位址而是堆記憶體位址裡面的值。這裡就是個(gè)重點(diǎn)了,像String 、Math、Integer、Double等這些封裝類別在使用equals()方法時(shí),已經(jīng)覆寫了object類別的equals()方法??聪耂tring裡面重寫的equals():

public?boolean?equals(Object?anObject)?{????if?(this?==?anObject)?{????????return?true;
????}????if?(anObject?instanceof?String)?{
????????String?anotherString?=?(String)anObject;
????????int?n?=?value.length;????????if?(n?==?anotherString.value.length)?{
????????????char?v1[]?=?value;
????????????char?v2[]?=?anotherString.value;
????????????int?i?=?0;????????????while?(n--?!=?0)?{????????????????if?(v1[i]?!=?v2[i])????????????????????return?false;
????????????????i++;
????????????}????????????return?true;
????????}
????}????return?false;
}

重寫了之後就是這是進(jìn)行的內(nèi)容比較,而已經(jīng)不再是先前位址的比較。依序類別推Math、Integer、Double等這些類別都是重寫了equals()方法的,從而進(jìn)行的是內(nèi)容的比較。當(dāng)然,基本型別是進(jìn)行值的比較。

要注意的是當(dāng)equals()方法被override時(shí),hashCode()也要被override。依照一般hashCode()方法的實(shí)作來說,相等的對象,它們的hashcode一定相等。為什麼會這樣,這裡又要簡單提hashcode了。

3、hashcode()淺談

明明是java中==和equals和hashCode的區(qū)別問題,怎麼一下子又扯到hashcode()上面去了。你一定很鬱悶,好了,我打個(gè)簡單的例子你就知道為什麼==或equals的時(shí)候會牽扯到hashCode。

舉例說明下:如果你想找出一個(gè)集合中是否包含某個(gè)對象,那麼程式該怎麼寫呢?不要用indexOf方法的話,就是從集合去遍歷然後比較是否想到。萬一集合中有10000個(gè)元素呢,累屎了吧。所以為了提高效率,哈希演算法也就產(chǎn)生了。核心思想就是將集合分成若干個(gè)儲存區(qū)域(可以看成一個(gè)個(gè)桶),每個(gè)物件可以計(jì)算出一個(gè)雜湊碼,可以根據(jù)雜湊碼分組,每組分別對應(yīng)某個(gè)儲存區(qū)域,這樣一個(gè)物件根據(jù)它的哈希碼就可以分到不同的儲存區(qū)域(不同的區(qū)域)。

所以再比較元素的時(shí)候,其實(shí)是先比較hashcode,如果相等了之後才去比較equal方法。

看下hashcode圖解:

2020全新java基礎(chǔ)面試題彙總

#一個(gè)物件一般有key和value,可以根據(jù)key來計(jì)算它的hashCode值,再根據(jù)其hashCode值儲存在不同的儲存區(qū)域中,如上圖。不同區(qū)域能儲存多個(gè)值是因?yàn)闀可娴絟ash衝突的問題。簡單如果兩個(gè)不同物件的hashCode相同,這種現(xiàn)象稱為hash衝突。簡單來說就是hashCode相同但是equals不同的值。對於比較10000個(gè)元素就不需要遍歷整個(gè)集合了,只需要計(jì)算要查找對象的key的hashCode,然後找到該hashCode對應(yīng)的存儲區(qū)域查找就over了。

2020全新java基礎(chǔ)面試題彙總

大概可以知道,先通過hashcode來比較,如果hashcode相等,那么就用equals方法來比較兩個(gè)對象是否相等。再重寫了equals最好把hashCode也重寫。其實(shí)這是一條規(guī)范,如果不這樣做程序也可以執(zhí)行,只不過會隱藏bug。一般一個(gè)類的對象如果會存儲在HashTable,HashSet,HashMap等散列存儲結(jié)構(gòu)中,那么重寫equals后最好也重寫hashCode。

總結(jié):

  1. hashCode是為了提高在散列結(jié)構(gòu)存儲中查找的效率,在線性表中沒有作用。
  2. equals重寫的時(shí)候hashCode也跟著重寫
  3. 兩對象equals如果相等那么hashCode也一定相等,反之不一定。

2. int、char、long 各占多少字節(jié)數(shù)

byte 是 字節(jié)

bit 是 位

1 byte = 8 bit

char在java中是2個(gè)字節(jié),java采用unicode,2個(gè)字節(jié)來表示一個(gè)字符

short 2個(gè)字節(jié)

int 4個(gè)字節(jié)

long 8個(gè)字節(jié)

float 4個(gè)字節(jié)

double 8個(gè)字節(jié)

3. int和Integer的區(qū)別

  1. Integer是int的包裝類,int則是java的一種基本數(shù)據(jù)類型
  2. Integer變量必須實(shí)例化后才能使用,而int變量不需要
  3. Integer實(shí)際是對象的引用,當(dāng)new一個(gè)Integer時(shí),實(shí)際上是生成一個(gè)指針指向此對象;而int則是直接存儲數(shù)據(jù)值
  4. Integer的默認(rèn)值是null,int的默認(rèn)值是0

延伸: 關(guān)于Integer和int的比較

  1. 由于Integer變量實(shí)際上是對一個(gè)Integer對象的引用,所以兩個(gè)通過new生成的Integer變量永遠(yuǎn)是不相等的(因?yàn)閚ew生成的是兩個(gè)對象,其內(nèi)存地址不同)。
Integer?i?=?new?Integer(100);
Integer?j?=?new?Integer(100);
System.out.print(i?==?j);?//false
  1. Integer變量和int變量比較時(shí),只要兩個(gè)變量的值是向等的,則結(jié)果為true(因?yàn)榘b類Integer和基本數(shù)據(jù)類型int比較時(shí),java會自動拆包裝為int,然后進(jìn)行比較,實(shí)際上就變?yōu)閮蓚€(gè)int變量的比較)
Integer?i?=?new?Integer(100);
int?j?=?100;
System.out.print(i?==?j);?//true
  1. 非new生成的Integer變量和new Integer()生成的變量比較時(shí),結(jié)果為false。(因?yàn)榉莕ew生成的Integer變量指向的是java常量池中的對象,而new Integer()生成的變量指向堆中新建的對象,兩者在內(nèi)存中的地址不同)
Integer?i?=?new?Integer(100);
Integer?j?=?100;
System.out.print(i?==?j);?//false
  1. 對于兩個(gè)非new生成的Integer對象,進(jìn)行比較時(shí),如果兩個(gè)變量的值在區(qū)間-128到127之間,則比較結(jié)果為true,如果兩個(gè)變量的值不在此區(qū)間,則比較結(jié)果為false
Integer?i?=?100;
Integer?j?=?100;
System.out.print(i?==?j);?//true
Integer?i?=?128;
Integer?j?=?128;
System.out.print(i?==?j);?//false

對于第4條的原因: java在編譯Integer i = 100 ;時(shí),會翻譯成為Integer i = Integer.valueOf(100);,而java API中對Integer類型的valueOf的定義如下:

public?static?Integer?valueOf(int?i){
????assert?IntegerCache.high?>=?127;????if?(i?>=?IntegerCache.low?&&?i?<p>java對于-128到127之間的數(shù),會進(jìn)行緩存,Integer i = 127時(shí),會將127進(jìn)行緩存,下次再寫Integer j = 127時(shí),就會直接從緩存中取,就不會new了</p><h2 class="heading" data-id="heading-6">4. java多態(tài)的理解</h2><h3 class="heading" data-id="heading-7">1.多態(tài)概述</h3><ol>
<li><p>多態(tài)是繼封裝、繼承之后,面向?qū)ο蟮牡谌筇匦浴?lt;/p></li>
<li><p>多態(tài)現(xiàn)實(shí)意義理解:</p></li>
</ol>
  • 現(xiàn)實(shí)事物經(jīng)常會體現(xiàn)出多種形態(tài),如學(xué)生,學(xué)生是人的一種,則一個(gè)具體的同學(xué)張三既是學(xué)生也是人,即出現(xiàn)兩種形態(tài)。

  • Java作為面向?qū)ο蟮恼Z言,同樣可以描述一個(gè)事物的多種形態(tài)。如Student類繼承了Person類,一個(gè)Student的對象便既是Student,又是Person。

  1. 多態(tài)體現(xiàn)為父類引用變量可以指向子類對象。

  2. 前提條件:必須有子父類關(guān)系。

注意:在使用多態(tài)后的父類引用變量調(diào)用方法時(shí),會調(diào)用子類重寫后的方法。

  1. 多態(tài)的定義與使用格式

定義格式:父類類型 變量名=new 子類類型();

2.多態(tài)中成員的特點(diǎn)

  1. 多態(tài)成員變量:編譯運(yùn)行看左邊

Fu f=new Zi();

System.out.println(f.num);//f是Fu中的值,只能取到父中的值

  1. 多態(tài)成員方法:編譯看左邊,運(yùn)行看右邊

Fu f1=new Zi();

System.out.println(f1.show());//f1的門面類型是Fu,但實(shí)際類型是Zi,所以調(diào)用的是重寫后的方法。

3.instanceof關(guān)鍵字

作用:用來判斷某個(gè)對象是否屬于某種數(shù)據(jù)類型。

*?注意:?返回類型為布爾類型

使用案例:

Fu?f1=new?Zi();
Fu?f2=new?Son();if(f1?instanceof?Zi){
????System.out.println("f1是Zi的類型");
}else{
????System.out.println("f1是Son的類型");
}

4.多態(tài)的轉(zhuǎn)型

多態(tài)的轉(zhuǎn)型分為向上轉(zhuǎn)型和向下轉(zhuǎn)型兩種

  • 向上轉(zhuǎn)型:多態(tài)本身就是向上轉(zhuǎn)型過的過程

    • 使用格式:父類類型 變量名=new 子類類型();

    • 適用場景:當(dāng)不需要面對子類類型時(shí),通過提高擴(kuò)展性,或者使用父類的功能就能完成相應(yīng)的操作。

  • 向下轉(zhuǎn)型:一個(gè)已經(jīng)向上轉(zhuǎn)型的子類對象可以使用強(qiáng)制類型轉(zhuǎn)換的格式,將父類引用類型轉(zhuǎn)為子類引用各類型

    • 使用格式:子類類型 變量名=(子類類型)父類類型的變量;

    • 適用場景:當(dāng)要使用子類特有功能時(shí)。

5.多態(tài)案例:

例1:

package?day0524;
?
public?class?demo04?{
????public?static?void?main(String[]?args)?{
????????People?p=new?Stu();
????????p.eat();
????????//調(diào)用特有的方法
????????Stu?s=(Stu)p;
????????s.study();
????????//((Stu)?p).study();
????}
}
class?People{
????public?void?eat(){
????????System.out.println("吃飯");
????}
}
class?Stu?extends?People{
????@Override
????public?void?eat(){
????????System.out.println("吃水煮肉片");
????}
????public?void?study(){
????????System.out.println("好好學(xué)習(xí)");
????}
}
class?Teachers?extends?People{
????@Override
????public?void?eat(){
????????System.out.println("吃櫻桃");
????}
????public?void?teach(){
????????System.out.println("認(rèn)真授課");
????}
}

答案:吃水煮肉片 好好學(xué)習(xí)

例2:

請問題目運(yùn)行結(jié)果是什么?

package?day0524;
public?class?demo1?{
????public?static?void?main(String[]?args)?{
????????A?a=new?A();
????????a.show();
????????B?b=new?B();
????????b.show();
????}
}
class?A{
????public?void?show(){
????????show2();
????}
????public?void?show2(){
????????System.out.println("A");
????}
}
class?B?extends?A{
????public?void?show2(){
????????System.out.println("B");
????}
}
class?C?extends?B{
????public?void?show(){
????????super.show();
????}
????public?void?show2(){
????????System.out.println("C");
????}
}

答案:A B

5. String、StringBuffer和StringBuilder區(qū)別

1、長度是否可變

  • String 是被 final 修飾的,他的長度是不可變的,就算調(diào)用 String 的concat 方法,那也是把字符串拼接起來并重新創(chuàng)建一個(gè)對象,把拼接后的 String 的值賦給新創(chuàng)建的對象
  • StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,并且不產(chǎn)生新的未使用對象,StringBuffer 與 StringBuilder 中的方法和功能完全是等價(jià)的。調(diào)用StringBuffer 的 append 方法,來改變 StringBuffer 的長度,并且,相比較于 StringBuffer,String 一旦發(fā)生長度變化,是非常耗費(fèi)內(nèi)存的!

2、執(zhí)行效率

  • 三者在執(zhí)行速度方面的比較:StringBuilder > StringBuffer > String

3、應(yīng)用場景

  • 如果要操作少量的數(shù)據(jù)用 = String
  • 單線程操作字符串緩沖區(qū) 下操作大量數(shù)據(jù) = StringBuilder
  • 多線程操作字符串緩沖區(qū) 下操作大量數(shù)據(jù) = StringBuffer

StringBuffer和StringBuilder區(qū)別

1、是否線程安全

  • StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在于 StringBuilder 的方法不是線程安全的(不能同步訪問),StringBuffer是線程安全的。只是StringBuffer 中的方法大都采用了 synchronized 關(guān)鍵字進(jìn)行修飾,因此是線程安全的,而 StringBuilder 沒有這個(gè)修飾,可以被認(rèn)為是線程不安全的。

2、應(yīng)用場景

  • 由于 StringBuilder 相較于 StringBuffer 有速度優(yōu)勢,所以多數(shù)情況下建議使用 StringBuilder 類。
  • 然而在應(yīng)用程序要求線程安全的情況下,則必須使用 StringBuffer 類。 append方法與直接使用+串聯(lián)相比,減少常量池的浪費(fèi)。

6. 什么是內(nèi)部類?內(nèi)部類的作用

內(nèi)部類的定義

將一個(gè)類定義在另一個(gè)類里面或者一個(gè)方法里面,這樣的類稱為內(nèi)部類。

內(nèi)部類的作用:

  1. 成員內(nèi)部類 成員內(nèi)部類可以無條件訪問外部類的所有成員屬性和成員方法(包括private成員和靜態(tài)成員)。 當(dāng)成員內(nèi)部類擁有和外部類同名的成員變量或者方法時(shí),會發(fā)生隱藏現(xiàn)象,即默認(rèn)情況下訪問的是成員內(nèi)部類的成員。

  2. 局部內(nèi)部類 局部內(nèi)部類是定義在一個(gè)方法或者一個(gè)作用域里面的類,它和成員內(nèi)部類的區(qū)別在于局部內(nèi)部類的訪問僅限于方法內(nèi)或者該作用域內(nèi)。

  3. 匿名內(nèi)部類 匿名內(nèi)部類就是沒有名字的內(nèi)部類

  4. 靜態(tài)內(nèi)部類 指被聲明為static的內(nèi)部類,他可以不依賴內(nèi)部類而實(shí)例,而通常的內(nèi)部類需要實(shí)例化外部類,從而實(shí)例化。靜態(tài)內(nèi)部類不可以有與外部類有相同的類名。不能訪問外部類的普通成員變量,但是可以訪問靜態(tài)成員變量和靜態(tài)方法(包括私有類型) 一個(gè) 靜態(tài)內(nèi)部類去掉static 就是成員內(nèi)部類,他可以自由的引用外部類的屬性和方法,無論是靜態(tài)還是非靜態(tài)。但是不可以有靜態(tài)屬性和方法

(學(xué)習(xí)視頻推薦:java課程

7. 抽象類別和介面的差異

  1. 抽象類別要被子類別繼承,介面要被類別實(shí)作。
    2020全新java基礎(chǔ)面試題彙總
  2. 介面只能做方法聲明,在抽象類別中可以作方法聲明,也可以做方法實(shí)作。
    2020全新java基礎(chǔ)面試題彙總
  3. 介面裡定義的變數(shù)只能是公共的靜態(tài)的常數(shù),抽象類別中的變數(shù)是普通變數(shù)。
    2020全新java基礎(chǔ)面試題彙總
  4. 介面是設(shè)計(jì)的結(jié)果,抽象類別是重構(gòu)的結(jié)果。
    2020全新java基礎(chǔ)面試題彙總
  5. 抽象類別和介面都是用來抽象特定物件的,但是介面的抽象層級最高。
    2020全新java基礎(chǔ)面試題彙總
  6. 抽象類別可以有具體的方法和屬性,介面只能有抽象方法和不可變常數(shù)。
    2020全新java基礎(chǔ)面試題彙總
  7. 抽象類別主要用來抽象類別,介面主要用來抽像功能。
    2020全新java基礎(chǔ)面試題彙總

8. 抽象類別的意義

抽象類別: 一個(gè)類別中如果包含抽象方法,這個(gè)類別應(yīng)該用abstract關(guān)鍵字聲明為抽象類別。

意義:

  1. 為子類別提供一個(gè)公共的型別;
  2. 封裝子類別中重複內(nèi)容(成員變數(shù)與方法) ;
  3. 定義有抽象方法,子類別雖然有不同的實(shí)現(xiàn),但該方法的定義是一致的。

9. 抽象類別與介面的應(yīng)用場景

1.介面(interface)的應(yīng)用場合:

  1. 類別與類別之間需要特定的介面進(jìn)行協(xié)調(diào),而不在乎其如何實(shí)現(xiàn)。
  2. 作為能夠?qū)崿F(xiàn)特定功能的標(biāo)識存在,也可以是什麼介面方法都沒有的純粹標(biāo)識。
  3. 需要將一組類別視為單一的類,而呼叫者只透過介面來與這組類別發(fā)生聯(lián)繫。
  4. 需要實(shí)現(xiàn)特定的多項(xiàng)功能,而這些功能之間可能完全沒有任何關(guān)聯(lián)。

2.抽象類別(abstract.class)的應(yīng)用場合:

一句話,在既需要統(tǒng)一的接口,又需要實(shí)例變數(shù)或缺省的方法的情況下,就可以使用它。最常見的有:

  1. 定義了一組接口,但又不想強(qiáng)迫每個(gè)實(shí)作類別都必須實(shí)作所有的介面??梢杂胊bstract.class定義一組方法體,甚至可以是空方法體,然後由子類別選擇自己感興趣的方法來覆寫。
  2. 某些場合下,只靠純粹的介面無法滿足類別與類別之間的協(xié)調(diào),也必需類別中表示狀態(tài)的變數(shù)來區(qū)別不同的關(guān)係。 abstract的中介作用可以很好地滿足這一點(diǎn)。
  3. 規(guī)範(fàn)了一組相互協(xié)調(diào)的方法,其中一些方法是共同的,與狀態(tài)無關(guān)的,可以共享的,無需子類分別實(shí)現(xiàn);而另一些方法卻需要各個(gè)子類根據(jù)自己特定的狀態(tài)來實(shí)現(xiàn)特定的功能

10. ?抽象類別是否可以沒有方法和屬性?

答案是:可以在

抽象類別中可以沒有抽象方法,但有抽象方法的一定是抽象類別。所以,java中 抽象類別裡面可以沒有抽象方法。注意即使是沒有抽象方法和屬性的抽象類,也不能被實(shí)例化。

11. 接口的意義

  1. 定義接口的重要性:在Java編程,abstract class 和interface是支持抽象類定義的兩種機(jī)制。正是由于這兩種機(jī)制的存在,才使得Java成為面向?qū)ο蟮木幊陶Z言。
  2. 定義接口有利于代碼的規(guī)范:對于一個(gè)大型項(xiàng)目而言,架構(gòu)師往往會對一些主要的接口來進(jìn)行定義,或者清理一些沒有必要的接口。這樣做的目的一方面是為了給開發(fā)人員一個(gè)清晰的指示,告訴他們哪些業(yè)務(wù)需要實(shí)現(xiàn);同時(shí)也能防止由于開發(fā)人員隨意命名而導(dǎo)致的命名不清晰和代碼混亂,影響開發(fā)效率。
  3. 有利于對代碼進(jìn)行維護(hù):比如你要做一個(gè)畫板程序,其中里面有一個(gè)面板類,主要負(fù)責(zé)繪畫功能,然后你就這樣定義了這個(gè)類。可是在不久將來,你突然發(fā)現(xiàn)現(xiàn)有的類已經(jīng)不能夠滿足需要,然后你又要重新設(shè)計(jì)這個(gè)類,更糟糕是你可能要放棄這個(gè)類,那么其他地方可能有引用他,這樣修改起來很麻煩。如果你一開始定義一個(gè)接口,把繪制功能放在接口里,然后定義類時(shí)實(shí)現(xiàn)這個(gè)接口,然后你只要用這個(gè)接口去引用實(shí)現(xiàn)它的類就行了,以后要換的話只不過是引用另一個(gè)類而已,這樣就達(dá)到維護(hù)、拓展的方便性。
  4. 保證代碼的安全和嚴(yán)密:一個(gè)好的程序一定符合高內(nèi)聚低耦合的特征,那么實(shí)現(xiàn)低耦合,定義接口是一個(gè)很好的方法,能夠讓系統(tǒng)的功能較好地實(shí)現(xiàn),而不涉及任何具體的實(shí)現(xiàn)細(xì)節(jié)。這樣就比較安全、嚴(yán)密一些,這一思想一般在軟件開發(fā)中較為常見。

12. Java泛型中的extends和super理解

在平時(shí)看源碼的時(shí)候我們經(jīng)??吹椒盒停医?jīng)常會看到extends和super的使用,看過其他的文章里也有講到上界通配符和下屆通配符,總感覺講的不夠明白。這里備注一下,以免忘記。

  1. extends也成為上界通配符,就是指定上邊界。即泛型中的類必須為當(dāng)前類的子類或當(dāng)前類。
  2. super也稱為下屆通配符,就是指定下邊界。即泛型中的類必須為當(dāng)前類或者其父類。

這兩點(diǎn)不難理解,extends修飾的只能取,不能放,這是為什么呢? 先看一個(gè)列子:

public?class?Food?{}
public?class?Fruit?extends?Food?{}
public?class?Apple?extends?Fruit?{}
public?class?Banana?extends?Fruit{}

public?class?GenericTest?{

????public?void?testExtends(List?extends?Fruit>?list){

????????//報(bào)錯(cuò),extends為上界通配符,只能取值,不能放.
????????//因?yàn)镕ruit的子類不只有Apple還有Banana,這里不能確定具體的泛型到底是Apple還是Banana,所以放入任何一種類型都會報(bào)錯(cuò)
????????//list.add(new?Apple());

????????//可以正常獲取
????????Fruit?fruit?=?list.get(1);
????}

????public?void?testSuper(List?super?Fruit>?list){

????????//super為下界通配符,可以存放元素,但是也只能存放當(dāng)前類或者子類的實(shí)例,以當(dāng)前的例子來講,
????????//無法確定Fruit的父類是否只有Food一個(gè)(Object是超級父類)
????????//因此放入Food的實(shí)例編譯不通過
????????list.add(new?Apple());
//????????list.add(new?Food());

????????Object?object?=?list.get(1);
????}
}

在testExtends方法中,因?yàn)榉盒椭杏玫氖莈xtends,在向list中存放元素的時(shí)候,我們并不能確定List中的元素的具體類型,即可能是Apple也可能是Banana。因此調(diào)用add方法時(shí),不論傳入new Apple()還是new Banana(),都會出現(xiàn)編譯錯(cuò)誤。

理解了extends之后,再看super就很容易理解了,即我們不能確定testSuper方法的參數(shù)中的泛型是Fruit的哪個(gè)父類,因此在調(diào)用get方法時(shí)只能返回Object類型。結(jié)合extends可見,在獲取泛型元素時(shí),使用extends獲取到的是泛型中的上邊界的類型(本例子中為Fruit),范圍更小。

總結(jié):在使用泛型時(shí),存取元素時(shí)用super,獲取元素時(shí),用extends。

13. 父類的靜態(tài)方法能否被子類重寫

不能,父類的靜態(tài)方法能夠被子類繼承,但是不能夠被子類重寫,即使子類中的靜態(tài)方法與父類中的靜態(tài)方法完全一樣,也是兩個(gè)完全不同的方法。

class?Fruit{

????static?String?color?=?"五顏六色";
????static?public?void?call()?{
????????System.out.println("這是一個(gè)水果");
????}
}

public?class?Banana?extends?Fruit{

????static?String?color?=?"黃色";
????static?public?void?call()?{
????????System.out.println("這是一個(gè)香蕉");
????}

????public?static?void?main(String[]?args)?{

????????Fruit?fruit?=?new?Banana();
????????System.out.println(fruit.color);????//五顏六色
????????fruit.call();?????????//這是一個(gè)水果
????}
}

如代碼所示,如果能夠被重寫,則輸出的應(yīng)該是這是一個(gè)香蕉。與此類似的是,靜態(tài)變量也不能夠被重寫。如果想要調(diào)用父類的靜態(tài)方法,應(yīng)該使用類來調(diào)用。 那為什么會出現(xiàn)這種情況呢? 我們要從重寫的定義來說:

重寫指的是根據(jù)運(yùn)行時(shí)對象的類型來決定調(diào)用哪個(gè)方法,而不是根據(jù)編譯時(shí)的類型。

對于靜態(tài)方法和靜態(tài)變量來說,雖然在上述代碼中使用對象來進(jìn)行調(diào)用,但是底層上還是使用父類來調(diào)用的,靜態(tài)變量和靜態(tài)方法在編譯的時(shí)候就將其與類綁定在一起。既然它們在編譯的時(shí)候就決定了調(diào)用的方法、變量,那就和重寫沒有關(guān)系了。

靜態(tài)屬性和靜態(tài)方法是否可以被繼承

可以被繼承,如果子類中有相同的靜態(tài)方法和靜態(tài)變量,那么父類的方法以及變量就會被覆蓋。要想調(diào)用就就必須使用父類來調(diào)用。

class?Fruit{

????static?String?color?=?"五顏六色";
????static?String?xingzhuang?=?"奇形怪狀";
????static?public?void?call()?{
????????System.out.println("這是一個(gè)水果");
????}
????static?public?void?test()?{
????????System.out.println("這是沒有被子類覆蓋的方法");
????}
}

public?class?Banana?extends?Fruit{

????static?String?color?=?"黃色";
????static?public?void?call()?{
????????System.out.println("這是一個(gè)香蕉");
????}

????public?static?void?main(String[]?args)?{

????????Banana?banana?=?new?Banana();????
????????banana.test();?????//這是沒有被子類覆蓋的方法
????????banana.call();?????//調(diào)用Banana類中的call方法????這是一個(gè)香蕉
????????Fruit.call();?????????//調(diào)用Fruit類中的方法?這是一個(gè)水果

????????System.out.println(banana.xingzhuang?+?"?"?+?banana.color);???//奇形怪狀?黃色
????}
}

從上述代碼可以看出,子類中覆蓋了父類的靜態(tài)方法的話,調(diào)用的是子類的方法,這個(gè)時(shí)候要是還想調(diào)用父類的靜態(tài)方法,應(yīng)該是用父類直接調(diào)用。如果子類沒有覆蓋,則調(diào)用的是父類的方法。靜態(tài)變量與此相似。

14. 執(zhí)行緒與行程的差異

  • 定義面向:行程是程式在某個(gè)資料集合上的一次執(zhí)行活動;執(zhí)行緒是行程中的一個(gè)執(zhí)行路徑。 (行程可以建立多個(gè)執(zhí)行緒)
  • 角色方面:在支援執(zhí)行緒機(jī)制的系統(tǒng)中,行程是系統(tǒng)資源分配的單位,執(zhí)行緒是CPU調(diào)度的單位。
  • 資源共享方面:進(jìn)程之間不能共享資源,而執(zhí)行緒共享所在行程的位址空間和其它資源。同時(shí)執(zhí)行緒還有自己的堆疊和堆疊指針,程式計(jì)數(shù)器等暫存器。
  • 獨(dú)立性方面:進(jìn)程有自己獨(dú)立的位址空間,而執(zhí)行緒沒有,執(zhí)行緒必須依賴進(jìn)程而存在。
  • 開銷方面。進(jìn)程切換的開銷較大。線程相對較小。 (前面也提到過,引入線程也出於了開銷的考慮。)

可看下這篇文章:juejin.im/post/684490…

15. final,finally,finalize的區(qū)別

  • final 用於聲明屬性,方法和類別, 分別表示屬性不可變, 方法不可覆寫, 類別不可繼承.
  • finally 是異常處理語句結(jié)構(gòu)的一部分,表示總是執(zhí)行.
  • finalize 是Object類別的一個(gè)方法,在垃圾收集器執(zhí)行的時(shí)候會呼叫被回收物件的此方法,可以覆寫此方法提供垃圾收集時(shí)的其他資源回收,例如關(guān)閉文件等.

16. 序列化Serializable和Parcelable的區(qū)別

#Android中Intent如果要傳遞類別對象,可以透過兩種方式實(shí)現(xiàn)。

方式一:Serializable,要傳遞的類別實(shí)作Serializable介面?zhèn)鬟f對象, 方式二:Parcelable,要傳遞的類別實(shí)作Parcelable介面?zhèn)鬟f物件。

Serializable(Java自帶):Serializable是序列化的意思,表示將物件轉(zhuǎn)換成可儲存或可傳輸?shù)臓顟B(tài)。序列化後的物件可以在網(wǎng)路上傳輸,也可以儲存到本地。 Serializable是一種標(biāo)記接口,這意味著無需實(shí)作方法,Java就會對這個(gè)物件進(jìn)行高效的序列化操作。

Parcelable(Android 專用):Android的Parcelable的設(shè)計(jì)初衷是因?yàn)镾erializable效率過慢(使用反射),為了在程式內(nèi)不同元件間以及不同Android程式間(AIDL)高效的傳輸資料而設(shè)計(jì),這些資料僅在記憶體中存在。 Parcelable方式的實(shí)作原理是將一個(gè)完整的物件分解,而分解後的每一部分都是Intent所支援的資料類型,這樣也就實(shí)現(xiàn)傳遞物件的功能了。

效率及選擇:

Parcelable的效能比Serializable好,因?yàn)獒嵴咴诜瓷溥^程頻繁GC,所以在記憶體間資料傳輸時(shí)建議使用Parcelable,如activity間傳輸資料。而Serializable可將資料持久化方便保存,所以在需要保存或網(wǎng)路傳輸資料時(shí)選擇Serializable,因?yàn)閍ndroid不同版本Parcelable可能不同,所以不建議使用Parcelable進(jìn)行資料持久化。 Parcelable不能使用在要將資料儲存在磁碟上的情況,因?yàn)镻arcelable不能很好的保證資料的持續(xù)性在外界有變化的情況下。儘管Serializable效率低點(diǎn),但此時(shí)還是建議使用Serializable 。

透過intent傳遞複雜資料型別時(shí)必須先實(shí)作兩個(gè)介面之一,對應(yīng)方法分別是getSerializableExtra(),getParcelableExtra()。

17. 靜態(tài)屬性和靜態(tài)方法是否可以被繼承?是否可以被重寫?以及原因?

父類別的靜態(tài)屬性和方法可以被子類別繼承

#不可以被子類別重寫:當(dāng)父類別的引用指向子類時(shí),使用物件呼叫靜態(tài)方法或靜態(tài)變量,是呼叫的父類別中的方法或變數(shù)。並沒有被子類改寫。

原因:

因?yàn)殪o態(tài)方法從程式開始運(yùn)行後就已經(jīng)分配了內(nèi)存,也就是說已經(jīng)寫死了。所有引用到該方法的物件(父類別的物件也好子類別的物件也好)所指向的都是同一塊記憶體中的數(shù)據(jù),也就是該靜態(tài)方法。

子類別中如果定義了相同名稱的靜態(tài)方法,並不會重寫,而應(yīng)該是在記憶體中又分配了一塊給子類別的靜態(tài)方法,沒有重寫這一說。

18 .java中靜態(tài)內(nèi)部類的設(shè)計(jì)意圖

內(nèi)部類別

#內(nèi)部類,即定義在一個(gè)類別的內(nèi)部的類別。為什麼有內(nèi)部類別呢?

我們知道,在java中類別是單繼承的,一個(gè)類別只能繼承另一個(gè)具體類別或抽象類別(可以實(shí)作多個(gè)介面)。這種設(shè)計(jì)的目的是因?yàn)樵诙嘀乩^承中,當(dāng)多個(gè)父類別中有重複的屬性或方法時(shí),子類別的呼叫結(jié)果會含糊不清,因此用了單繼承。

而使用內(nèi)部類別的原因是:每個(gè)內(nèi)部類別都能獨(dú)立地繼承一個(gè)(介面的)實(shí)現(xiàn),所以無論外圍類別是否已經(jīng)繼承了某個(gè)(介面的)實(shí)現(xiàn),對於內(nèi)部類別都沒有影響。

在我們程式設(shè)計(jì)中有時(shí)候會存在一些使用介面很難解決的問題,這個(gè)時(shí)候我們可以利用內(nèi)部類別提供的、可以繼承多個(gè)具體的或是抽象的類別的能力來解決這些程式設(shè)計(jì)問題??梢赃@樣說,介面只是解決了部分問題,而內(nèi)部類別使得多重繼承的解決方案變得更加完整。

靜態(tài)內(nèi)部類別

在說靜態(tài)內(nèi)部類別之前,先了解下成員內(nèi)部類別(非靜態(tài)的內(nèi)部類別)。

成員內(nèi)部類別

成員內(nèi)部類別也是最普通的內(nèi)部類,它是外圍類別的一個(gè)成員,所以它可以無限制的存取外圍類別的所有成員屬性和方法,儘管是private的,但是外圍類別要存取內(nèi)部類別的成員屬性和方法則需要透過內(nèi)部類別實(shí)例來存取。

在成員內(nèi)部類別中要注意兩點(diǎn):

  • 成員內(nèi)部類別中不能存在任何static的變數(shù)和方法;

  • 成員內(nèi)部類別是依附於外圍類別的,所以只有先建立了外圍類別才能夠建立內(nèi)部類別。

靜態(tài)內(nèi)部類別

靜態(tài)內(nèi)部類別與非靜態(tài)內(nèi)部類別之間存在著最大的差異:非靜態(tài)內(nèi)部類別在編譯完成之後會隱含地保存著一個(gè)引用,該引用是指向創(chuàng)建它的外圍內(nèi),但是靜態(tài)內(nèi)部類別卻沒有。

沒有這個(gè)引用就意味著:

  • 它的創(chuàng)建是不需要依賴外圍類別的。

  • 它不能使用任何外圍類別的非static成員變數(shù)和方法。

其它兩種內(nèi)部類別:局部內(nèi)部類別與匿名內(nèi)部類別

#局部內(nèi)部類別

局部內(nèi)部類別是嵌套在方法和作用域內(nèi)的,對於這個(gè)類別的使用主要是應(yīng)用與解決比較複雜的問題,想創(chuàng)建一個(gè)類別來輔助我們的解決方案,到那時(shí)又不希望這個(gè)類別是公共可用的,所以就產(chǎn)生了局部內(nèi)部類,局部內(nèi)部類別和成員內(nèi)部類別一樣被編譯,只是它的作用域發(fā)生了改變,它只能在該方法和屬性中被使用,出了該方法和屬性就會失效。

匿名內(nèi)部類別

  1. 匿名內(nèi)部類別是沒有存取修飾符的。

  2. new 匿名內(nèi)部類,這個(gè)類別首先是要存在的。

  3. 當(dāng)所在方法的形參需要被匿名內(nèi)部類別使用,那麼這個(gè)形參就必須為final。

  4. 匿名內(nèi)部類別沒有明面上的建構(gòu)方法,編譯器會自動產(chǎn)生一個(gè)引用外部類別的建構(gòu)方法。

相關(guān)推薦:java入門

以上是2020全新java基礎(chǔ)面試題彙總的詳細(xì)內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何在Java的地圖上迭代? 如何在Java的地圖上迭代? Jul 13, 2025 am 02:54 AM

遍歷Java中的Map有三種常用方法:1.使用entrySet同時(shí)獲取鍵和值,適用於大多數(shù)場景;2.使用keySet或values分別遍歷鍵或值;3.使用Java8的forEach簡化代碼結(jié)構(gòu)。 entrySet返回包含所有鍵值對的Set集合,每次循環(huán)獲取Map.Entry對象,適合頻繁訪問鍵和值的情況;若只需鍵或值,可分別調(diào)用keySet()或values(),也可在遍歷鍵時(shí)通過map.get(key)獲取值;Java8中可通過Lambda表達(dá)式使用forEach((key,value)-&gt

Java可選示例 Java可選示例 Jul 12, 2025 am 02:55 AM

Optional能清晰表達(dá)意圖並減少null判斷的代碼噪音。 1.Optional.ofNullable是處理可能為null對象的常用方式,如從map中取值時(shí)可結(jié)合orElse提供默認(rèn)值,邏輯更清晰簡潔;2.通過鍊式調(diào)用map實(shí)現(xiàn)嵌套取值,安全地避免NPE,任一環(huán)節(jié)為null則自動終止並返回默認(rèn)值;3.filter可用於條件篩選,滿足條件才繼續(xù)執(zhí)行後續(xù)操作,否則直接跳到o??rElse,適合輕量級業(yè)務(wù)判斷;4.不建議過度使用Optional,如基本類型或簡單邏輯中其反而增加複雜度,部分場景直接返回nu

如何修復(fù)java.io.notserializable Exception? 如何修復(fù)java.io.notserializable Exception? Jul 12, 2025 am 03:07 AM

遇到j(luò)ava.io.NotSerializableException的核心解決方法是確保所有需序列化的類實(shí)現(xiàn)Serializable接口,並檢查嵌套對象的序列化支持。 1.給主類添加implementsSerializable;2.確保類中自定義字段對應(yīng)的類也實(shí)現(xiàn)Serializable;3.用transient標(biāo)記不需要序列化的字段;4.檢查集合或嵌套對像中的非序列化類型;5.查看異常信息定位具體哪個(gè)類未實(shí)現(xiàn)接口;6.對無法修改的類考慮替換設(shè)計(jì),如保存關(guān)鍵數(shù)據(jù)或使用可序列化的中間結(jié)構(gòu);7.考慮改

Java中的可比較與比較器 Java中的可比較與比較器 Jul 13, 2025 am 02:31 AM

在Java中,Comparable用於類內(nèi)部定義默認(rèn)排序規(guī)則,Comparator用於外部靈活定義多種排序邏輯。 1.Comparable是類自身實(shí)現(xiàn)的接口,通過重寫compareTo()方法定義自然順序,適用於類有固定、最常用的排序方式,如String或Integer。 2.Comparator是外部定義的函數(shù)式接口,通過compare()方法實(shí)現(xiàn),適合同一類需要多種排序方式、無法修改類源碼或排序邏輯經(jīng)常變化的情況。兩者區(qū)別在於Comparable只能定義一種排序邏輯且需修改類本身,而Compar

Java方法參考解釋了 Java方法參考解釋了 Jul 12, 2025 am 02:59 AM

方法引用是Java中一種簡化Lambda表達(dá)式的寫法,使代碼更簡潔。它不是新語法,而是Java8引入的Lambda表達(dá)式的一種快捷方式,適用於函數(shù)式接口的上下文。其核心在於將已有方法直接作為函數(shù)式接口的實(shí)現(xiàn)來使用。例如System.out::println等價(jià)於s->System.out.println(s)。方法引用主要有四種形式:1.靜態(tài)方法引用(ClassName::staticMethodName);2.實(shí)例方法引用(綁定到特定對象,instance::methodName);3.

如何處理Java中的字符編碼問題? 如何處理Java中的字符編碼問題? Jul 13, 2025 am 02:46 AM

處理Java中的字符編碼問題,關(guān)鍵是在每一步都明確指定使用的編碼。 1.讀寫文本時(shí)始終指定編碼,使用InputStreamReader和OutputStreamWriter並傳入明確的字符集,避免依賴系統(tǒng)默認(rèn)編碼。 2.在網(wǎng)絡(luò)邊界處理字符串時(shí)確保兩端一致,設(shè)置正確的Content-Type頭並用庫顯式指定編碼。 3.謹(jǐn)慎使用String.getBytes()和newString(byte[]),應(yīng)始終手動指定StandardCharsets.UTF_8以避免平臺差異導(dǎo)致的數(shù)據(jù)損壞??傊?,通過在每個(gè)階段

如何在Java解析JSON? 如何在Java解析JSON? Jul 11, 2025 am 02:18 AM

解析JSON在Java中的常見方式有三種:使用Jackson、Gson或org.json。 1.Jackson適合大多數(shù)項(xiàng)目,性能好且功能全面,支持對象與JSON字符串之間的轉(zhuǎn)換及註解映射;2.Gson更適合Android項(xiàng)目或輕量級需求,使用簡單但處理複雜結(jié)構(gòu)和高性能場景略遜;3.org.json適用於簡單任務(wù)或小腳本,不推薦用於大型項(xiàng)目,因其靈活性和類型安全不足。選擇應(yīng)根據(jù)實(shí)際需求決定。

新電子郵件的Outlook快捷方式 新電子郵件的Outlook快捷方式 Jul 11, 2025 am 03:25 AM

在Outlook中快速新建郵件的方法如下:1.桌面版使用快捷鍵Ctrl Shift M,可直接彈出新郵件窗口;2.網(wǎng)頁版可通過創(chuàng)建包含JavaScript的書籤(如javascript:document.querySelector("divrole='button'").click())實(shí)現(xiàn)一鍵新建郵件;3.使用瀏覽器插件(如Vimium、CrxMouseGestures)自定義快捷鍵觸發(fā)“新建郵件”按鈕;4.Windows用戶還可通過右鍵任務(wù)欄Outlook圖標(biāo)選擇“新建電

See all articles