首頁  >  文章  >  Java  >  Java的基礎面試題目(2)

Java的基礎面試題目(2)

(*-*)浩
(*-*)浩原創
2019-11-30 15:28:331524瀏覽

Java的基礎面試題目(2)

11、是否可以從一個static方法內部發出對非static方法的呼叫?

不可以。因為非static方法是要與物件關聯在一起的,必須建立一個物件後,才可以在該物件上進行方法調用,而static方法調用時不需要建立對象,可以直接調用。 (推薦學習:java面試題目

也就是說,當一個static方法被呼叫時,可能還沒有創建任何實例對象,如果從一個static方法中發出對非static方法的調用,那個非static方法是關聯到哪個物件上的呢?這個邏輯無法成立,所以,一個static方法內部發出對非static方法的呼叫。

12、Integer與int的差異

int是java提供的8種原始資料型別之一。 Java為每個原始類型提供了封裝類,Integer是java為int提供的封裝類別。 int的預設值為0,而Integer的預設值為null,即Integer可以區分出未賦值和值為0的區別,int則無法表達出未賦值的情況。

例如:若要表達出沒有參加考試和考試成績為0的區別,則只能使用Integer。在JSP開發中,Integer的預設值為null,所以用el表達式在文字方塊中顯示時,值為空白字串,而int預設的預設值為0,所以用el表達式在文字方塊中顯示時,結果為0,所以,int不適合作為web層的表單資料的型別。

在Hibernate中,如果將OID定義為Integer類型,那麼Hibernate就可以根據其值是否為null而判斷一個物件是否是臨時的,如果將OID定義為了int類型,還需要在hbm映射文件中設定其unsaved-value屬性為0。

另外,Integer提供了多個與整數相關的操作方法,例如,將一個字串轉換成整數,Integer中也定義了表示整數的最大值和最小值的常數。

13、Math.round(11.5)等於多少?Math.round(-11.5)等於多少?

##Math類別中提供了三個與取整有關的方法:ceil、floor、round,這些方法的作用與它們的英文名稱的含義相對應。

例如,ceil的英文意義是天花板,該方法就表示向上取整,Math.ceil(11.3)的結果為12,Math.ceil(-11.3)的結果是-11;

floor的英文意義是地板,該方法就表示向下取整,Math.ceil(11.6)的結果為11,Math.ceil(-11.6)的結果是-12;

最難掌握的是round方法,它表示“四捨五入”,演算法為Math.floor(x 0.5),即將原來的數字加上0.5後再向下取整,所以,Math.round(11.5)的結果為12, Math.round(-11.5)的結果為-11。

14、Overload和Override的差別? Overloaded的方法是否可以改變回傳值的型別?

Overload是重載的意思,Override是覆寫的意思,也就是重寫。

重載Overload表示同一個類別中可以有多個名稱相同的方法,但這些方法的參數清單各不相同(即參數個數或型別不同)。

重寫Override表示子類別中的方法可以與父類別中的某個方法的名稱和參數完全相同,透過子類別建立的實例物件呼叫這個方法時,將呼叫子類別中的定義方法,這相當於把父類別中定義的那個完全相同的方法給覆蓋了,這也是物件導向程式設計的多態性的一種表現。

子類別覆寫父類別的方法時,只能比父類別拋出更少的異常,或者是拋出父類別拋出的異常的子異常,因為子類別可以解決父類別的一些問題,不能比父類有更多的問題。

子類別方法的存取權限只能比父類別的更大,不能更小。如果父類別的方法是private類型,那麼,子類別則不存在覆蓋的限制,相當於子類別中增加了一個全新的方法。

至於Overloaded的方法是否可以改變回傳值的型別這個問題,要看你倒底想問什麼呢?

這個題目很模糊。如果幾個Overloaded的方法的參數清單不一樣,它們的回傳者類型當然也可以不一樣。

但我估計你想問的問題是:如果兩個方法的參數列表完全一樣,是否可以讓它們的回傳值不同來實作重載Overload。

這是不行的,我們可以用反證法來說明這個問題,因為我們有時在呼叫一個方法時也可以不定義回傳結果變量,即不要關心其傳回結果。

例如,當我們呼叫map.remove(key)方法時,雖然remove方法有回傳值,但是我們通常都不會定義接收傳回結果的變量,這時候假設該類別中有兩個名稱和參數清單完全相同的方法,光是傳回型別不同,java就無法確定程式設計者倒底是想呼叫哪個方法了,因為它無法透過傳回結果類型來判斷。

override可以翻譯為覆蓋,從字面就可以知道,它是覆蓋了一個方法並且對其重寫,以求達到不同的作用。

對我們來說最熟悉的覆蓋就是對介面方法的實現,在介面中一般只是對方法進行了聲明,而我們在實現時,就需要實現介面聲明的所有方法。除了這個典型的用法以外,我們在繼承中也可能會在子類別覆寫父類別中的方法。在覆蓋要注意以下的幾點:

1、覆蓋的方法的標誌必須要和被覆蓋的方法的標誌完全匹配,才能達到覆蓋的效果;

2、覆蓋的方法的回傳值必須和被覆寫的方法的回傳一致;

3、覆寫的方法所拋出的例外必須和被覆寫方法的所拋出的異常一致,或者是其子類別;

4、被覆寫的方法不能為private,否則在其子類別中只是新定義了一個方法,並沒有對其進行覆寫。

Overload對我們來說可能比較熟悉,可以翻譯為重載,它是指我們可以定義一些名稱相同的方法,透過定義不同的輸入參數來區分這些方法,然後再呼叫時,VM就會根據不同的參數樣式,來選擇適當的方法執行。在使用重載要注意以下的幾點:

1、使用重載時只能透過不同的參數樣式。例如,不同的參數類型,不同的參數個數,不同的參數順序(當然,同一方法內的幾個參數類型必須不一樣,例如可以是fun(int,float),但是不能為fun(int,int ));

2、不能透過存取權限、傳回型別、拋出的例外進行重載;

3、方法的例外類型和數目不會對重載造成影響;

4、對於繼承來說,如果某一方法在父類別中是存取權限是priavte,那麼就不能在子類別中重載,如果定義的話,也只是定義了一個新方法,而不會達到重載的效果。

15、介面是否可繼承介面?抽象類別是否可實現(implements)介面?抽象類別是否可繼承特定類別(concreteclass)?抽象類別中是否可以有靜態的main方法?

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

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

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

16、Java中實作多型態的機制是什麼?

靠的是父類別或介面定義的參考變數可以指向子類別或具體實作類別的實例對象,而程式呼叫的方法在運行期間才會動態綁定,就是引用變數所指向的具體實例物件的方法,也就是記憶體裡正在運行的那個物件的方法,而不是引用變數的型別中定義的方法。

17、abstractclass和interface語法上有什麼差別?

1.抽象類別可以有建構方法,介面中不能有建構方法。

2.抽象類別中可以有普通成員變量,介面中沒有普通成員變數

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

4. 抽象類別中的抽象方法的存取類型可以是public,protected和(預設類型,雖然eclipse下不報錯,但應該也不行),但介面中的抽象方法只能是public類型的,並且預設為public abstract類型。

5. 抽象類別中可以包含靜態方法,介面中不能包含靜態方法

6. 抽象類別和介面中都可以包含靜態成員變數,抽象類別中的靜態成員變數的存取類型可以任意,但介面中定義的變數只能是publicstatic final類型,且預設為publicstatic final類型。

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

18、abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?

abstract的method不可以是static的,因為抽象的方法是要被子類別實現的,而static與子類別扯不上關係!

native方法表示該方法要用另一個依賴平台的程式語言實現的,不存在被子類別實現的問題,所以,它也不能是抽象的,不能與abstract混用。

例如,FileOutputSteam類別要硬體打交道,底層的實作用的是作業系統相關的api實作;例如,在windows用c語言實現的,所以,查看jdk的源代碼,可以發現FileOutputStream的open方法的定義如下:

private native void open(Stringname) throwsFileNotFoundException;

如果我們要用java呼叫別人寫的c語言函數,我們是無法直接呼叫的,我們需要按照java的要求寫一個c語言的函數,又我們的這個c語言函數去呼叫別人的c語言函數。

由於我們的c語言函數是按java的要求來寫的,我們這個c語言函數就可以與java對接上,java那邊的對接方式就是定義出與我們這個c函數相對應的方法,java對應的方法不需要寫具體的程式碼,但需要在前面宣告native。

關於synchronized與abstract合用的問題,我覺得也不行,因為在我幾年的學習和開發中,從來沒見過過這種情況,並且我覺得synchronized應該是作用在一個具體的方法上才有意義。

而且,方法上的synchronized同步所使用的同步鎖定物件是this,而抽象方法上無法確定this是什麼。

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

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

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

class Outer
{
    static int x;
    static class Inner
    {
        voidtest(){
          syso(x);
        }
    }
}

20、String s = "Hello";s = s "world!";這兩行程式碼執行後,原始的String物件中的內容到底變了沒有?

沒有。因為String被設計成不可變(immutable)類,所以它的所有物件都是不可變物件。

在這段程式碼中,s原先指向一個String對象,內容是 "Hello",然後我們對s進行了 操作,那麼s所指向的那個對像是否發生了改變呢?答案是沒有。

這時,s不指向原來那個物件了,而指向了另一個String對象,內容為"Hello world!",原來那個物件還存在於記憶體之中,只是s這個引用變數不再指向它了。

透過上面的說明,我們很容易導出另一個結論,如果經常對字串進行各種各樣的修改,或者說,不可預見的修改,那麼使用String來代表字串的話會引起很大的記憶體開銷。

因為String物件建立之後不能再改變,所以對於每一個不同的字串,都需要一個String物件來表示。這時,應該考慮使用StringBuffer類,它允許修改,而不是每個不同的字串都要產生一個新的物件。並且,這兩種類別的物件轉換十分容易。

同時,我們也可以知道,如果要使用內容相同的字串,不必每次都new一個String。例如我們要在建構器中對一個名叫s的String引用變數進行初始化,把它設為初始值,應這樣做:

public class Demo {
    private String s;
    ...
public Demo {
    s = "Initial Value";
    }
    ...
}

#而非

s = new String("Initial Value");

後者每次都會呼叫建構器,產生新對象,效能低且記憶體開銷大,且沒有意義,因為String物件不可改變,所以對於內容相同的字串,只要一個String物件來表示就可以了。

也就說,多次呼叫上面的建構器來建立多個對象,他們的String類型屬性s都指向同一個對象。

上面的結論也基於這樣一個事實:對於字串常數,如果內容相同,Java認為它們代表同一個String物件。而用關鍵字new呼叫建構器,總是會建立一個新的對象,無論內容是否相同。

至於為什麼要把String類別設計成不可變類,是它的用途決定的。其實不只String,很多Java標準類別庫中的類別都是不可變的。

在開發一個系統的時候,我們有時候也需要設計不可變類,來傳遞一組相關的值,這也是物件導向思想的體現。

不可變類別有一些優點,例如因為它的物件是唯讀的,所以多執行緒並發存取也不會有任何問題。當然也有一些缺點,例如每個不同的狀態都要一個物件來代表,可能會造成效能上的問題。所以Java標準類別函式庫也提供了一個可變版本,即StringBuffer。

以上是Java的基礎面試題目(2)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn