115 司法特考三等 檢察事務官類科電子資訊組 程式語言 考古題詳解

115 年・司法特考・三等・檢察事務官類科電子資訊組
試題代碼 程式語言

第 一 題5 分

請根據圖 1-1 的 Java 程式碼回答問題。

interface PaymentMethod { boolean pay(int amount); }

class Card implements PaymentMethod { private int limit = 1000;

public boolean pay(int amount) {
    if (amount > limit) {
        return false;
    }
    limit -= amount;
    return true;
}

}

class Cash implements PaymentMethod { public boolean pay(int amount) { return true; } }

class Order { private int total;

public Order(int total) {
    this.total = total;
}

public boolean checkout(PaymentMethod method) {
    return method.pay(total);
}

}

圖 1-1

(一) 在 Order 類別中,checkout() 方法的參數型別宣告為 PaymentMethod 介面。請說明為何這樣的設計能讓該方法同時接收 Card 與 Cash 的物件作為參數。(5 分)

(二) 此設計運用了物件導向程式設計的什麼特性?(5 分)

(三) 假設在某類別的 main() 方法中依序執行圖 1-2 的程式碼,請寫出其執行結果。(5 分)

PaymentMethod card = new Card(); PaymentMethod cash = new Cash(); Order order = new Order(600);

System.out.println(order.checkout(card)); System.out.println(order.checkout(cash)); System.out.println(order.checkout(card));

圖 1-2

(四) 此系統欲擴充退款功能,但並非所有付款方式都支援退款,因此新定義了一個 Refundable 介面:

interface Refundable { boolean refund(int amount); }

請在不更動既有類別架構的前提下,完成下列 tryRefund() 方法,實作邏輯如下。(10 分)

  1. 若傳入的 method 物件,其執行時期的類別亦實作 Refundable 介面,則呼叫其 refund(amount) 方法。
  2. 若傳入的 method 物件未實作 Refundable 介面,即不支援退款,則回傳 false。

boolean tryRefund(PaymentMethod method, int amount) { // 請在此處填入您的實作程式碼 }

🖼️ 本題原卷含圖表。基於試題來源之版權考量,本站不轉載原卷影像; 題目文字已完整轉錄,圖表請自行參閱考選部公告之試題原檔。

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查 Java 的:

  • 介面(interface)與實作類別
  • 子型別多型(polymorphism)
  • 介面型別參數
  • 執行時期型別判斷(instanceof)
  • 型別轉換(casting)

Card 與 Cash 都實作 PaymentMethod,因此兩者都是 PaymentMethod 的子型別。

(一) 為何可同時接收 Card 與 Cash

Card 宣告為:

class Card implements PaymentMethod

Cash 宣告為:

class Cash implements PaymentMethod

因此,Card 與 Cash 都必須提供介面所規定的:

boolean pay(int amount)

在 Java 中,實作介面的類別物件可以向上轉型為介面型別。因此下列指定皆合法:

PaymentMethod card = new Card;
PaymentMethod cash = new Cash;

checkout 的參數雖然宣告為 PaymentMethod,但實際傳入的物件可以是任何實作該介面的類別,例如:

order.checkout(new Card);
order.checkout(new Cash);

checkout 只需要依賴 PaymentMethod 所提供的 pay 方法,不必知道實際物件是 Card 還是 Cash,因此提高程式的彈性與可擴充性。

(二) 使用的物件導向特性

本設計主要運用了「多型(Polymorphism)」。

checkout 的參數型別是 PaymentMethod,但實際執行時可以傳入不同的實作物件:

  • 傳入 Card 時,執行 Card 的 pay。
  • 傳入 Cash 時,執行 Cash 的 pay。

相同的:

method.pay(total)

會依據執行時期物件的實際類別,呼叫不同的實作方法,這就是執行時期多型。

同時,此設計也符合「面向介面設計」的概念,使 Order 不需要依賴特定付款類別。

(三) 執行結果

初始建立:

PaymentMethod card = new Card;

Card 的初始額度為:

limit=1000limit = 1000

訂單金額為:

Order order = new Order(600);

第一次付款

order.checkout(card)

執行 Card.pay(600):

600≤1000600 \leq 1000

付款成功,並更新額度:

limit=1000−600=400limit = 1000 - 600 = 400

輸出:

true
🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 二 題10 分

請回答以下關於 Java 程式語言例外處理(Exception Handling)的問題。

(一) 請說明 Java 語言中 checked exception 與 unchecked exception 的差異,並各舉一個 Java 內建的例外類別作為範例。(10 分)

(二) 根據圖 2-1 所示的 Java 程式碼,寫出執行 main() 方法後的完整輸出結果。(5 分)

public class Test { static int parse(String text) { try { return Integer.parseInt(text); } catch (NumberFormatException e) { return -1; } finally { System.out.print("F"); } }

public static void main(String[] args) {
    System.out.println(parse("12"));
    System.out.println(parse("abc"));
}

}

圖 2-1

(三) 假設有一個類別 Calculator 包含圖 2-2 所示的靜態方法,請撰寫一個 JUnit 5 測試類別,驗證下列三項行為。(10 分)

  1. divide(10, 2) 應得到 55。
  2. divide(10, 0) 應拋出 IllegalArgumentException。
  3. 例外訊息應為 "division by zero"。

public static int divide(int a, int b) { if (b == 0) { throw new IllegalArgumentException("division by zero"); } return a / b; }

圖 2-2

🖼️ 本題原卷含圖表。基於試題來源之版權考量,本站不轉載原卷影像; 題目文字已完整轉錄,圖表請自行參閱考選部公告之試題原檔。

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查三個 Java 例外處理重點:

  1. checked exception 與 unchecked exception 的差異。
  2. try-catch-finally 的執行順序,尤其是 finally 一定會執行。
  3. JUnit 5 對正常回傳值、例外類型與例外訊息的測試方法。

(一)Checked Exception 與 Unchecked Exception

1. Checked exception

checked exception 是編譯器會檢查的例外,程式必須:

  • 使用 try-catch 捕捉;或
  • 在方法宣告中使用 throws 向外拋出。

否則程式無法通過編譯。

常見類別為 IOException,例如檔案讀取失敗時可能發生:

public void readFile throws IOException {
 // 檔案讀取操作
}

2. Unchecked exception

unchecked exception 不會被編譯器強制要求捕捉或宣告,通常是程式執行期間因邏輯錯誤或不合法操作所產生。

其主要基底類別為 RuntimeException,例如:

  • NullPointerException
  • ArithmeticException
  • NumberFormatException
  • IllegalArgumentException

本題程式中的 NumberFormatException 即屬於 unchecked exception。

3. 差異整理

比較項目Checked exceptionUnchecked exception
編譯器是否強制處理是否
是否須 catch 或 throws必須不必
常見基底類別Exception 的非 RuntimeException 子類別RuntimeException
範例IOExceptionNullPointerException

(二)程式輸出結果

解題方法

執行:

parse("12")

時:

  1. Integer.parseInt("12") 成功,回傳 12。
  2. 離開 try 前,仍會執行 finally。
  3. finally 先輸出字元 F。
  4. parse 回傳 12 後,外層的 System.out.println 再輸出 12 並換行。

因此第一行為:

F12

執行:

parse("abc")

時:

  1. Integer.parseInt("abc") 產生 NumberFormatException。
  2. 由 catch 捕捉,回傳 -1。
  3. 回傳前仍會執行 finally,先輸出 F。
  4. 外層 println 再輸出 -1 並換行。

因此第二行為:

F-1

解題技巧

遇到下列結構:

🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 三 題5 分

已知二元搜尋樹的節點定義如圖 3-1,請根據圖 3-2 的二元搜尋樹回答問題。

typedef struct TNode { int key; struct TNode *left; struct TNode *right; } TNode;

圖 3-1:節點定義

圖 3-2:二元搜尋樹(原卷包含樹狀圖)

(一) 請分別說明二元樹的遞迴走訪函式中,下列兩種情況的目的與執行行為。(5 分)

  1. 基底情況(Base case)。
  2. 遞迴情況(Recursive case)。

(二) 執行圖 3-3 的函式,root 為圖 3-2 二元搜尋樹根節點,low = 5,high = 10。

  1. 其最終回傳值為何?(5 分)
  2. 請依此函式實際遞迴走訪的先後順序,列出 current = 1 節點的 key 值。(5 分)

int countRange(TNode *root, int low, int high) { if (root == NULL) { return 0; }

int current = (root->key >= low && root->key <= high) ? 1 : 0;

return current
    + countRange(root->left, low, high)
    + countRange(root->right, low, high);

}

圖 3-3

(三) 圖 3-4 的函式可以用來在二元搜尋樹中搜尋指定值 target。

  1. 請將圖 3-5 的三行指令分別填入圖 3-4 函式 A、B、C 的空格中,每個選項限填一次且不可重複填用。(5 分)
  2. 根據圖 3-2 的二元搜尋樹,若執行 search(root, 7),請問此函式最後回傳的指標所指向的節點,其 key 值為何?(5 分)

TNode *search(TNode *root, int target) { while (root != NULL) { if (A) { return root; }

    if (B) {
        root = root->left;
    } else {
        root = C;
    }
}

return NULL;

}

圖 3-4

圖 3-5 選項:

  • root->right
  • root->key == target
  • target < root->key
🖼️ 本題原卷含圖表。基於試題來源之版權考量,本站不轉載原卷影像; 題目文字已完整轉錄,圖表請自行參閱考選部公告之試題原檔。

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查:

  • 二元樹遞迴走訪中的基底情況與遞迴情況。
  • 二元搜尋樹節點搜尋。
  • 遞迴計數與條件判斷。
  • 函式呼叫順序。

圖 3-2 的二元搜尋樹結構為:

  • 根節點:1010
  • 1010 的左子節點:55
  • 1010 的右子節點:1212
  • 55 的左子節點:44
  • 55 的右子節點:77

(一)二元樹遞迴走訪

1. 基底情況(Base case)

基底情況是遞迴函式停止遞迴的條件,用來處理最簡單或已經沒有子樹的情形。

在二元樹中,通常判斷:

root==NULLroot == NULL

代表目前指標沒有指向任何節點,也就是已經走到空子樹。此時函式直接回傳結果,不再繼續呼叫自己,以避免無限遞迴。

例如:

if (root == NULL)
 return 0;

2. 遞迴情況(Recursive case)

遞迴情況是處理目前節點,並繼續對其左子樹與右子樹呼叫相同函式。

二元樹通常分成三個部分:

  1. 處理目前節點。
  2. 遞迴處理左子樹。
  3. 遞迴處理右子樹。

例如本題的 countRange:

return current
 + countRange(root->left, low, high)
 + countRange(root->right, low, high);

這會將目前節點、左子樹及右子樹的結果加總。


(二)countRange 函式

1. 最終回傳值

條件為:

5≤key≤105 \leq key \leq 10

各節點判斷如下:

節點 key是否落在 [5,10][5,10]current
1010是11
55是11
1212否00
44否00
77是11

因此:

1+1+0+0+1=31+1+0+0+1=3

2. current = 1 的節點走訪順序

函式先判斷目前節點的 current,再遞迴走訪左子樹,最後走訪右子樹,因此節點判斷順序為:

10→5→4→7→1210 \rightarrow 5 \rightarrow 4 \rightarrow 7 \rightarrow 12

其中 current = 1 的節點依序為:

10、5、7\boxed{10、5、7}

(三)二元搜尋樹搜尋函式

1. A、B、C 填空

正確填法為:

🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 四 題5 分

某網路書店之網站提供下列 API,網站系統可依客戶端需求回傳 JSON 或 XML 資料。

  • GET /api/books:查詢所有書籍。
  • GET /api/books/{id}:查詢指定書籍。
  • POST /api/books:新增書籍。
  • DELETE /api/books/{id}:刪除指定書籍。

(一) 請說明 HTTP 的無狀態性(Stateless)是什麼意思。(5 分)

(二) 若此網路書店需要辨識已登入的使用者,伺服器端可以採用哪一種機制來保存或傳遞登入狀態?請舉出一種說明即可。(5 分)

(三) 假設伺服器收到下列請求:

GET /api/books?discount=20

伺服器執行圖 4 的 Python 程式碼,且所有數值,包含計算後的結果,在轉為 JSON 輸出時,皆會強制保留一位小數,即浮點數格式。請寫出最後一行指令在標準 JSON 格式下所輸出的單行完整 JSON 字串結果。(5 分)

books = [ {"id": 1, "price": 500}, {"id": 2, "price": 800} ]

discount = float(request.query["discount"])

for each book in books: book["salePrice"] = book["price"] * (100 - discount) / 100

print(output_as_json(books))

圖 4

(四) 系統後台使用下列 Python 程式碼來實作 GET /api/books/{id},即查詢指定書籍的功能:

book_id = request.query["id"] sql = "SELECT title, price FROM Book WHERE id = " + book_id result = database.execute(sql)

  1. 請說明此程式碼在網頁安全上可能遭受的惡意攻擊類型與原因。(5 分)
  2. 請使用參數化查詢(Parameterized Query)修正上述程式碼,寫出修正後的完整程式片段,以有效防範該攻擊。(5 分)
🖼️ 本題原卷含圖表。基於試題來源之版權考量,本站不轉載原卷影像; 題目文字已完整轉錄,圖表請自行參閱考選部公告之試題原檔。

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查:

  1. HTTP 的無狀態性。
  2. 登入狀態的保存機制。
  3. JSON 數值格式與折扣計算。
  4. SQL Injection 與參數化查詢。

解題方法

(一)HTTP 的無狀態性

HTTP 的無狀態性是指:伺服器處理每一個 HTTP 請求時,彼此獨立,不會自動記住前一次請求的使用者狀態。

因此,每次請求都必須自行攜帶必要資訊,例如驗證用的 Cookie、Session ID 或 Token。伺服器不會因為先前已處理過登入請求,就自動知道後續請求是哪一位使用者。

無狀態性不代表伺服器不能保存資料,而是指 HTTP 通訊協定本身不會自動維持請求之間的連續狀態。

(二)保存或傳遞登入狀態的機制

可採用 Cookie 搭配 Session 機制:

  1. 使用者登入成功後,伺服器建立 Session,並產生唯一的 Session ID。
  2. 伺服器將 Session ID 放入 Set-Cookie 回應標頭,傳送給瀏覽器。
  3. 瀏覽器之後每次請求,自動將 Cookie 送回伺服器。
  4. 伺服器依 Session ID 找到對應的登入使用者資料,完成身分辨識。

此方式是在無狀態的 HTTP 上,額外建立登入狀態管理機制。

(三)JSON 輸出結果

請求為:

GET /api/books?discount=20

因此:

discount=20.0discount = 20.0

售價計算公式為:

salePrice=price×100−discount100salePrice = price \times \frac{100-discount}{100}

第一本書:

500.0×100.0−20.0100.0=500.0×0.8=400.0500.0 \times \frac{100.0-20.0}{100.0} =500.0\times0.8 =400.0

第二本書:

800.0×100.0−20.0100.0=800.0×0.8=640.0800.0 \times \frac{100.0-20.0}{100.0} =800.0\times0.8 =640.0

題目指定所有數值均以一位小數輸出,因此 id 與 price 也須表示成浮點數格式。

(四)1. 網頁安全問題

此程式碼可能遭受 SQL Injection(SQL 注入攻擊)。

原因是程式直接將使用者輸入的 book_id 串接到 SQL 指令中:

sql = "SELECT title, price FROM Book WHERE id = " + book_id
🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

其他考古題