1. 程式人生 > >筆試面試題總結(二)---軟體開發

筆試面試題總結(二)---軟體開發

1.PreparedStatement與Statement

(1)PreparedStatement介面繼承Statement, PreparedStatement 例項包含已編譯的 SQL 語句,所以其執行速度要快於 Statement 物件。

(2)作為 Statement 的子類,PreparedStatement繼承了 Statement 的所有功能。三種方法execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要引數

(3)在JDBC應用中,如果你已經是稍有水平開發者,你就應該始終以PreparedStatement代替Statement.也就是說,在任何時候都不要使用Statement.

2.語句:char foo='中',是否正確?(假設原始檔以GB2312編碼儲存,並且以javac – encoding GB2312命令編譯)

這在java中是正確的,在C語言中是錯誤的,java的char型別佔兩個位元組,預設使用GBK編碼儲存。這種寫法是正確的,此外java還可以用中文做變數名。

3. java中的equal和==

 例項:
String str1 = new String("str");
String str2 = newString("str");
System.out.println("==比較 :"+ (str1 == str2));
System.out.println("equal比較:"+ str1.equals(str2));
String str3 ="str1";
String str4 ="str1";
System.out.println("==比較 :"+ (str3 == str4));
System.out.println("equal比較:"+ str3.equals(str4));

輸出結果:

false
equal比較:true
true
equal比較:true

根據列印的結果可以發現使用equal比較時無論是使用自動裝箱來例項化還是用new來例項化,返回的都true,而用==則不一樣了,自動裝箱來例項化的返回的是true,而用new來例項化的返回的確實false;先不急著解決為什麼,先來了解下equals和==的區別,到時候就可以知道答案了:

equals方法最初是在所有類的基類Object中進行定義的,原始碼是

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

可以看出這裡定義的equals與==是等效的,但上面的怎麼還會不一樣呢?

原因就是String類對equals進行了重寫:

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

這裡對equals重新需要注意五點:

 1)自反性:對任意引用值X,x.equals(x)的返回值一定為true. 
 2)對稱性:對於任何引用值x,y,當且僅當y.equals(x)返回值為true時,x.equals(y)的返回值一定為true; 
 3)傳遞性:如果x.equals(y)=true,y.equals(z)=true,則x.equals(z)=true 
 4)一致性:如果參與比較的物件沒任何改變,則物件比較的結果也不應該有任何改變 
 5)非空性:任何非空的引用值X,x.equals(null)的返回值一定為false 

經過重寫後就跟==有本質的區別了:

equal:是用來比較兩個物件內部的內容是否相等的,由於所有的類都是繼承自java.lang.Object類的,所以如果沒有對該方法進行覆蓋的話,呼叫的仍然是Object類中的方法,而Object中的equal方法返回的卻是==的判斷,因此,如果在沒有進行該方法的覆蓋後,呼叫該方法是沒有任何意義的。

==可用於基本型別和引用型別:當用於基本型別時候,是比較值是否相同;當用於引用型別的時候,是比較物件是否相同。

4. 關於抽象類與介面

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

介面(interface)可以說成是抽象類的一種特例,介面中的所有方法都必須是抽象的。介面中的方法定義預設為public abstract型別,介面中的成員變數型別預設為public static final。

下面比較一下兩者的語法區別:

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

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

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

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

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

6). 抽象類和介面中都可以包含靜態成員變數,抽象類中的靜態成員變數的訪問型別可以任意,但介面中定義的變數只能是public static final型別,並且預設即為public static final型別。

7). 一個類可以實現多個介面,但只能繼承一個抽象類。二者在應用方面也有一定的區別:介面更多的是在系統架構設計方法發揮作用,主要用於定義模組之間的通訊契約。而抽象類在程式碼實現方面發揮作用,可以實現程式碼的重用,例如,模板方法設計模式是抽象類的一個典型應用,假設某個專案的所有Servlet類都要用相同的方式進行許可權判斷、記錄訪問日誌和處理異常,那麼就可以定義一個抽象的基類,讓所有的Servlet都繼承這個抽象基類,在抽象基類的service方法中完成許可權判斷、記錄訪問日誌和處理異常的程式碼,在各個子類中只是完成各自的業務邏輯程式碼。

5. super和this的異同:

1)super(引數):呼叫基類中的某一個建構函式(應該為建構函式中的第一條語句) 

2)this(引數):呼叫本類中另一種形成的建構函式(應該為建構函式中的第一條語句)
3)super: 它引用當前物件的直接父類中的成員(用來訪問直接父類中被隱藏的父類中成員資料或函式,基類與派生類中有相同成員定義時如:super.變數名    super.成員函資料名(實參)

4)this:它代表當前物件名(在程式中易產生二義性之處,應使用this來指明當前物件;如果函式的形參與類中的成員資料同名,這時需用this來指明成員變數名)

5)呼叫super()必須寫在子類構造方法的第一行,否則編譯不通過。每個子類構造方法的第一條語句,都是隱含地呼叫super(),如果父類沒有這種形式的建構函式,那麼在編譯的時候就會報錯。

6)super()和this()類似,區別是,super()從子類中呼叫父類的構造方法,this()在同一類內呼叫其它方法。

7)super()和this()均需放在構造方法內第一行。

8)儘管可以用this呼叫一個構造器,但卻不能呼叫兩個。

