Java面試題之Java基礎部分 21-30題

20、接口是否可繼承接口?抽象類是否可實現(implements)接口?抽象類是否可繼承具體類(concrete class)?抽象類中是否可以有靜態的main方法?

    接口可以繼承接口。抽象類可以實現(implements)接口,抽象類可以繼承具體類。抽象類中可以有靜態的main方法

    備註:只要明白了接口和抽象類的本質和作用,這些問題都很好回答,你想想,如果你是java語言的設計者,你是否會提供這樣的支持,如果不提供的話,有什麼理由嗎?如果你沒有道理不提供,那答案就是肯定的了。

只有記住抽象類與普通類的唯一區別:就是不能創建實例對象和允許有abstract方法。

 

21、寫clone()方法時,通常都有一行代碼,是什麼?

clone 有缺省行爲,super.clone();他負責產生正確大小的空間,並逐位複製。

因爲首先要把父類中的成員複製到位,然後纔是複製自己的成員

 

22、面向對象的特徵有哪些方面

1抽象

 抽象就是忽略一個主題中與當前目標無關的那些方面,以便更充分地注意與當前目標有關的方面。抽象並不打算了解全部問題,而只是選擇其中的一部分,暫時不用部分細節。抽象包括兩個方面,一是過程抽象,二是數據抽象。

2繼承

繼承是一種聯結類的層次模型,並且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。對象的一個新類可以從現有的類中派生,這個過程稱爲類繼承。新類繼承了原始類的特性,新類稱爲原始類的派生類(子類),而原始類稱爲新類的基類(父類)。派生類可以從它的基類那裏繼承方法和實例變量,並且類可以修改或增加新的方法使之更適合特殊的需要。

3封裝

封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面。面向對象計算始於這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的對象,這些對象通過一個受保護的接口訪問其他對象。

4多態性

多態性是指允許不同類的對象對同一消息作出響應。多態性包括參數化多態性和包含多態性。多態性語言具有靈活、抽象、行爲共享、代碼共享的優勢,很好的解決了應用程序函數同名問題

 

23java中實現多態的機制是什麼?

靠的是父類或接口定義的引用變量可以指向子類或具體實現類的實例對象,而程序調用的方法在運行期才動態綁定,就是引用變量所指向的具體實例對象的方法,也就是內存里正在運行的那個對象的方法,而不是引用變量的類型中定義的方法

 

24、接口(interface)和抽象類(abstract class)有什麼區別?你選擇使用接口和抽象類的依據是什麼?

兩者的語法區別:

1.抽象類可以有構造方法,接口中不能有構造方法。

2.抽象類中可以有普通成員變量,接口中沒有普通成員變量

3.抽象類中可以包含非抽象的普通方法,接口中的所有方法必須都是抽象的,不能有非抽象的普通方法。

4. 抽象類中的抽象方法的訪問類型可以是publicprotected和(默認類型,雖然eclipse下不報錯,但應該也不行),但接口中的抽象方法只能是public類型的,並且默認即爲public abstract類型。

5. 抽象類中可以包含靜態方法,接口中不能包含靜態方法

6. 抽象類和接口中都可以包含靜態成員變量,抽象類中的靜態成員變量的訪問類型可以任意,但接口中定義的變量只能是public static final類型,並且默認即爲public static final類型。

7. 一個類可以實現多個接口,但只能繼承一個抽象類。

 

應用場合很簡單了 (接口用於規範,抽象類用於共性):

優先定義接口 

如果有多個接口實現有公用的部分,則使用抽象類,然後集成它。

 

擴展:

    含有abstract修飾符的class即爲抽象類,abstract類不能創建的實例對象。含有abstract方法的類必須定義爲abstract classabstract class類中的方法不必是抽象的。abstract class類中定義抽象方法必須在具體(Concrete)子類中實現,所以,不能有抽象構造方法或抽象靜態方法。如果的子類沒有實現抽象父類中的所有抽象方法,那麼子類也必須定義爲abstract類型。

接口(interface)可以說成是抽象類的一種特例,接口中的所有方法都必須是抽象的。接口中的方法定義默認爲public abstract類型,接口中的成員變量類型默認爲public static final

下面接着再說說兩者在應用上的區別:

