An original Thinka practice paper modelled on the structure and difficulty of the Jun 2025 CCEA AS Level Software Systems Development CL4 paper. Not affiliated with or reproduced from CCEA.
Unit AS 1 Examination Paper
Answer all seven questions in the spaces provided. Candidates may write solutions in C# or Java.
7 题目 · 100 分
题目 1 · Technical Definitions
6 分
With regard to object-oriented programming, provide definitions of each of these terms: (i) Class [2] (ii) Object [2] (iii) Constructor [2]
查看答案详解收起答案详解
解题
(i) A class is a blueprint, or template, that defines the fields (attributes) and methods (behaviour) that objects created from it will have. (ii) An object is a specific instance of a class — an individual occurrence created from the class's blueprint, with its own particular values stored in the fields defined by the class. (iii) A constructor is a special method, sharing the same name as its class, that is automatically called whenever a new object of that class is created; it is used to initialise the object's fields, often using values passed in as parameters. Final answer: (i) a class is a blueprint defining fields/methods; (ii) an object is an instance created from a class; (iii) a constructor is the special method that initialises a new object's fields when it is created.
评分标准
(i) Correct definition of class (blueprint/template defining fields and methods) [2]. (ii) Correct definition of object (an instance of a class, with its own field values) [2]. (iii) Correct definition of constructor (special method, same name as class, called on object creation, initialises fields) [2].
题目 2 · Algorithm & Array Manipulation
17 分
A library stores the number of times each of its 10 books has been borrowed in an integer array called borrowCounts, indexed 0 to 9. (a) Write the code to declare and create the array borrowCounts, able to hold 10 integers. [2] (b) Write a method called totalBorrows() that takes the array borrowCounts as a parameter and returns the total number of times all books have been borrowed (i.e. the sum of all the values in the array). [6] (c) Write a method called mostBorrowed() that takes the array borrowCounts as a parameter and returns the INDEX of the book with the highest number of borrows. [9]
查看答案详解收起答案详解
解题
(a) The array is declared and created as: int[] borrowCounts = new int[10]; (identical in C# and Java). (b) totalBorrows() loops through every element of the array, adding each value to a running total, then returns the total: C#: public int totalBorrows(int[] borrowCounts) { int total = 0; for (int i = 0; i < borrowCounts.Length; i++) { total = total + borrowCounts[i]; } return total; } Java: public int totalBorrows(int[] borrowCounts) { int total = 0; for (int i = 0; i < borrowCounts.length; i++) { total = total + borrowCounts[i]; } return total; } (c) mostBorrowed() keeps track of the index of the largest value found so far (starting with index 0), updating it whenever a larger value is found later in the array, then returns that index: C#: public int mostBorrowed(int[] borrowCounts) { int maxIndex = 0; for (int i = 1; i < borrowCounts.Length; i++) { if (borrowCounts[i] > borrowCounts[maxIndex]) { maxIndex = i; } } return maxIndex; } Java: public int mostBorrowed(int[] borrowCounts) { int maxIndex = 0; for (int i = 1; i < borrowCounts.length; i++) { if (borrowCounts[i] > borrowCounts[maxIndex]) { maxIndex = i; } } return maxIndex; } Traced check: for borrowCounts = {3,7,2,9,5,1,9,0,4,6}, totalBorrows returns 46 (the sum of all ten values) and mostBorrowed returns 3 (the first index holding the highest value, 9). Final answer: (a) int[] borrowCounts = new int[10];; (b) a loop summing every element, returning the total; (c) a loop tracking and returning the index of the largest value found (initialised to index 0, updated whenever a strictly larger value is found).
评分标准
(a) Correct array declaration and creation for 10 integers [2]. (b) Correct method header with int[] parameter and int return type [1]; correct initialisation of a running total to 0 [1]; correct loop structure iterating over the full array [2]; correct accumulation of each element into the total [1]; correct return statement [1] (max 6). (c) Correct method header with int[] parameter and int return type [1]; correct initialisation of maxIndex to 0 [1]; correct loop structure iterating over the array (from index 1 onward, or 0 with equivalent correct logic) [2]; correct comparison to find a larger value [2]; correct update of maxIndex [2]; correct return statement [1] (max 9).
题目 3 · Class Construction & Array Search
20 分
A library wants to represent each book using a class called Book, with the following private fields: title (a string), author (a string), and isbn (a string). (a) Complete the class definition for Book with: (i) A parameterised constructor that sets all three fields. [3] (ii) GET methods for title, author and isbn. [3] (b) The library stores its books in an array called catalogue, of type Book, containing 50 books. Write a method called findByIsbn() that takes the array catalogue and a string isbn as parameters, and returns the Book object in the array whose isbn field matches the given isbn, or returns null if no match is found. [8] (c) Explain why using an array is not the most efficient way to search for a book by ISBN once the catalogue becomes very large, and suggest one alternative approach that could improve search efficiency. [6]
查看答案详解收起答案详解
解题
(a)(i)–(ii) Class definition: C#: public class Book { private string title; private string author; private string isbn;
public String getTitle() { return title; } public String getAuthor() { return author; } public String getIsbn() { return isbn; } } (b) findByIsbn() loops through the catalogue array, comparing each Book's isbn field against the given isbn, and returns the matching Book as soon as it is found; if the loop finishes without a match, it returns null: C#: public Book findByIsbn(Book[] catalogue, string isbn) { for (int i = 0; i < catalogue.Length; i++) { if (catalogue[i].getIsbn() == isbn) { return catalogue[i]; } } return null; } Java: public Book findByIsbn(Book[] catalogue, String isbn) { for (int i = 0; i < catalogue.length; i++) { if (catalogue[i].getIsbn().equals(isbn)) { return catalogue[i]; } } return null; } (Note: Java string comparison uses .equals(), not ==, since == compares object references in Java; C# overloads == for strings to compare their values.) (c) This method performs a linear search, checking the array one element at a time from the start until a match is found or the end of the array is reached; in the worst case (the ISBN is not present, or is near the end), every element must be checked. As the catalogue grows very large, the number of comparisons needed grows in proportion to its size, making the search progressively slower. An alternative approach that would improve efficiency is to store the books in a hash table (dictionary) keyed on isbn, giving near-instant lookup regardless of size, or to keep the array sorted by isbn and use a binary search algorithm, which is much faster than linear search for a large, sorted collection since it repeatedly halves the portion of the array still to be searched. Final answer: (a) constructor sets the three fields; get methods each return one field; (b) a linear-search loop comparing isbn values, returning the matching Book or null; (c) linear search may need to check every element as the catalogue grows, so a hash table/dictionary (or a sorted array with binary search) would search much more efficiently at scale.
评分标准
(a)(i) Correct constructor header with three string parameters [1]; correct assignment of all three fields [2] (max 3). (a)(ii) Each of the three get methods correctly returning its field [1 mark each, max 3]. (b) Correct method header with Book[] and string parameters, returning Book [1]; correct loop over the full array [2]; correct language-appropriate comparison of isbn (.equals() in Java, or valid == in C#) [2]; correct return of the matching Book [2]; correct return of null if no match is found [1] (max 8). (c) Correct explanation that linear search may need to check every element, and this gets slower as the array grows [3]; valid, correctly explained alternative (hash table/dictionary, or sorted array with binary search) [3] (max 6).
(a) Complete the following statements by inserting the appropriate word from the list below. Each word may be used once, more than once, or not at all. [ try, catch, finally, throw, exception, block ] (i) A run-time error that disrupts the normal flow of a program is called an __________. [1] (ii) Code that might cause an error is placed inside a __________ block. [1] (iii) If an error occurs, the program jumps to the matching __________ block, where the error can be handled. [1] (iv) The __________ block, if present, contains code that runs whether or not an error occurred. [1] (b) Write a method called safeDivide() that takes two integer parameters, numerator and denominator, and returns the result of dividing numerator by denominator as a double value. The method should use try/catch to handle the situation where denominator is zero (which would otherwise cause a division-by-zero run-time error): if this occurs, the method should catch the error and return 0.0 instead of allowing the program to crash. [13]
查看答案详解收起答案详解
解题
(a)(i) A run-time error that disrupts the normal flow of a program is called an exception. (ii) Code that might cause an error is placed inside a try block. (iii) If an error occurs, the program jumps to the matching catch block, where the error can be handled. (iv) The finally block, if present, contains code that runs whether or not an error occurred. (b) The method performs the (integer) division inside a try block; because both numerator and denominator are declared as int, dividing by a denominator of zero causes a run-time exception (DivideByZeroException in C#, ArithmeticException in Java), which is caught in the matching catch block, where 0.0 is returned instead of allowing the program to crash: C#: public double safeDivide(int numerator, int denominator) { try { int result = numerator / denominator; return (double)result; } catch (DivideByZeroException e) { return 0.0; } } Java: public double safeDivide(int numerator, int denominator) { try { int result = numerator / denominator; return (double)result; } catch (ArithmeticException e) { return 0.0; } } Final answer: (a) exception, try, catch, finally; (b) the integer division numerator / denominator is attempted inside a try block; if denominator is 0 this throws a division/arithmetic exception, which is caught and handled by returning 0.0 instead of crashing the program.
评分标准
(a) Each correct word in the correct blank [1 mark each, max 4]: (i) exception, (ii) try, (iii) catch, (iv) finally. (b) Correct method header with two int parameters and a double return type [2]; correct use of a try block containing the division [2]; correct integer division of numerator by denominator [2]; correct use of a matching catch block naming the correct/an acceptable exception type [3]; correct return of 0.0 within the catch block [2]; correct return of the division result (cast to double) when no exception occurs [2] (max 13).
题目 5 · Serialization Theory & Implementation
5 分
(a) Explain the purpose of serialization when working with objects in a program. [2] (b) State the mechanism a class must use in Java (or in C#) in order for its objects to be serializable, and explain why this is necessary. [3]
查看答案详解收起答案详解
解题
(a) Serialization is the process of converting an object, along with its current field values, into a format (such as a byte stream or file) that can be saved or transmitted, and later reconstructed (deserialized) back into an equivalent object; this allows an object's data to persist beyond the lifetime of the running program, for example being saved to a file and reloaded the next time the program runs. (b) In Java, a class must implement the Serializable interface (java.io.Serializable), which is a 'marker' interface with no methods that must be written; in C#, the class must instead be marked with the [Serializable] attribute above its class definition. This is necessary because it explicitly signals to the runtime/serialization mechanism that a class's objects are intended, and safe, to be converted into a storable format — not every object can safely be serialized (for example, one holding an open file handle or network connection), so the language requires this explicit declaration before allowing it. Final answer: (a) serialization converts an object into a storable format that can later be reconstructed, letting its data persist beyond the running program; (b) in Java the class implements Serializable, in C# it is marked with the [Serializable] attribute, which is required to explicitly confirm the class's objects can safely be converted to that storable format.
评分标准
(a) Correct explanation of serialization (converting an object to a storable format, later reconstructable) [1]; correct reference to allowing data to persist beyond the running program [1]. (b) Correct mechanism named for Java (implements Serializable) or C# ([Serializable] attribute) [2]; valid explanation of why this is necessary [1].
A library extends its system to catalogue different types of item. It uses a base class called LibraryItem with the following protected fields: title (a string) and itemId (a string), and a method getDetails() that returns the string: title + " (" + itemId + ")", for example 'Frankenstein (BK001)'. Two classes, Book and DVD, inherit from LibraryItem. Book adds a private field author (a string). DVD adds a private field runtimeMinutes (an integer). (a) Write the class definition for LibraryItem, including its constructor (which sets title and itemId) and the getDetails() method described above. [6] (b) Write the class definition for Book, which inherits from LibraryItem. Book should: (i) have a constructor that accepts title, itemId and author, and calls the base class constructor to set title and itemId; [4] (ii) override getDetails() so that it returns the base class's details PLUS the author's name in square brackets, e.g. 'Frankenstein (BK001) [Mary Shelley]'. [6] (c) Write the class definition for DVD, which inherits from LibraryItem. DVD should: (i) have a constructor that accepts title, itemId and runtimeMinutes, and calls the base class constructor to set title and itemId; [3] (ii) override getDetails() so that it returns the base class's details PLUS the runtime in minutes in square brackets, e.g. 'Inception (DV001) [148 mins]'. [6]
查看答案详解收起答案详解
解题
C#: public class LibraryItem { protected string title; protected string itemId;
Traced check: new Book("Frankenstein","BK001","Mary Shelley").getDetails() calls the base getDetails(), giving "Frankenstein (BK001)", then appends " [Mary Shelley]", giving "Frankenstein (BK001) [Mary Shelley]" — matching the example exactly. Similarly, new DVD("Inception","DV001",148).getDetails() gives "Inception (DV001)" then appends " [148 mins]", giving "Inception (DV001) [148 mins]" — matching the example exactly. Final answer: LibraryItem defines the shared title/itemId fields and a base getDetails(); Book and DVD each inherit from it, pass title/itemId to the base constructor, and override getDetails() to call the base version and append their own extra field, exactly reproducing both example outputs.
评分标准
(a) Correct fields declared as protected [1]; correct constructor header and correct assignment of both fields [2]; correct getDetails() method, correctly marked as overridable (virtual in C#; Java methods are overridable by default) and returning the correct concatenated string [3] (max 6). (b)(i) Correct constructor header with three parameters [1]; correct call to the base class constructor passing title and itemId [2]; correct assignment of author [1] (max 4). (b)(ii) Correct override syntax (override in C#; @Override/re-declared method in Java) [1]; correct call to the base class's getDetails() [3]; correct concatenation of the author in square brackets in the specified format [2] (max 6). (c)(i) Correct constructor header with three parameters (including an int for runtimeMinutes) [1]; correct call to the base class constructor [1]; correct assignment of runtimeMinutes [1] (max 3). (c)(ii) Correct override syntax [1]; correct call to the base class's getDetails() [3]; correct concatenation of the runtime in square brackets in the specified format [2] (max 6).
题目 7 · Polymorphic Array Processing & Reporting
10 分
Using the LibraryItem, Book and DVD classes from Question 6, write a method called printCatalogue() that takes an array of LibraryItem (which may contain a mixture of Book and DVD objects) as a parameter, and prints the result of calling getDetails() on each item in the array, one item per line. [10]
查看答案详解收起答案详解
解题
C#: public void printCatalogue(LibraryItem[] items) { for (int i = 0; i < items.Length; i++) { Console.WriteLine(items[i].getDetails()); } }
Java: public void printCatalogue(LibraryItem[] items) { for (int i = 0; i < items.length; i++) { System.out.println(items[i].getDetails()); } }
Although the array is declared to hold the base type LibraryItem, each element may actually be a Book or a DVD object at run time; because getDetails() is overridden in both Book and DVD, calling items[i].getDetails() automatically runs the correct, more specific version of the method for whatever type of object is actually stored at that position in the array (a Book's version if it is a Book, a DVD's version if it is a DVD), without printCatalogue() needing to know or check which specific type each item is. This is an example of polymorphism. Final answer: a method with a LibraryItem[] parameter that loops through the array and prints items[i].getDetails() for each element — polymorphism ensures the correct overridden Book or DVD version of getDetails() runs automatically for each item, regardless of the array's declared base type.
评分标准
Correct method header with a LibraryItem[] parameter and void return type [2]; correct loop structure iterating over the full array [3]; correct call to getDetails() on each array element [2]; correct output statement printing the result, one item per line [2]; explanation/evidence (through correct code) that the polymorphic call correctly resolves to each object's own overridden version [1] (max 10).