9)this和super不能同時出現在一個建構函式裡面,因為this必然會呼叫其它的建構函式,其它的建構函式必然也會有super語句的存在,所以在同一個建構函式裡面有相同的語句,就失去了語句的意義,編譯器也不會通過。

10)this()和super()都指的是物件,所以,均不可以在static環境中使用。包括:static變數,static方法,static語句塊。

6. JAVA語言的下面幾種陣列複製方法中,哪個效率最高?

A.for迴圈逐一複製
B.System.arraycopy
C.System.copyof
D.使用clone方法

解析:

 A、for迴圈的話,很靈活,但是程式碼不夠簡潔.

 B、System.arraycopy()原始碼。可以看到是native方法:native關鍵字說明其修飾的方法是一個原生態方法,方法對應的實現不是在當前檔案,而是在用其他語言(如C和C++)實現的檔案中。 可以將native方法比作Java程式同C程式的介面。

public static native void arraycopy(Object src,int srcPos,Object dest,int destPos,int length);
  public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)       
 從指定源陣列中複製一個數組,複製從指定的位置開始,到目標陣列的指定位置結束。從 src 引用的源陣列到 dest 引用的目標陣列,陣列元件的一個子序列被複制下來。被複制的元件的編號等於 length 引數。源陣列中位置在 srcPos 到 srcPos+length-1 之間的元件被分別複製到目標陣列中的 destPos 到 destPos+length-1 位置。

 C、選項有誤,copyOf不是System的方法,而是Arrays的方法,下面是原始碼,可以看到本質上是呼叫的arraycopy方法。,那麼其效率必然是比不上 arraycopy的
public static int[] copyOf(int[] original, int newLength) {
   int[] copy = new int[newLength];
   System.arraycopy(original, 0, copy, 0,
   Math.min(original.length, newLength));
   return copy;
}

 D。clone的話,返回的是Object,需要強制轉換。 一般用clone效率是最差的,

注:arraycopy是個native方法,測試結果表明, 當陣列很小,但記憶體是呼叫次數多的話。使用它複製陣列並不比for迴圈手工複製陣列快。 但是如果是陣列比較大,那麼使用System.arraycopy會比較有優勢,因為其使用的是記憶體複製省去了大量的陣列定址訪問等時間。 

native方法: 
Java不是完美的,Java的不足除了體現在執行速度上要比傳統的C++慢許多之外,Java無法直接訪問到作業系統底層(如系統硬體等),為此Java使用native方法來擴充套件Java程式的功能。 
  可以將native方法比作Java程式同C程式的介面,其實現步驟:

       1)在Java中宣告native()方法,然後編譯; 

       2)用javah產生一個.h檔案;
  3)寫一個.cpp檔案實現native匯出方法,其中需要包含第二步產生的.h檔案(注意其中又包含了JDK帶的jni.h檔案);
  4)將第三步的.cpp檔案編譯成動態連結庫檔案; 
  5)在Java中用System.loadLibrary()方法載入第四步產生的動態連結庫檔案,這個native()方法就可以在Java中被訪問了。

7.   java中訪問控制符

通常我們可以顯示宣告的訪問控制符有三個:public, private 和 protected。另一種情況是:在成員變數或者方法宣告前面不加任何的訪問控制符。通過這種方式宣告的成員具有預設訪問控制(default access)屬性。具有預設訪問屬性的類成員的可訪問性被限制在包(package)內。

然後,關於四種訪問控制屬性的對比,可以直接引用 SO 上的一張非常清晰的對比圖表:

Java程式碼  收藏程式碼
  1. Modifier    | Class | Package | Subclass | World  
  2. ————————————+———————+—————————+——————————+———————  
  3. public      |  ✔    |    ✔    |    ✔     |   ✔  
  4. ————————————+———————+—————————+——————————+———————  
  5. protected   |  ✔    |    ✔    |    ✔     |   ✘  
  6. ————————————+———————+—————————+——————————+———————  
  7. no modifier |  ✔    |    ✔    |    ✘     |   ✘  
  8. ————————————+———————+—————————+——————————+———————  
  9. private     |  ✔    |    ✘    |    ✘     |   ✘  

這張圖表可以這樣解讀(以 protected 為例):

proctected 訪問控制符所修飾的類成員在宣告該成員的類、類所在的包中的所有其他類以及該類的所有子類中是可見的,而對除此之外的其他類是不可見的。

需要注意的一點是,預設訪問控制的類成員只是包內可見,如果其子類也同一個包內,那麼也是子類可見的。但是,由於對包外宣告的子類是不可見的,所以有上圖示中的第4行第4列的✘

另外,值得領會的另一個問題是:在實際程式設計中應該如何選擇使用哪一種訪問控制符?總的來說,訪問控制符設計的初衷是針對 OO 中的封裝性 - 應該儘量將資訊隱藏。類成員的訪問許可權放的越開,日後對於該類成員的任何改變就越要謹慎,因為這個類成員可能被很多人使用。如何選擇,應該充分考慮類成員的最終用途。

一個值得注意的Java和C++不同之處,同一個Package中,一個class的protected成員函式,可以被同一個package中的其他類訪問到。C++中,一個類的protected成員函式只能被自己和自己的子類訪問到,其他類是訪問不到的。


參考資源:

[5].牛客網