SEN1002 · Week 10 · Midterm Review

Midterm review: weeks 1-9 mixed

A one-page summary of every topic on the midterm, from classes to exceptions, and 12 exam-style questions that mix the topics together.

constructor chainingdynamic bindingabstract classinterfaceupcastingdowncastingoverloadingoverridingStringBuilderregexchecked exceptionfinallystack unwinding

This page is the last round before the midterm. Each of the first nine weeks can be asked separately, but midterm questions often combine two or three topics in one piece of code: a polymorphic call inside a constructor chain, an interface method in an abstract class, try/finally inside an overridden method. The table below collects the “if you do not know it, you lose points” rules of each week. After that there are 12 mixed questions; each question’s explanation says which week it belongs to. When you get stuck on a question, go back to that week’s page.

Study suggestion: solve the questions on paper, and do not open the answer before writing yours. In “What is printed?” questions, trace every line one by one and write the variable values next to it. In compile-error questions, first ask “does the compiler know this”: the compiler looks only at types, it does not see objects.

Weekly summary table

WeekTopicWhat you need to knowClassic pitfall
1Classes and objectsConstructor, this, encapsulation, static and instance, toString, equalsname = name; does not fill the field; once you write a constructor the default constructor is gone
2Inheritanceextends, super(...), constructor chain, overriding and overloading, ObjectIf the superclass has no no-argument constructor, the hidden super() does not compile
3PolymorphismStatic type and dynamic type, upcasting, downcasting, instanceofA method not in the type of the variable cannot be called; a wrong cast gives ClassCastException
4Abstract and interfaceabstract method, implements, default method, ComparableWriting an interface method without public
5GUI componentsJFrame, JLabel, JTextField, JButton, FlowLayout, BorderLayout, GridLayoutThe second add in BorderLayout replaces the previous one; getText() is a String
6EventsActionListener, getSource, inner class, anonymous class, lambdaModifying a local variable inside a lambda
7UMLVisibility markers, relationship arrows, multiplicity, aggregation and compositionThe triangle points to the superclass; the diamond is on the whole side
8String and regexsubstring, indexOf, char arithmetic, StringBuilder, split, matchesIf s.toUpperCase(); is not assigned, nothing changes
9Exceptionstry/catch/finally flow, checked and unchecked, throw and throws, custom exceptionWriting the general catch first; finally running before the return

A method for solving output questions

In mixed questions, follow this order:

  1. If an object is created, draw the constructor chain. Starting from the top superclass, write the bodies in order. Do not forget that field initializers are assigned after super() finishes.
  2. Ask two questions at every method call. Does the compiler allow this call (type of the variable)? Which version runs at run time (type of the object)?
  3. If there is an overload, choose the signature first. Look at the compile-time types of the arguments.
  4. If an exception happens in a try, cross out the remaining lines. Find the first matching catch, add the finally, then go up if it was not caught.
  5. In String operations, write out the indexes. In substring and indexOf questions, number the characters from 0 underneath them.
Example: new Mid();   (Mid extends Base, show() is called inside Base())

1. Mid() → super() → Base()
2. Base body: "Base "  then show()
3. show() is overridden, the object is a Mid → Mid.show()  → tag is still null  → "M.show(null) "
4. super() finished → Mid's fields are assigned: tag = "mid"
5. Mid body: "Mid "

Compile error or run-time error?

In “what happens?” questions on the midterm there are three answers: it does not compile, an exception is thrown while it runs, or it runs normally. A table to tell them apart:

SituationResult
Calling a method not in the type of the variableCompile error
Assigning from a supertype to a subtype without a castCompile error
Cast between sibling classesCompile error
A valid cast whose object does not fitRun time: ClassCastException
new on an abstract classCompile error
A concrete class did not write an abstract methodCompile error
A checked exception neither caught nor declaredCompile error
Array or String bound exceededRun time: IndexOutOfBounds
Method call on nullRun time: NullPointerException
Dividing an int by 0Run time: ArithmeticException
Integer.parseInt("abc")Run time: NumberFormatException
Modifying a local variable inside a lambdaCompile error
Access to a private field from another classCompile error

Final checklist

  • When you override equals, is the parameter Object? Did you write @Override?
  • Does the subclass constructor call the right constructor with super(...)?
  • Did you write public when implementing interface methods?
  • Does compareTo return an int, did you use Double.compare or Integer.compare?
  • Are the catches ordered from specific to general?
  • Is your own exception extends Exception (checked) or extends RuntimeException (unchecked), and does the method signature match?
  • Did you assign the String result to a variable?

Common mistakes

Wrong ideaThe truth
The subclass’s fields are ready at the start of the constructorThey hold default values until super() finishes
equals(Coin c) overrides equalsIt is an overload; when called with an argument of type Object, Object’s runs
An interface default method cannot be overriddenIt can; the Final.grade() example
p.parse("12") + p.parse("x") prints 12 firstprintln’s argument is computed completely, so the finally outputs come first
If there is a return in the catch, finally is skippedIt still runs
With an uncaught exception, finally does not runIt runs, then the exception goes up
An abstract class must write the interface methodIt does not have to; the concrete subclass must

