2019年Android開發者常見面試題(二)

上一篇主要介紹的是Java相關的面試題,其實已經重複的說過,在Android面試中,Java相關的面試大概要佔到20%,甚至是大於20%,所以不得不顯得尤爲重要,畢竟目前的開發中,Java語言開發畢竟還是佔到絕大部分的。

這篇繼續Java相關的面試題分享:

問題 8:抽象類的意義

答案【答案不唯一,可自己衡量】:

抽象類往往用來表徵對問題領域進行分析、設計中得出的抽象概念,是對一系列看上去不同,但是本質上相同的具體概念的抽象。具體分析如下:

1.因爲抽象類不能實例化對象,所以必須要有子類來實現它之後才能使用。這樣就可以把一些具有相同屬性和方法的組件進行抽象,這樣更有利於代碼和程序的維護。

比如本科和研究生可以抽象成學生,他們有相同的屬性和方法。這樣當你對其中某個類進行修改時會受到父類的限制,這樣就會提醒開發人員有些東西不能進行隨意修改,這樣可以對比較重要的東西進行統一的限制,也算是一種保護,對維護會有很大的幫助。 
2.當又有一個具有相似的組件產生時,只需要實現該抽象類就可以獲得該抽象類的那些屬性和方法。 
比如學校又新產生了專科生這類學生,那麼專科生直接繼承學生,然後對自己特有的屬性和方法進行補充即可。這樣對於代碼的重用也是很好的體現。

所以,Java中抽象類對於代碼的維護和重用有很好的幫助,也是Java面向對象的一個重要體現。

 

問題 9:抽象類與接口的應用場景

答案【答案不唯一,可自己衡量】:

應用都是基於規則的應用,也就是基於語法的應用,我們可以根據語法上的異同點來總結抽象類和接口的應用場景

相同點沒有什麼可說的,我們從不同點下手。

1、第一個重要的不同點

抽象類中不一定都是抽象的方法,也可以有具體實現的方法,這樣就可以把大家公用的方法提升到抽象類中,然後具體的方法可以留給子類自己實現(此處經典的應用,模板方法設計模式)。所以抽象類可以更好的實現代碼的複用

2、另一個重要的不同就是類可以實現多個接口。

接口和抽象類的概念不一樣。這個可以理解爲接口是對動作的抽象,抽象類是對根源的抽象(即對本質的抽象與其他類的本質不同)。

抽象類表示的是,這個對象是什麼。接口表示的是,這個對象能做什麼。比如,男人,女人,這兩個類(如果是類的話……),他們的抽象類是人。說明,他們都是人。人可以吃東西,狗也可以吃東西,你可以把“吃東西”定義成一個接口,然後讓這些類去實現它。

所以,在高級語言上,一個類只能繼承一個類(抽象類)(正如人不可能同時是生物和非生物),但是可以實現多個接口(吃飯接口、走路接口)。

當你關注一個事物的本質的時候,用抽象類;當你關注一個操作的時候,用接口。

另一個重要的概念就是多態,多態通過分離做什麼和怎麼做,從另一個角度將接口和實現分離出來。多態不但能夠改善代碼的組織結果和可讀性,還能創建可擴展的程序----即無論在項目最初創建時還是在需要添加新功能時都可以“生長”的程序。由於接口更關注於動作的實現,多態主要是分離“做什麼”和“怎麼做”,所以接口的另一個重要的應用就是多態的實現(當然抽象類也可以實現多態,但是接口更加合適)。

抽象類的功能要遠超過接口,但是,定義抽象類的代價高。因爲高級語言來說(從實際設計上來說也是)每個類只能繼承一個類。在這個類中,你必須繼承或編寫出其所有子類的所有共性。雖然接口在功能上會弱化許多,但是它只是針對一個動作的描述。而且你可以在一個類中同時實現多個接口。在設計階段會降低難度的。

 

10:抽象類是否可以沒有方法和屬性

答案【答案不唯一,可自己衡量】:

答案是肯定的,可以。

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

 

問題 11:接口的意義

答案【答案不唯一,可自己衡量】:

1、定義接口的重要性:在Java編程,abstract class 和interface是支持抽象類定義的兩種機制。正是由於這兩種機制的存在,才使得Java成爲面向對象的編程語言。

2、定義接口有利於代碼的規範:對於一個大型項目而言,架構師往往會對一些主要的接口來進行定義,或者清理一些沒有必要的接口。這樣做的目的一方面是爲了給開發人員一個清晰的指示,告訴他們哪些業務需要實現;同時也能防止由於開發人員隨意命名而導致的命名不清晰和代碼混亂,影響開發效率。

3、有利於對代碼進行維護:比如你要做一個畫板程序,其中裏面有一個面板類,主要負責繪畫功能,然後你就這樣定義了這個類。可是在不久將來,你突然發現現有的類已經不能夠滿足需要,然後你又要重新設計這個類,更糟糕是你可能要放棄這個類,那麼其他地方可能有引用他,這樣修改起來很麻煩。如果你一開始定義一個接口,把繪製功能放在接口裏,然後定義類時實現這個接口,然後你只要用這個接口去引用實現它的類就行了,以後要換的話只不過是引用另一個類而已,這樣就達到維護、拓展的方便性。

