Method Signatures — Homework (1.9)
AP CSA 1.9 — Method Signatures: Homework
Complete all parts. Submit this executed notebook on GitHub Pages and answer MCQs on the Google Form.
Popcorn Hack: Write and test max overloads
Instructions: Write two overloaded methods named max that each return the larger of two numbers.
One should accept two int values.
The other should accept two double values.
Then, test both versions in the main method.
public class PopcornMax {
// TODO: write int version of max
// TODO: write double version of max
public static void main(String[] args) {
System.out.println(max(3, 9)); // expected: 9
System.out.println(max(-2, -7)); // expected: -2
System.out.println(max(3.5, 2.9)); // expected: 3.5
System.out.println(max(2, 2.0)); // should call double version → 2.0
}
}
public class PopcornMax {
// TODO: write int version of max
public static int max(int a, int b) {
return (a > b) ? a : b;
}
// TODO: write double version of max
public static double max(double a, double b) {
return (a > b) ? a : b;
}
public static void main(String[] args) {
System.out.println(max(3, 9)); // expected: 9
System.out.println(max(-2, -7)); // expected: -2
System.out.println(max(3.5, 2.9)); // expected: 3.5
System.out.println(max(2, 2.0)); // should call double version → 2.0
}
}
PopcornMax.main(null);
9
-2
3.5
2.0
Popcorn Hack: Overload print for int and String
Instructions:Implement two overloaded print methods — one that accepts an int and prints int: and another that accepts String and prints str:. Test with mixed types.
public class PopcornPrint {
// TODO: write print(int n)
// TODO: write print(String s)
public static void main(String[] args) {
print(42); // expected: int:42
print("hello"); // expected: str:hello
print('A' + "!"); // char + String → String → expected: str:A!
}
}
public class PopcornPrint {
// TODO: write print(int n)
public static void print(int n) {
System.out.println("int:" + n);
}
// TODO: write print(String s)
public static void print(String s) {
System.out.println("str:" + s);
}
public static void main(String[] args) {
print(42); // expected: int:42
print("hello"); // expected: str:hello
print('A' + "!"); // char + String → String → expected: str:A!
}
}
PopcornPrint.main(null);
int:42
str:hello
str:A!
MCQs with Explanations
1) Which pair is a valid overload?
- A)
int f(int a)andint f(int x)[INCORRECT] - B)
int f(int a)anddouble f(int a)[INCORRECT] - C)
int f(int a)anddouble f(double a)[CORRECT] - D)
int f(int a, int b)andint f(int a, int b)[INCORRECT]
Explanation: Answer is C. Valid overloading requires different parameter lists (either different types or number of parameters). Option C has different parameter types (int vs double). A is invalid because parameter names don’t matter. B is invalid because return type alone doesn’t distinguish methods. D is invalid because it’s exactly the same method.
2) Which is the AP CSA notion of a method signature?
- A)
public static int max(int a, int b)[INCORRECT] - B)
max(int, int)[CORRECT] - C)
max(int a, int b) throws Exception[INCORRECT] - D)
max(int, double)[INCORRECT]
Explanation: Answer is B. In AP CSA, a method signature includes just the method name and parameter types, not the modifiers, return type, parameter names, or exceptions. max(int, int) is the correct format.
3) With the overloads void p(int x) and void p(double x), what prints?
p(5);
p(5.0);
- A)
int,double[CORRECT] - B)
double,double[INCORRECT] - C)
int,int[INCORRECT] - D) Compile error [INCORRECT]
Explanation: Answer is A. Java uses the most specific matching type. 5 is an int, so it calls p(int). 5.0 is a double, so it calls p(double). No ambiguity here.
4) Which call is ambiguous with only these two methods?
void h(long x) {}
void h(float x) {}
- A)
h(5)[CORRECT] - B)
h(5.0)[INCORRECT] - C)
h(5f)[INCORRECT] - D) None are ambiguous [INCORRECT]
Explanation: Answer is A. When calling h(5), Java can’t decide whether to widen the int to long or float - both conversions are equally valid. 5.0 is a double and prefers float. 5f is explicitly a float. The ambiguity only happens with int literal 5.
5) Which statement is TRUE?
- A) Parameter names affect the method signature. [INCORRECT]
- B) Return type affects the method signature. [INCORRECT]
- C) Access modifiers affect the method signature. [INCORRECT]
- D) Overloading requires different parameter lists. [CORRECT]
Explanation: Answer is D. Method signatures in Java are only affected by:
- Method name
- Parameter types and order
- Number of parameters
Parameter names, return type, access modifiers, and exceptions are NOT part of the signature.
Short answer
Question 1: Why can’t int sum(int a, int b) and double sum(int a, int b) both exist?
These methods cannot coexist because they have the same method signature sum(int, int). In Java, method overloading is determined only by the method name and parameter list (types and order), not by return type. When the compiler sees sum(5, 3), it wouldn’t know which method to call since both methods accept the same parameter types.
Question 2: Distinguish parameters vs arguments in one sentence:
Parameters are the variables declared in the method definition while arguments are the actual values passed to the method when it is called (e.g., in max(x, y), x and y are arguments that get assigned to the parameters declared in the method header).
Coding Tasks
1. Three overloads of abs:
public static int abs(int x) {
return (x < 0) ? -x : x;
}
public static double abs(double x) {
return (x < 0) ? -x : x;
}
public static long abs(long x) {
return (x < 0) ? -x : x;
}
2. Two overloads of concat:
public static String concat(String a, String b) {
return a + b;
}
public static String concat(String a, int n) {
if (n <= 0) return "";
StringBuilder result = new StringBuilder();
for (int i = 0; i < n; i++) {
result.append(a);
}
return result.toString();
}
3. Method call output analysis:
static void show(int x) { System.out.println("int"); }
static void show(double x) { System.out.println("double"); }
static void show(long x) { System.out.println("long"); }
show(7); // Prints: "int" - 7 is an integer literal, exact match with int parameter
show(7L); // Prints: "long" - 7L is explicitly marked as long, exact match with long parameter
show(7.0); // Prints: "double" - 7.0 is a double literal, exact match with double parameter
Each call demonstrates Java’s method overload resolution:
show(7)- Matchesshow(int)because 7 is an integer literalshow(7L)- Matchesshow(long)because of the L suffixshow(7.0)- Matchesshow(double)because of the decimal point
FRQ-style Solutions
FRQ 1: indexOf Overloads with Test Cases
**Implementation Notes:**
1. Both overloads handle reversed bounds by swapping
2. Uses Math.min/max for cleaner implementation
3. Integer version handles int range only
4. Double version handles floating-point values
5. Both maintain inclusive bounds [low, high]
```java
// FRQ 1: IndexFinder implementation and tests
public class IndexFinder {
// First overload: find char in string
public static int indexOf(char target, String s) {
if (s == null) return -1;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == target) {
return i;
}
}
return -1;
}
// Second overload: find substring in string
public static int indexOf(String target, String s) {
if (s == null || target == null || target.length() > s.length()) {
return -1;
}
for (int i = 0; i <= s.length() - target.length(); i++) {
boolean found = true;
for (int j = 0; j < target.length(); j++) {
if (s.charAt(i + j) != target.charAt(j)) {
found = false;
break;
}
}
if (found) return i;
}
return -1;
}
public static void main(String[] args) {
// Test char indexOf
System.out.println("--- Testing char indexOf ---");
System.out.println("indexOf('a', \"Java\") = " + indexOf('a', "Java")); // 1
System.out.println("indexOf('z', \"Java\") = " + indexOf('z', "Java")); // -1
System.out.println("indexOf('J', \"Java\") = " + indexOf('J', "Java")); // 0
// Test String indexOf
System.out.println("\n--- Testing String indexOf ---");
System.out.println("indexOf(\"av\", \"Java\") = " + indexOf("av", "Java")); // 1
System.out.println("indexOf(\"java\", \"Java\") = " + indexOf("java", "Java")); // -1 (case sensitive)
System.out.println("indexOf(\"\", \"Java\") = " + indexOf("", "Java")); // 0 (empty string)
}
}
IndexFinder.main(null);
--- Testing char indexOf ---
indexOf('a', "Java") = 1
indexOf('z', "Java") = -1
indexOf('J', "Java") = 0
--- Testing String indexOf ---
indexOf("av", "Java") = 1
indexOf("java", "Java") = -1
indexOf("", "Java") = 0
// FRQ 2: ValueClamper implementation and tests
public class ValueClamper {
public static int clamp(int value, int low, int high) {
// Swap if bounds are reversed
if (low > high) {
int temp = low;
low = high;
high = temp;
}
return Math.min(Math.max(value, low), high);
}
public static double clamp(double value, double low, double high) {
// Swap if bounds are reversed
if (low > high) {
double temp = low;
low = high;
high = temp;
}
return Math.min(Math.max(value, low), high);
}
public static void main(String[] args) {
// Test integer clamp
System.out.println("--- Testing int clamp ---");
System.out.println("clamp(5, 1, 10) = " + clamp(5, 1, 10)); // 5 (within bounds)
System.out.println("clamp(0, 1, 10) = " + clamp(0, 1, 10)); // 1 (below min)
System.out.println("clamp(15, 1, 10) = " + clamp(15, 1, 10)); // 10 (above max)
System.out.println("clamp(5, 10, 1) = " + clamp(5, 10, 1)); // 5 (reversed bounds)
// Test double clamp
System.out.println("\n--- Testing double clamp ---");
System.out.println("clamp(3.5, 1.0, 10.0) = " + clamp(3.5, 1.0, 10.0)); // 3.5
System.out.println("clamp(0.5, 1.0, 10.0) = " + clamp(0.5, 1.0, 10.0)); // 1.0
System.out.println("clamp(11.5, 1.0, 10.0) = " + clamp(11.5, 1.0, 10.0)); // 10.0
System.out.println("clamp(5.5, 10.0, 1.0) = " + clamp(5.5, 10.0, 1.0)); // 5.5 (reversed bounds)
}
}
ValueClamper.main(null);
--- Testing int clamp ---
clamp(5, 1, 10) = 5
clamp(0, 1, 10) = 1
clamp(15, 1, 10) = 10
clamp(5, 10, 1) = 5
--- Testing double clamp ---
clamp(3.5, 1.0, 10.0) = 3.5
clamp(0.5, 1.0, 10.0) = 1.0
clamp(11.5, 1.0, 10.0) = 10.0
clamp(5.5, 10.0, 1.0) = 5.5