Test yourself

Exam-style questions. Solve them on paper first, then reveal the answer.

Question 1medium

What is printed?

class Item {
    static int made = 0;
    int id;
    Item() { this(100); System.out.print("I() "); }
    Item(int id) { this.id = id + made; made++; System.out.print("I(" + this.id + ") "); }
}
// in main:
new Item(); new Item(5);
System.out.println(Item.made);
Show answer
I(100) I() I(6) 2

new Item() → this(100): made is still 0, id = 100, made becomes 1, I(100) is printed; then the outer constructor prints I(). new Item(5): id = 5 + 1 = 6, made 2. The static counter was shared across the two objects. (Week 1)

Question 2hard

What is printed by new Mid();?

class Base {
    Base() { System.out.print("Base "); show(); }
    void show() { System.out.print("B.show "); }
}
class Mid extends Base {
    String tag = "mid";
    Mid() { super(); System.out.print("Mid "); }
    @Override void show() { System.out.print("M.show(" + tag + ") "); }
}
Show answer
Base M.show(null) Mid

Base's constructor runs first. The show() inside it is overridden: the object is a Mid, so Mid's show runs. But Mid's field initializer (tag = "mid") is assigned after super() finishes; at that moment tag is still null. Then Mid's body. (Week 2 + 3)

Question 3medium

What is printed?

interface Scorable {
    int score();
    default String grade() { return score() >= 50 ? "PASS" : "FAIL"; }
}
abstract class Exam implements Scorable {
    protected int raw;
    Exam(int raw) { this.raw = raw; }
    public String toString() { return getClass().getSimpleName() + ":" + score() + ":" + grade(); }
}
class Midterm extends Exam { Midterm(int r) { super(r); } public int score() { return raw * 2; } }
class Final extends Exam {
    Final(int r) { super(r); }
    public int score() { return raw + 10; }
    public String grade() { return score() >= 60 ? "PASS" : "FAIL"; }
}
// in main:
Exam[] exams = { new Midterm(30), new Final(45), new Midterm(20) };
for (Exam e : exams) System.out.println(e);
Show answer
Midterm:60:PASS / Final:55:FAIL / Midterm:40:FAIL

Midterm(30): 60, the default grade (threshold 50): PASS. Final(45): 55, Final overrides grade (threshold 60): FAIL. Midterm(20): 40 < 50: FAIL. Exam is abstract and does not write score; the concrete classes do. (Week 3 + 4)

Question 4medium

Find the compile errors.

interface Scorable { int score(); }
abstract class Exam implements Scorable { }
class Quiz extends Exam { }
// in main:
Exam e = new Quiz();
Scorable s = e;
Quiz q = s;
Show answer
Quiz does not write score(); Scorable → Quiz cannot be assigned without a cast

Since Exam is abstract it does not have to write score(), but the concrete Quiz must: Quiz is not abstract and does not override abstract method score() in Scorable. Scorable s = e; is valid (upcasting). Quiz q = s; is a downcast: incompatible types: Scorable cannot be converted to Quiz; (Quiz) s is needed. (Week 3 + 4)

Question 5medium

What is printed?

static String mystery(String s) {
    StringBuilder sb = new StringBuilder();
    for (int i = s.length() - 1; i >= 0; i -= 2) sb.append(s.charAt(i));
    return sb.toString().toUpperCase();
}
// in main:
System.out.println(mystery("polymorph"));
Show answer
HRMLP

"polymorph" has 9 characters, indexes 0-8. The loop goes 8, 6, 4, 2, 0: h, r, m, l, p. Joined it is "hrmlp", in upper case HRMLP. (Week 8)

Question 6medium

What is printed?

String s = "a-b--c";
System.out.println(s.split("-").length + " " + s.replaceAll("-+", "+") + " " + s.indexOf("--"));
Show answer
4 a+b+c 3

split: a, b, "" (between the two dashes), c: 4 parts. -+ is one or more dashes: each group becomes a single +. "--" first starts at index 3 (a0 -1 b2 -3). (Week 8)

Question 7hard

What is printed?

class Parser { int parse(String s) { return Integer.parseInt(s); } }
class SafeParser extends Parser {
    @Override int parse(String s) {
        try { return super.parse(s); }
        catch (NumberFormatException e) { return -1; }
        finally { System.out.print("[done " + s + "] "); }
    }
}
// in main:
Parser p = new SafeParser();
System.out.println(p.parse("12") + p.parse("x"));
Show answer
[done 12] [done x] 11

Dynamic binding: both calls go to SafeParser's parse. "12" → 12, finally prints. "x" → NumberFormatException is caught, −1, finally prints. println's argument is computed only after both calls finish: 12 + (−1) = 11 is printed last. (Week 3 + 9)

Question 8hard

What is printed?