4、保證代碼的安全和嚴密:一個好的程序一定符合高內聚低耦合的特徵,那麼實現低耦合,定義接口是一個很好的方法,能夠讓系統的功能較好地實現,而不涉及任何具體的實現細節。這樣就比較安全、嚴密一些,這一思想一般在軟件開發中較爲常見。

 

問題 12:泛型中extends和super的區別

答案【答案不唯一,可自己衡量】:

<? extends T>限定參數類型的上界:參數類型必須是T或T的子類型

<? super T> 限定參數類型的下界:參數類型必須是T或T的超類型

總結爲:

<? extends T> 只能用於方法返回,告訴編譯器此返參的類型的最小繼承邊界爲T,T和T的父類都能接收,但是入參類型無法確定,只能接受null的傳入

<? super T>只能用於限定方法入參,告訴編譯器入參只能是T或其子類型,而返參只能用Object類接收

? 既不能用於入參也不能用於返參

 

問題 13:父類的靜態方法能否被子類重寫

答案【答案不唯一,可自己衡量】:

首先答案是不能!

這個問題有兩個關鍵字,一個是靜態方法,一個是重寫。

我們來先說說重寫,可能很多初學的朋友分不清重寫和重載的區別。

重寫:子類繼承父類後,定義了一個和父類中的一模一樣方法,這個一模一樣是值方法名和參數的定義一模一樣。這時候子類要實現這個方法,就稱爲對父類方法的重寫。

重載:子類繼承父類後,定義了一個和父類中相同名字的方法,但是參數不一樣(必須),實現也不同(可選),這就是重載。

靜態方法:java中,static修飾符修飾的方法就是靜態方法。所謂靜態就是指:在編譯之後所分配的內存會一直存在(不會被回收),直到程序退出內存纔會釋放這個空間。

在java中,所有的東西都是對象,對象的抽象就是類,對於一個類而言,如果要使用他的成員(類中的屬性,方法等),一般情況下,必須先實例化對象後,通過對象的引用才能訪問這些成員。

但是,如果要使用的成員使用了static修飾,就可以不通過實例化獲得該成員。

就比如,現在有個桌子,我想吃蘋果,一般情況下,我需要先拿個盤子(對象的實例化)去裝蘋果才能吃到蘋果,現在有個蘋果直接放在桌子上(用static修飾過的靜態方法),這樣我就可以直接從桌子上拿到蘋果。可能大家會有疑問,既然靜態方法(能不通過實例化就使用成員)這麼方便,爲什麼不都使用靜態方法。

大家回到static這個修飾符的功能定義:所謂靜態就是指:在編譯之後所分配的內存會一直存在(不會被回收),直到程序退出內存纔會釋放這個空間。

java的回收機制會定時的回收已經使用過的對象的內存來釋放內存給應用程序。如果全部都是靜態變量和靜態方法,內存都被佔用了,java程序哪裏還有運行的空間呢?就好比,你回家就看到桌子上擺滿了蘋果,那你買的梨子就沒地方放了。

現在回到題目中來,父類的靜態方法能不能被重寫。答案是不能。

因爲靜態方法從程序開始運行後就已經分配了內存,也就是說已經寫死了。所有引用到該方法的對象(父類的對象也好子類的對象也好)所指向的都是同一塊內存中的數據,也就是該靜態方法。子類中如果定義了相同名稱的靜態方法,並不會重寫,而應該是在內存中又分配了一塊給子類的靜態方法,沒有重寫這一說。

 

問題 14:進程和線程的區別

答案【答案不唯一,可自己衡量】:

1. 定義

進程是一個術語,用來描述一組資源和程序運行所需的內存分配。對於每一個被加載到內存的exe,在它的生命週期中操作系統會爲之創建一個單獨隔離的進程。一個進程的失敗不會影響其他的進程。每個進程是由私有的虛擬地址空間、代碼、數據和其他各種系統資源組成的。

線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。系統創建好進程後,實際就啓動執行了該進程的主線程,主線程終止了,進程也就隨之終止,每一個進程至少有一個線程(即主線程,它無需由用戶主動去創建,是由系統在應用程序啓動後創建的),用戶根據需要在應用程序中創建其他線程,使多個線程併發的運行在同一個進程中。

2.關係

一個線程可以創建和撤銷另一個線程;同一個進程中的多個線程之間可以併發執行.

相對進程而言,線程是一個更加接近於執行體的概念,它可以與同進程中的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。

3.區別

進程和線程的主要差別在於它們是不同的操作系統資源管理方式。進程有獨立的地址空 間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行並且又要共享某些變量的併發操作,只能用線程,不能用進程。

1) 簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.

2) 線程的劃分尺度小於進程,使得多線程程序的併發性高。

3) 另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。

4) 線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

5) 從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章