接口更多的是在系統架構設計方法發揮作用,主要用於定義模塊之間的通信契約。而抽象類在代碼實現方面發揮作用,可以實現代碼的重用,例如,模板方法設計模式是抽象類的一個典型應用,假設某個項目的所有Servlet類都要用相同的方式進行權限判斷、記錄訪問日誌和處理異常,那麼就可以定義一個抽象的基類,讓所有的Servlet都繼承這個抽象基類,在抽象基類的service方法中完成權限判斷、記錄訪問日誌和處理異常的代碼,在各個子類中只是完成各自的業務邏輯代碼,僞代碼如下:

public abstract classBaseServlet extends HttpServlet{

public final void service(HttpServletRequest request,HttpServletResponse response) throws IOExcetion,ServletException {

記錄訪問日誌

進行權限判斷

if(具有權限){

try{

   doService(request,response);

   }

catch(Excetpion e) {

   記錄異常信息

   }

}

}

protected abstract void doService(HttpServletRequest request,HttpServletResponse response) throws IOExcetion,ServletException;

//注意訪問權限定義成protected,顯得既專業,又嚴謹,因爲它是專門給子類用的

}

 

public class MyServlet1 extendsBaseServlet

{

    protected voiddoService(HttpServletRequest request, HttpServletResponse response) 

        throwsIOExcetion,ServletException{

        本Servlet只處理的具體業務邏輯代碼

    }

}

父類方法中間的某段代碼不確定,留給子類幹,就用模板方法設計模式。

備註:這道題的思路是先從總體解釋抽象類和接口的基本概念,然後再比較兩者的語法細節,最後再說兩者的應用區別。比較兩者語法細節區別的條理是:先從一個類中的構造方法、普通成員變量和方法(包括抽象方法),靜態變量和方法,繼承性等6個方面逐一去比較回答,接着從第三者繼承的角度的回答,特別是最後用了一個典型的例子來展現自己深厚的技術功底。

 

25abstractmethod是否可同時是static,是否可同時是native,是否可同時是synchronized?

都不行;

    static修飾一個方法時,表明這個方法屬於該類本身,即通過類就可以調用這個方法,這與abstract修飾的方法,必須實例化後才能調用相矛盾。

    native方法表示該方法要用另外一種依賴平臺的編程語言實現的,不存在着被子類實現的問題,所以,它也不能是抽象的,不能與abstract混用。例如,FileOutputSteam類要硬件打交道,底層的實現用的是操作系統相關的api實現,例如,在windowsc語言實現的,所以,查看jdk的源代碼,可以發現FileOutputStreamopen方法的定義如下:

     private native void open(Stringname) throws FileNotFoundException;

如果我們要用java調用別人寫的c語言函數,我們是無法直接調用的,我們需要按照java的要求寫一個c語言的函數,又我們的這個c語言函數去調用別人的c語言函數。由於我們的c語言函數是按java的要求來寫的,我們這個c語言函數就可以與java對接上,java那邊的對接方式就是定義出與我們這個c函數相對應的方法,java中對應的方法不需要寫具體的代碼,但需要在前面聲明native

關於synchronizedabstract合用的問題,我覺得也不行,因爲在我幾年的學習和開發中,從來沒見到過這種情況,並且我覺得synchronized應該是作用在一個具體的方法上纔有意義。而且,方法上的synchronized同步所使用的同步鎖對象是this,而抽象方法上無法確定this是什麼

 

26、什麼是內部類?Static Nested ClassInner Class的不同

    內部類就是在一個類的內部定義的類,內部類中不能定義靜態成員

Nested Class (一般是C++的說法),Inner Class (一般是JAVA的說法)Java內部類與C++嵌套類最大的不同就在於是否有指向外部的引用上。

 

擴展:

Anonymous Inner Class (匿名內部類) 是否可以extends(繼承)其它類,是否可以implements(實現)interface(接口)?

 

Inner Class(內部類)定義在類中的類。 

Nested Class(嵌套類)是靜態(static)內部類。1. 要創建嵌套類的對象,並不需要其外圍類的對象。 2. 不能從嵌套類的對象中訪問非靜態的外圍類對象。

 

Anonymous Inner Class (匿名內部類)匿名的內部類是沒有名字的內部類。

 

匿名的內部類不能extends(繼承)其它類,但一個內部類可以作爲一個接口,由另一個內部類實現。

 

嵌套類可以作爲接口的內部類。正常情況下,你不能在接口內部放置任何代碼,但嵌套類可以作爲接口的一部分,因爲它是static 的。只是將嵌套類置於接口的命名空間內,這並不違反接口的規則。

 