static int risky(int x) {
    try {
        if (x < 0) throw new IllegalArgumentException("neg");
        return 10 / x;
    } catch (ArithmeticException e) {
        System.out.print("AE ");
        return 0;
    } finally {
        System.out.print("F ");
    }
}
// in main:
System.out.println(risky(5));
System.out.println(risky(0));
try { System.out.println(risky(-1)); }
catch (IllegalArgumentException e) { System.out.println("caught " + e.getMessage()); }
Show answer
F 2 / AE F 0 / F caught neg

risky(5): 10 / 5 = 2, before returning, finally prints "F ". risky(0): ArithmeticException is caught, "AE ", it will return 0, but first finally prints "F ". risky(-1): there is no catch for IllegalArgumentException; finally runs, the exception goes up to main and the catch there catches it. (Week 9)

Question 9hard

What is printed?

class Coin {
    int value;
    Coin(int v) { value = v; }
    public boolean equals(Coin other) { return value == other.value; }
}
// in main:
Coin c1 = new Coin(5), c2 = new Coin(5);
Object o2 = c2;
System.out.println(c1.equals(c2) + " " + c1.equals(o2));
Show answer
true false

equals(Coin) does not override Object's equals(Object), it overloads it. c1.equals(c2): the argument is a Coin, the compiler chooses equals(Coin): true. c1.equals(o2): the static type of the argument is Object, equals(Object) is chosen, and that is Object's (address): false. If @Override had been written, the compiler would have caught the error. (Week 1 + 2 + 3)

Question 10easy

Which statement is FALSE?

  1. A subclass constructor always calls a superclass constructor first
  2. An interface can contain default methods
  3. A checked exception must be caught or declared
  4. Fields are chosen by the object's runtime type
Show answer
Fields are chosen by the object's runtime type

Fields are not overridden; ref.field looks at the compile-time type of the variable. Dynamic binding is only for overridden instance methods. The other three are true: the hidden super(), Java 8+ default methods, the checked exception rule.

Question 11easy

Which layout is the default for a JFrame's content pane, and what happens when you call frame.add(b1); frame.add(b2);?

Show answer
BorderLayout; both go to CENTER, only b2 is visible

The content pane comes with BorderLayout; an add without a position puts the component in CENTER and replaces the earlier component in the same region. To see them side by side, use setLayout(new FlowLayout()) or a JPanel. (Week 5)

Question 12hard

Write an abstract class Shape that implements Comparable<Shape> (comparing by area) with an abstract double area(), and two subclasses Rect(w, h) and Circle(r). Sorting {Rect(2,5), Circle(1), Rect(1,1)} must give [Rect(1.0), Circle(3.14), Rect(10.0)].

Show answer
abstract class Shape implements Comparable<Shape> + Double.compare(area(), o.area())

compareTo is written once in the abstract class, and the area() inside it works differently in each subclass (polymorphism):

abstract class Shape implements Comparable<Shape> {
    abstract double area();
    public int compareTo(Shape o) {
        return Double.compare(area(), o.area());
    }
}
class Rect extends Shape {
    double w, h;
    Rect(double w, double h) { this.w = w; this.h = h; }
    double area() { return w * h; }
    public String toString() { return "Rect(" + area() + ")"; }
}
class Circle extends Shape {
    double r;
    Circle(double r) { this.r = r; }
    double area() { return Math.PI * r * r; }
    public String toString() { return String.format("Circle(%.2f)", area()); }
}
The areas are 10.0, 3.14..., 1.0; Arrays.sort orders them ascending: [Rect(1.0), Circle(3.14), Rect(10.0)].

Verification: All questions were run with JDK 26 (java verify/SEN1002/W10.java); the compile-error question was tried with javac (verify/SEN1002/err/E10a.java). The rules in the summary table come from the verification files of the week 1-9 pages.

Review card

CTOR: this(...) / super(...) first line. Hidden super(). Output top down. Field initializer AFTER super(). STATIC: one copy. No access to an instance field from static. ==: address. Override equals(Object); equals(Coin) becomes an overload. The COMPILER looks at the type of the variable, the JVM at the type of the object (for overridden methods). Field / static / private: type of the variable. Overload choice: static type of the argument. Upcast is automatic. Downcast needs (Sub); ClassCastException if wrong. Between siblings: compile error. abstract: no new; abstract method → abstract class; the concrete subclass writes all of them. interface: methods public; field public static final; many implements; override if defaults clash. GUI: JPanel FlowLayout, JFrame BorderLayout. getText() String. Lambda only for single-method interfaces. Local variable in a lambda is effectively final. MouseListener → MouseAdapter. UML: + - # ~, underlined static, hollow triangle extends, dashed triangle implements, filled diamond composition. String immutable; substring(a,b) b excluded; 'A'+2=67; split drops trailing empties; StringBuilder has no equals. try rest is skipped, first matching catch, finally ALWAYS; subclass catch first. Checked (IOException) → catch or throws. Unchecked (RuntimeException) → free.