內部類被繼承,由於內部類有一個指向外圍類對象的祕密引用,所以在繼承內部類的時候,該祕密引用必須被初始化。解決方法是enclosingClassReference.super();語法,看一下代碼:

 

class Outer

...{

     class Inner

      ...{

      }

}

class AnoClass extends Outer.Inner

...{

     AnoClass (Outer wi)

        ...{

             wi.super();

        }

}

 

匿名類(Anonymous Class

  當一個內部類的類聲名只是在創建此類對象時用了一次,而且要產生的新類需繼承於一個已有的父類或實現一個接口,才能考慮用匿名類,由於匿名類本身無名,因此它也就不存在構造方法,它需要顯示地調用一個無參的父類的構造方法,並且重寫父類的方法。

 

。。。。。。。。。。。。

 

f.addMouseMotionListener(new MouseMotionAdapter(){ //匿名類開始

       public void mouseDragged(MouseEvent e){

        String s="Mouse dragging: x="+e.getX()+"Y="+e.getY();

        tf.setText(s); }

      } ); //匿名類結束

 

  存在它的原因是:

  1.一個內部類的對象能夠訪問創建它的對象的實現,包括私有數據。即內部類實例對包含它的哪個類的實例來說,是特權的。

  2.對於同一個包中的其他類來說,內部類能夠隱藏起來,換句話說,內部類不管方法的可見性如何,那怕是public,除了包容類,其他類都無法使用它。

  3.匿名內部類可以很方便的定義回調。

  4.使用內部類可以非常方便的編寫事件驅動程序。

其實它真正的目的僅僅爲了定義回調--進一步就是事件驅動。

 

 在使用匿名內部類時,要記住以下幾個原則: 

  ·匿名內部類不能有構造方法。   

  ·匿名內部類不能定義任何靜態成員、方法和類。   

  ·匿名內部類不能是public,protected,private,static。   

  ·只能創建匿名內部類的一個實例。 

    ·一個匿名內部類一定是在new的後面,用其隱含實現一個接口或實現一個類。   

  ·因匿名內部類爲局部內部類,所以局部內部類的所有限制都對其生效。

 

匿名類和內部類中的中的this :

有時候,我們會用到一些內部類和匿名類。當在匿名類中用this時,這個this則指的是匿名類或內部類本身。 這時如果我們要使用外部類的方法和變量的話,則應該加上外部類的類名。

 

27、內部類可以引用它的包含類的成員嗎?有沒有什麼限制?

完全可以。如果不是靜態內部類,那沒有什麼限制!

如果你把靜態嵌套類當作內部類的一種特例,那在這種情況下不可以訪問外部類的普通成員變量,而只能訪問外部類中的靜態成員,例如,下面的代碼:

class Outer

{

     static int x;

     static class Inner

     {

          void test()

        {

             syso(x);

        }

     }

}

答題時,也要能察言觀色,揣摩提問者的心思,顯然人家希望你說的是靜態內部類不能訪問外部類的成員,但你一上來就頂牛,這不好,要先順着人家,讓人家滿意,然後再說特殊情況,讓人家吃驚。

 

28Anonymous Inner Class (匿名內部類)是否可以extends(繼承)其它類,是否可以implements(實現)interface(接口)?

可以繼承其他類或實現其他接口。不僅是可以,而是必須!

 

29super.getClass()方法調用

下面程序的輸出結果是多少?

importjava.util.Date;

public class Test extends Date{

      public static void main(String[] args) {

            new Test().test();

      }

      public void test(){

           System.out.println(super.getClass().getName());

      }

}

結果是Test。在test方法中,直接調用getClass().getName()方法,返回的是Test類名

    由於getClass()Object類中定義成了final,子類不能覆蓋該方法,所以,在test方法中調用getClass().getName()方法,其實就是在調用從父類繼承的getClass()方法,等效於調用super.getClass().getName()方法,所以,super.getClass().getName()方法返回的也應該是Test

   如果想得到父類的名稱,應該用如下代碼:

         getClass().getSuperClass().getName();

 

30、String是最基本的數據類型嗎?

不是。基本數據類型包括byteintcharlongfloatdoublebooleanshortjava.lang.String類是final類型的,因此不可以繼承這個類、不能修改這個類。爲了提高效率節省空間,我們應該用StringBuffer類。

發佈了116 篇原創文章 · 獲贊 34 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章