Fifteen modules, one Eclipse project, and every verbatim previous-year question answered in full — built for a student picking this up with nothing but the syllabus.
Official R-24 wording for Unit 2, with the module that covers each phrase.
Grouped the way the Eclipse Package Explorer would show it — click a folder to expand.
Fifteen modules that build one Eclipse project from an empty folder to a working multithreaded program. Every line is typed, run, and shown with its real console output — and every previous-year question is answered in full where it belongs.
A short orientation before Unit 2's Java content begins.
The official Unit 2 syllabus (UI24PC320CS, R-24), with the module that covers each phrase.
JDK 21 and Eclipse assumed installed. Three panels recur throughout the unit: Package Explorer (left), editor (centre), Console (bottom).
Nothing new here. Every Unit 2 example is this same shape with more added — the private field, the constructor that fills it, the method that reads it. If any line above is unfamiliar, revisit Unit 1 before Module 2.
Package Explorer is where your folder tree lives — every module ends by showing you what it looks like. The Console is where every output in this unit appears.
Almost everything you make in Eclipse starts the same way — File → New → then whatever you want:
Watch the cursor below. It opens File, rests on New until the second menu slides out, then lands on Java Project. Three stops, always in that order.
If the side menu closes before you reach it, you moved diagonally and slipped off New on the way. Travel right first, then down.
The wizard that opens has a lot on it. You only need the first box; everything else is already correct.
Type the project name exactly as shown — Unit2Project, one word, capital U and P, no spaces. Every folder path in this unit assumes that name, so a different spelling means translating every later instruction in your head.
Unit2Project into Project namesrc folderEclipse closes the wizard and Unit2Project appears in the Package Explorer on the left, with an empty src folder inside. That src folder is where every file in this unit will live.
That third setting is the one that creates the src folder every file in this unit lives inside. Leave it ticked.
Unit 2 builds on three things from Unit 1. The program below contains all three, labelled as they appear. If it reads comfortably, you're ready.
Student object will hold and donew Student("Asha").Module 2 changes exactly one thing about that constructor — and that single change is the whole Singleton idea.
About nine hours total, split into four sittings. Every sitting ends on a completed topic — never mid-concept.
Eighteen previous-year questions land across these modules — each one answered in full, at the point its concept is taught, never saved for the end.
Using the Student class above, answer these three, then open the worked answers to check.
1. Which line is the constructor, and how did you know?
2. Why can't you print a Student's name from outside the class right now?
3. What would change if the constructor were marked private?
Student), and it has no return type — not even void. Those two together only ever describe a constructor.name field is private, so only code inside Student can touch it. Outside code would need a method the class chooses to offer.new Student(...) anymore — creation would be blocked entirely unless the class provided its own way out. That's exactly the door Module 2 walks through.
The project as it stands after Module 1 — empty. Module 2 adds the first file, and this tree grows cumulatively from there.
Module 2 adds school/ClassMonitor.java — the first file in this project.
newThe parameter is t and the field is title, so the two names never clash.
== compares objects, not contents. This matters more than it looks — Module 2 exists because of it.Two objects were built, so matching titles change nothing. == asks "are these the same object in memory?" Module 2 is entirely about controlling this.
private blocks outside access. Writing a.title from another class does not compile.Outside code must go through getTitle(). Module 2 applies this same rule to a constructor instead of a field — that one move is what makes a Singleton work.
title private rather than public?a == b print if both came from the same new Book(...) call?true, both names would point at one object; getTitle().Module 1 set up the project. This is the first thing built inside it, and it answers a question the language itself cannot: how do you stop a class being made twice?
Before any Java: a classroom has exactly one class monitor at a time. A new monitor cannot be appointed while the post is already filled.
That rule is not about tidiness. It exists because the monitor holds something — today's attendance, who was sent to the office, which period got cancelled. One holder means one answer to any question about it.
Now imagine the post were unguarded and two students each believed they were monitor. Both start taking attendance. Ask "how many present today?" and you get two numbers. Neither is wrong from where that student sits — and there is no way to decide which counts. The information has not just gone stale; it has split.
The right-hand case is not merely untidy — it is broken, and broken in a way that is hard to notice. Nothing crashes. Both monitors work perfectly. The failure only appears when the two answers are finally compared, which might be days later.
The class monitor is a stand-in for a whole family of real cases. Each one is a thing a program should have exactly one of:
The pattern you are about to learn is called Singleton — "single" plus "-ton", one instance. Its whole job is to make the second copy impossible, rather than merely discouraged by a comment.
Hold onto that. In a moment you'll watch Java cheerfully create the broken version.
new actually doesBefore any code, one rule. It has no exceptions, and the whole module rests on it:
new, it builds a brand-new, separate object. It never checks whether a similar one already exists. It never reuses one.So if a program says new twice, two objects exist:
Apply that to the classroom. A monitor is a post that allows one holder — but Java has no idea about that rule. Ask it for two monitors and it will hand you two, without hesitation.
Here is the first line. Nothing unusual — this is the ordinary class creation you already know from Unit 1.
first at it.new means new.== on two objects asks one narrow question: are these the very same object in memory? Not "do they look alike" — are they the same one?Now the same three lines, assembled into a program you can actually run.
No error. No warning. Java did exactly as told and produced two separate monitors. The broken case from the last page is now sitting in front of you, confirmed by that false.
new BUILT ITS OWN OBJECTTwo boxes on the left are names. Two boxes on the right are objects. Each name points at its own object — which is exactly why == answered false. Fixing this means making both names point at one object, and that is what the next chunk builds.
Before writing the fix, the file has to exist in the right place. This is the first file of the unit, so it is worth doing slowly — every later module repeats these same steps without spelling them out.
Java files live inside packages, which are just folders under src. This one goes in a package called school.
src folder inside Unit2Projectschool, press Finishschool package, choose New → ClassClassMonitor as the class name — capital C, capital M, no .java on the endpublic class ClassMonitor has to sit in ClassMonitor.java. Eclipse handles this when you use the wizard, which is exactly why we use it rather than creating files by hand.Three changes make a second monitor impossible. Not discouraged — impossible, refused by the compiler. They arrive one at a time.
static field.private so no outside code can call new.static method that hands out that one monitor.Run it with the MonitorDemo driver below. The constructor line prints once, not three times — that single line is the proof.
private can only be called from inside this class. Every new ClassMonitor() written anywhere else now fails to compile — that's the lock.
getInstance() must be static because you call it without having an object yet — ClassMonitor.getInstance(), not someMonitor.getInstance().
The formal definition, which describes exactly what was written above:
private, and that single word is what stops outside code from calling new ClassMonitor(). If you see private on a constructor, a Singleton is almost always the reason.There is a name for what you just did — hiding the inside of a class and exposing one controlled way in. It is called encapsulation, and Module 7 gives it a section of its own.
Three unfamiliar words arrive together here. Said in plain English, one at a time, they are simple.
static means the slot belongs to the class, so there is one slot, not one per object. It starts empty.private means only code inside this class may make one — nobody else, ever.If the code still looks dense, read only the three lines above. Nothing else in the class matters to the idea.
The same rule appears outside code. In both cases: one holder of the post, and one route to reach whoever holds it.
getInstance().
Neither needs a line of code to make sense — and that is the point. If you can explain the principal, you can explain getInstance().
Three separate requests for the monitor, from three different points in main.
The first line printed once, not three times: the constructor ran exactly once across all three requests. That is stronger proof than the boolean alone.
The same object is returned all three times. Writing new ClassMonitor() in this file is rejected by the compiler before the program runs.
getInstance() call actually asks for it.
new still works from outside. All three pieces are needed together.
static on the field. A non-static field belongs to an object — but you need it before any object exists. It won't compile.
null check. Without it, every call builds a fresh object and you're back to the broken version from Chunk 2.
Eager is one line shorter — private static ClassMonitor theMonitor = new ClassMonitor(); and no null check — but it builds the object whether the program ever asks for it or not.
getInstance() at the exact same instant, both could find theMonitor still null and both build one. Fixing that needs a tool you meet in Module 12, where this exact class gets its repair.The classroom example made the idea concrete. Here is the same pattern with nothing in common except the shape — a school has one and only one attendance register for the day.
Two different teachers mark attendance from two different places in the program — and because both reach the same object, the count adds up instead of splitting in two.
Same three pieces, different domain. If you can spot the private field, the private constructor and the static access method here, you can spot them anywhere.
a and b are two names for the same object, so both increments land on the same counter, and both reads report the same number. Had this been an ordinary class with a public constructor, the answer would have been 1 1 — two separate registers, each counting its own.public, not private.getInstance() built the one shared card, and then line two ignored it entirely and built a second card directly. The static field and the access method are doing their jobs perfectly — they are simply being bypassed, because nothing forbids new.public LibraryCard() to private LibraryCard(). The second line then fails to compile with "The constructor LibraryCard() is not visible", which is exactly what you want — the mistake gets caught before the program ever runs.synchronized because there is no first-call race.private static field to hold the one instance, a private constructor so no outside code can call new, and a public static method that creates it on first request and returns the same one thereafter.Point out in the answer: "Constructor ran once." appears a single time even though getInstance() was called twice — that one line is what proves only one object was ever created.
Answer these three, then open the worked answers to check.
1. Remove only the private from the constructor. What breaks?
2. Why must getInstance() be static?
3. Explain the whole pattern to someone in one sentence, using the classroom.
new ClassMonitor() again, so second and third monitors appear freely — you're back to Chunk 2's false. The field and getInstance() still work, but nothing stops duplication anymore. All three pieces only work together.static lets you call it on the class itself: ClassMonitor.getInstance().The project after Module 2 — two files: the Singleton class and the driver that demonstrated it.
Module 3 adds an abstract class alongside these — nothing here gets replaced.
PrincipalOffice that stores the principal's name and hands out the same office object every time. Include a small main proving two requests return one object.private constructor to block new, the private static field to hold the one instance, and the public static method to hand it out.getTotalSeats() is untouched. Turning a class into a Singleton changes how it is obtained, never what it does.Module 2 made a class that guards how many objects exist. This one goes further — a class that cannot be made into an object at all, and is still useful.
Consider a blueprint that deliberately leaves one room unlabelled. Walls, plumbing and staircase are fixed; the unlabelled room is left for each builder to decide — study, nursery, or storeroom.
You could try to fake it with an ordinary class — write reserve() with an empty body and leave a comment saying "subclasses must override this". Two things go wrong.
A Unit 1 word, recalled: to override a method is for a subclass to write its own version of a method the parent already declared. The subclass's version is the one that runs.
reserve() compiles happily and silently inherits the empty version. The bug appears at runtime as "nothing happened" — the hardest kind to trace.
new Reservation() and gets an object whose central method does nothing — a reservation that cannot reserve.
Marking the class abstract hands both problems to the compiler. The forgetful subclass is refused; the attempt to build the parent is refused. Neither reaches a running program.
abstract.
The smallest possible abstract class, followed by the one operation Java refuses to allow.
Line 6 is the whole difference: abstract, no braces, ends in a semicolon. A method with no body cannot be run — so an object of this class would be unusable, and Java refuses to make one.
Read the message literally: to instantiate is to make an object. Java is stating that this type is not one you can make an object of.
The red mark appears the instant you type it — before you ever press Run. This is a compile-time refusal, not a crash at runtime.
Now the useful shape. An abstract class is rarely all holes — that would make it an interface, which Module 5 covers. Its real value is carrying both kinds of method at once.
abstract and make them supply it.Work through the two methods a reservation needs:
reserve() differs. A train booking allocates a coach and berth; a bus booking allocates a seat number. No sensible shared version exists — so it stays abstract.printReceipt() is identical. Every reservation prints the same banner. Writing it twice means fixing any typo twice — so it is written once, concretely, in the parent.That single judgement is the whole design skill here:
Each subclass supplied its own reserve(). The receipt line is identical in both, and was written once in the abstract class.
Consider what that buys you. Adding a third booking type — flight, ferry, anything — costs exactly one reserve() method. The receipt, and any shared behaviour added later, arrives free and already correct. That is the return on marking the class abstract.
reserve() in a subclass and that subclass won't compile either — Java makes you either implement it or declare the subclass abstract too.
It sounds contradictory, since no object of the class can be made directly. Yet an abstract class can have a constructor, and it does run.
This class alone produces no output — it cannot be run. Attempting new Reservation() gives the compiler error above, which is the whole point of Chunk 2.
No code wrote new Reservation(). Its constructor still ran, and the field it initialised is present inside the ReserveTrain object.
ReserveTrain therefore always builds its Reservation part first.
public or private in front. That is enough for a subclass in the same package to read it. Access specifiers get their own full treatment in Module 7.
Note there is no super() written anywhere above — none is needed, so none was added.
printReceipt() lives in one place. Fix a typo there and every subclass is fixed at the same time.
reserve() — the compiler stops it. A comment asking politely would not.
Reservation variable can hold a train or a bus booking, so code that handles bookings doesn't care which kind arrived.
Reservation — no sensible default reserve() existsVehicle whose start() every subclass inherits unchangedThe deciding question is simply: does a plain "Reservation" — neither train nor bus — mean anything on its own? It doesn't. That's the signal to make it abstract.
Same shape, different subject. Every exam paper has to be graded, but a multiple-choice paper and a written paper are graded in completely different ways — while the pass mark is identical for both.
Both papers are graded through one common variable type, and both use the same untouched hasPassed().
ExamPaper. What prints, and which grade() actually runs?ExamPaper, the parent type — but each object remembers what it really is. Java picks grade() based on the actual object, not the declared type — so the written paper grades by rubric and the MCQ by key. hasPassed() is not overridden anywhere, so both calls run the one version in ExamPaper.if checking which kind you have.hasPassed(), which it was free to do but was never required to. It never supplied grade(), which it was required to. Overriding an optional method does not satisfy a mandatory one.grade() has no body, so an ExamPaper object would have a method that cannot run — Java refuses to create one.grade() method to PracticalPaper, or mark the class abstract itself and let its own subclasses supply it.ReserveTrain in a Reservation variable is upcasting. Java choosing which reserve() runs at run time, based on the real object rather than the variable's type, is dynamic method dispatch — also called run-time polymorphism.Reservation, marked abstract, declaring reserve() with no body.extends Reservation and supplies its own reserve().reserve(), proving the two behave differently from the same parent type.Worth two extra marks: lines 31–32 declare both variables as type Reservation, not ReserveTrain/ReserveBus. Java still calls the right reserve() for each. Say so in the answer — it shows the abstract class is doing real work as a shared type, not just holding a method signature.
Write ReserveFlight extending the same Reservation class, then answer both questions before opening the solution.
1. Write the full ReserveFlight class.
2. Do you have to write printReceipt() in it? Why or why not?
3. If you only wrote the class header and left the body empty, what would Eclipse say?
class ReserveFlight extends Reservation
{
public void reserve()
{
System.out.println("Flight reserved : 6E-233, seat 22A");
}
}
2. No. printReceipt() is concrete in Reservation, so it's inherited already — writing it again would only duplicate working code. Only reserve() is left unfinished, so only reserve() must be supplied.Three files added this module, in a new travel package alongside the existing school package.
Module 4 adds nested classes to this same tree — nothing here gets replaced.
Employee with an abstract calculateSalary() and a concrete showId(). Implement PermanentEmployee and ContractEmployee, then create one of each and print both salaries.id directly in its own constructor. No super() is written anywhere, because none is needed — the parent has a no-argument constructor, so Java supplies that call itself.abstract still achieve?abstract with every method fully written.Car builds its Vehicle part first, then finishes the Car part.v is declared as Vehicle, yet v.start() runs Car's version — Java selects the method from the actual object, not the declared type.Module 3 left a class deliberately unfinished. This one is deliberately hidden — a class that only makes sense inside another.
Some things have no meaning on their own. A car's engine is a real, complicated thing — but nobody keeps a spare engine in the living room and calls it useful. It exists to sit inside a car.
Java lets you write a class in exactly that position: declared inside another class, because outside it the class would mean nothing.
.java file.
Car.Engine.
Engine belongs to Car.
Java offers four forms of this. The three you will meet and be examined on:
Marked static. It lives inside the outer class for organisation only — it does not need an outer object to exist, and it cannot reach the outer object's fields.
static. The nesting is then purely organisational — a filing decision, not a behavioural one.A college address is a good fit. The address does not depend on which college object you happen to hold; it is data in its own right. Nesting it under College just says "this belongs to the college concept" so nobody has to hunt for a loose Address.java among forty files.
A nested class needs no new file. It is typed inside the braces of the class that contains it.
src, choose New → Package, name it campuscampus, choose New → Class, name it CollegeAddress class inside College's braces — do not create a second fileAddress listed underneathLine 8 is the whole syntax: Outer.Inner obj = new Outer.Inner(); — the outer class name appears, but no outer object is ever built.
name. Writing System.out.println(name); inside Address fails with "Cannot make a static reference to the non-static field name". A static nested class has no outer object to read that field from.
Drop the static and everything changes. The class is now tied to a specific outer object, and in exchange it can read that object's private fields directly.
That trade is worth being precise about, because it is the whole difference between the two forms:
A principal is the natural example, and it shows why the dependency is worth modelling:
Line 8 is the syntax students most often get wrong, and the one that makes this topic feel hard: c.new Principal().
c to make me a Principal." The college makes its own principal, so the college's name goes first.new Principal() — "make me a principal." Java asks: of which college? and has no answer.c.new Principal() — "college c, make your principal." Now there is an answer, so the object can exist.It looks strange because it is rare — most Java code never needs it. You need to recognise it and be able to write it once; you do not need to find it natural.
new College.Principal() fails with "An enclosing instance that contains College.Principal is required" — Java is telling you it has no outer object to attach the new inner object to.
Start from a question: if a class is going to be written, used once, and never mentioned again — why give it a name at all?
Here is the long way. An interface, a named class implementing it, and one use:
The name MorningGreeting is used exactly once, on line 14, and never again. An anonymous inner class removes it:
Greeting, and give me one object of it".
Every nested class could have been an ordinary class in its own file. These are the reasons not to.
Address inside College tells you instantly that it belongs there. A loose Address.java among forty files tells you nothing.Principal reads name directly. Written separately it would need the college passed in, stored, and exposed by a getter — three more pieces to keep correct.static class Xclass Xnew Outer.X()outerObj.new X()College.Addressc.new Principal()AnonDemo’s one-off GreeterSection object is bound to the particular Batch that created it, so each reads a different year. This is the whole point of an inner class — the same class definition produces objects that behave differently depending on which outer object they belong to.Section is an inner class, so it cannot exist without a Batch object. Fix: Batch b = new Batch(2024); Batch.Section s = b.new Section();Address is static, so there is no outer object for it to read name from. Fix: either drop static to make it an inner class, or pass the name in as a parameter.Three scenarios. For each, say which of the three forms fits and give one line of reasoning.
1. A BankAccount class needs a small Transaction type that records an amount and a date. Transactions are created and listed from many places in the program.
2. A Library class needs a DueDateCalculator that must read the library's own loanPeriodDays field.
3. A button needs a click handler that prints one line, used at exactly one place in the code.
Transaction has its own amount and date — it never needs to read the account's fields. Grouping it under BankAccount shows the relationship, and static means callers can build one with new BankAccount.Transaction(...) without holding an account object.loanPeriodDays on a specific library object. Making it static would break exactly that — "Cannot make a static reference to the non-static field". Create it with lib.new DueDateCalculator().new ClickHandler() { ... }; — remember the semicolon after the closing brace.Laptop class with an inner Battery class that prints the laptop's model along with a charge percentage. Drive it from main.Battery reads model with no getter, because an inner object holds a link to the outer object that made it.LoudAlarm class disappears entirely. Watch the semicolon after the closing brace — the whole thing is still one assignment statement.outerObj.new Inner() exists as syntax at all. Why can Java not simply use new Outer.Inner() for both forms?new is how you supply it.new Outer.Inner() names only the class, not any particular object — which is exactly enough for a static nested class, and exactly not enough for an inner one. The two syntaxes exist because the two forms need different amounts of information.Module 5 adds interfaces to this same tree — nothing here gets replaced.
A hospital, a school and a shopping mall have nothing in common. Different buildings, different staff, different purpose.
Yet all three sign the same fire-safety agreement: there must be an alarm, an exit route, and a drill schedule. The agreement says what each building must provide. It says nothing about how — the mall's alarm and the school's alarm can work completely differently.
Two files. The first states what must exist; the second supplies it. Neither knows anything about the other beyond that agreement.
public is not optional on line 5. Interface methods are public by default, and a class may never reduce that. Leave it off and you get "Cannot reduce the visibility of the inherited method".
soundAlarm() entirely and the class will not compile: "The type School must implement the inherited abstract method FireSafety.soundAlarm()" — the same enforcement you met with abstract classes in Module 3.
A class may extend only one class. That is a hard limit in Java, and it is worth knowing why — because that limitation is the entire reason interfaces exist.
Suppose a class could extend two parents, and both happened to define a method called report(), each with its own body. A call to report() on the child would have two candidates and no rule for choosing. Worse, if both parents held a field called count, the child would carry two different counts under one name.
Languages that permit two parents need complicated rules to untangle it. Java forbids it instead:
report() create no conflict, because neither supplies an implementation to choose between. So a class may sign as many as it needs.That is the trade in one line: one class for what you inherit, many interfaces for what you promise.
One comma on line 3 of Hospital.java is the whole syntax. Both agreements are now binding, and both methods had to be supplied.
default and staticOriginally an interface could hold nothing but empty method names. That caused a practical problem: add one new method to an interface, and every class that ever signed it stops compiling until it supplies that method too.
Java 8 added two escapes, and both exist for practical reasons rather than elegance.
Picture an interface used by two hundred classes across a codebase you don't fully control. Adding one method the old way breaks all two hundred at once, and every owner must be found and made to fix theirs before anything compiles again. That cost meant interfaces effectively could never grow.
FireSafety.helpline(), never through an object, and never inherited by signers.
All three classes go in a single file here, which is legal as long as only one of them is public — and that one must match the file name.
src → New → Package, name it safetysafety → New → Class, name it LibraryDemo, tick the main stubLibrary interface and VasaviLibrary class above the public class, in the same fileWorth a mark: line 32 declares lib as type Library, the interface — not VasaviLibrary. Say in the answer that an interface can be used as a variable type even though it can never be instantiated.
An interface costs a file and a keyword. What it buys back:
FireSafety variable and treated identically.Library works with VasaviLibrary, or any library written later that you have never seen.This comparison is asked directly in exams. Both enforce that subclasses supply certain methods — the differences are what decide which you reach for.
extendsimplementsdefault or staticLibrary — three promises, no shared codeReservation — printReceipt() shared, reserve() notThe quickest test: could two totally unrelated classes need this? A hospital and a mall are not kinds of the same thing, but both are capable of fire safety — so that is an interface. A train booking and a bus booking are both kinds of reservation, sharing a PNR and a receipt — so that was an abstract class.
Receipt overrode header(), so its own version runs. It said nothing about footer(), so the interface's default body runs untouched. The class compiled without supplying either — that is exactly what default is for.public static final — a constant — so private is refused. Interfaces describe behaviour, not data.pay() has no body, so the object would be unusable.pay() is public in the interface. Omitting public on line 14 makes it package-private, which is narrower. Fix: public void pay().Three designs. For each, choose interface or abstract class and justify in one line.
1. SavingsAccount and CurrentAccount both hold a balance and an account number, and both need their own calculateInterest().
2. A Drone, a Parrot and a Kite all need a fly() method.
3. Every class in a payroll system must be able to exportToCsv(), and most of them should share one standard implementation.
deposit() in the parent, leave calculateInterest() abstract.Flyer parent would also burn each class's single extends slot for nothing.default method. The capability is needed across unrelated classes, so an interface — but a shared standard implementation belongs in a default body, so no class has to write it and any class may still override it.Playable with play() and stop(), implemented by Guitar and Radio. Drive both through one array declared as the interface type.describe(). How do you add it without breaking any of the ten, and what is the trade-off?default method with a working body:
extend an abstract class and implements an interface at the same time? Write the header line if so.extends comes first, then implements:
Module 6 begins Packages — the folders themselves become the subject.
Modules 2 to 5 filled one folder with classes. A real project has dozens, and two of them eventually want the same name. That is what a package solves.
That is the whole idea, and it is worth saying plainly before any tool gets involved. A package is a folder on your disk. Nothing more mysterious than that.
Java uses folders for the same reasons you do:
Library in one folder and a Library in another are two different classes, and Java can tell them apart.package line written inside a file must exactly match the folder path that file sits in. package college.exams; means the file lives in a folder called exams, inside a folder called college. Mismatch it and nothing runs.You have already been using packages — school, travel, campus, safety. Eclipse created the folders silently each time. This module removes the tool so you can see what it was doing.
Close Eclipse. For this module you need two things only: a plain text editor and a command window.
It is fair to ask why, when Eclipse does all of this in two clicks. Three reasons:
college.exams as one flat row and hides the nesting. Doing it by hand, you make the folders yourself.javac, -d, and running by fully qualified name expect the manual picture, not the IDE one.ManualDemo. This stands in for the project.collegecollege, make a folder called examsPaper.java inside examsPaper.java.txt, which the compiler will not accept.Two folders, one empty file. No tool made these — you did, with the same right-click you would use for any folder.
package statementNow the file declares where it lives. This line must be the very first line of code in the file — nothing but comments may come before it.
Java is strict about the order at the top of every file, and the order is always the same three things:
package — where this file lives. At most one, and it comes first.import — what this file borrows from elsewhere. As many as needed.Put an import above the package line and it will not compile. The order is not a convention — it is part of the language.
Run from D:\ManualDemo with java college.office.PaperDemo once the driver in Chunk 5 exists.
college\\exams on disk becomes college.exams in code.
;. Forgetting it is the most common first error here.
Open a command window in the ManualDemo folder — not in exams. Where you stand matters, and the next chunk shows why.
Four pieces, each doing one job:
javac — the Java compiler. It turns .java source into .class bytecode.-d — "destination". It tells javac where to put the compiled output, and to build the package folders there itself.. — the destination, meaning "right here, the folder I am standing in".college\exams\Paper.java — which file to compile, given as a path from where you stand.-d, the .class file lands beside the source, inside exams, and Java will not find it as part of a package. -d . is what makes the compiled output respect the package structure.javac prints nothing when it works. If you see nothing at all, it compiled.A class inside a package is no longer called Paper. Its real name now includes the package.
Notice there is no .class on the end and no backslashes. You give java the class name, not a file path — and the full class name uses dots.
This trips people up because javac and java want different things from you, and they look similar on the line.
javac takes a file. It needs to find a .java file on disk, so you give it a path with backslashes and the extension: college\exams\Paper.javajava takes a class. It needs a class name, so you give it dots and no extension: college.exams.PaperThe reason for the second rule is worth knowing. Java starts at your current folder and treats each dot as "go one folder deeper". college.office.PaperDemo means: look for a folder college, then office inside it, then a file PaperDemo.class inside that.
java Paperjava college.exams.PaperPaper any moreexamsManualDemo, above the package foldersManualDemo it can find college, then exams. From inside exams there is nowhere left to go, and you get "Could not find or load main class".After compiling, the folder contains both what you wrote and what javac produced.
The .class file sits beside its source because you compiled with -d . from ManualDemo, and javac rebuilt the same college\exams path underneath. Source and output mirror each other exactly.
importOne package alone proves little. The real question is how a class in one folder reaches a class in another.
Add a second package, college.office, holding a class that uses Paper.
Paper, I mean the one in college.exams". Without it, line 9 fails — this file's own folder has no Paper in it.
package first, then import, then the class. Java will not accept them in any other order.
Paper and show() are both public. Had either been left plain, this file could not touch them from a different package — the subject of Module 7.
Both files are listed in one javac command so the compiler sees them together. Then the program is run by its full name, from ManualDemo, exactly as before.
You could put every class loose in one folder. Java allows it. Here is what you lose by doing so.
Library can coexist as college.Library and city.Library. Without packages the second one simply cannot exist.travel, every safety class in safety. Finding something becomes navigation rather than searching.java from the folder above the package works because . — the current folder — is on the classpath by default, and college.exams.Paper is then found at .\college\exams\Paper.class.The file sits in college\exams but its first line says something else.
Why it's nasty: javac -d . happily creates a folder called exam to match what you wrote. Nothing complains until you try to run it. One missing letter, and the compiler quietly builds you the wrong structure.
You wrote the package line first and never created the matching folder.
Why it's kinder: this one fails loudly and straight away. The package statement does not create folders — it only declares where the file already is. You make the folders; the statement describes them.
package line, and the name you typed after java. All three must agree exactly, including capitals.
Everything you just did by hand, Eclipse does for you in two clicks. Knowing the manual version is what lets you fix it when the tool gets it wrong.
1. What does -d . tell javac to do, in one sentence?
2. A file in shop\billing should start with which line?
3. From which folder do you run java shop.billing.Invoice?
.class files in the current folder, rebuilding the package folder structure there.package shop.billing; — dots where the backslashes are.shop, not shop or billing. Java follows the dots downward from where you stand.package line describes it, and public is what let one package's class be used from another. Module 7 turns that last point into the full access-control picture.D:\Shop\billing\Invoice.java. Write its first line, then the command that compiles it, standing in D:\Shop.billing sits directly inside Shop, and Shop is where you stand — so the package is just billing, with no Shop in front of it.java Invoice reports "Could not find or load main class Invoice". The file is correct. What is wrong, and what should they type?Invoice any more.java billing.Invoice, standing in D:\Shop.billing cannot work, because Java looks for a folder called billing below where it starts.shop.billing.Invoice and shop.staff.Cashier. Cashier needs to create an Invoice. Write the top three lines of Cashier.java.shop together is not enough — billing and staff are different packages, so the import is required.Invoice and any method Cashier calls on it must also be public, or the import will not save it.Module 7 rebuilds this same structure inside Eclipse, then uses it to teach access control.
Module 6 had you make folders, type the package line, and compile by hand. Eclipse does all three from one dialog. You are about to rebuild the identical structure — college.exams and college.office — the fast way.
src folder of Unit2Projectcollege.exams — not one folder at a timecollege.officecollege.exams makes both levels at once. Making a package called college and then another called exams gives you two unrelated packages side by side, not one inside the other.Eclipse shows college.exams as one flat row. On disk it is still two nested folders — exactly what you built by hand. The display is a convenience; the structure is unchanged.
Every manual step from Module 6 still happens. Eclipse simply performs each one without telling you.
college.examspackage linejavac -d . path\File.javajava college.office.PaperDemopackage line and something stops working, you now know what it rewrote and what it must match. Without that, the tool is doing something invisible and unfixable.Now that classes live in different packages, a question arises that never came up before: can a class in college.office touch something in college.exams?
Java answers with four levels of access. You have already met two of them without being told their names.
private — only inside this same class. Nothing outside can reach it, not even a subclass. This is the lock you used on the Singleton constructor.protected — same package, plus subclasses anywhere, even in other packages. Inheritance is the only thing that opens the extra door.public — visible everywhere, from any package, to anybody. This is why Paper and show() had to be public in Module 6.Read it top to bottom and the pattern is simple: every level keeps everything the level above allowed, and opens one more column. There are no exceptions to memorise.
One class with all four levels on display, and a second class in a different package trying to reach each of them.
Line 6 has no access word at all. That is the default level — it is a real choice, not an omission.
One line works and three fail. Each for its own reason:
title is public — open to every package, so Clerk reads it freely.code is default — open only inside college.exams. Clerk is in college.office, which is a different package no matter how similar the name looks.marks is protected — the extra door only opens for subclasses. Clerk does not extend Paper, so it gets nothing beyond default.answerKey is private — sealed inside Paper itself. No package, no subclass, no exception.Keep Paper exactly as it was. Change only one detail about the second class: make it a subclass.
Paper changed. marks was refused to Clerk and granted to PracticalPaper, purely because one extends Paper and the other does not. protected is the only modifier whose answer depends on the relationship between the two classes, not just on where they sit.code is still unreachable even here — default access cares only about the package, and college.office is still the wrong one. Inheritance does not help with default.
Access specifiers are the mechanism. Encapsulation is the reason they exist.
It is always the same two moves together. One without the other is not encapsulation:
private, so no outside code can reach it at all.public method that can check, reject, or adjust before anything changes.private String name with getName(). The field was sealed; the method was the door.
private constructor with getInstance(). Same shape applied to object creation instead of to a field — which is why only one object can exist.
A public field seems simpler. Here is what the private-plus-method version buys, in a case you can picture:
The negative deposit never reached balance. No error, no crash — it was simply refused, and the object stayed valid.
Line 7 is the whole argument. With balance public, any line anywhere could write a.balance = -500; and nothing would stop it. Sealed behind deposit(), a negative amount is simply refused — and it is refused for every caller, forever, without any of them having to remember the rule.
setBalance() accepts anything at all, the field is public with extra typing. The checking is the point, not the method.
private fields plus public methods as how it is done. The two questions want the same material pointed in opposite directions.final — the other way to restrictAccess specifiers control who may use something. final controls whether it may be changed. Different question, and the two are often asked together.
final int marks = 70; — any later assignment is refused by the compiler.
String is the famous example — no subclass of String can exist anywhere in Java.
Now try to break each rule. Every one is refused before the program runs:
On a final class, marking methods final as well is redundant — there can be no subclass to override them.
final or protected? Justify your answer."Answer it as two halves, because they solve opposite problems:
final when a value or behaviour must not vary — a constant such as a maximum mark, a method whose logic is a rule rather than a choice, or a class whose correctness depends on nobody altering it.protected when a subclass genuinely needs a member but the wider program must not. It opens one door, for inheritance only.protected and final, and the risk if these are not applied."final classprotected memberWorth stating in the answer: a class cannot itself be protected at the top level — only its members can. Say so and you show you know the boundary, which the question is quietly testing.
protected and final at once?Yes. They answer two different questions, so they never collide.
protected answers "who may see it?" — same package, plus subclasses anywhere.final answers "may it change?" — no, it is set once.Drop the word protected and the field becomes default access. Exactly one row changes:
protected finalfinal alone (default)Paper.marks reached by PracticalPaper in another packageSo the choice is narrow. If subclasses live in other packages and need the value, write protected final. If everything that needs it sits in this package, plain final is enough — and the smaller door is the better habit. final behaves identically either way; only visibility moves.
protected, with or without final — only public or default.An immutable object is one that can never change after it is built.
The word is the intimidating part. The idea is not.
String in Java is immutable. s.toUpperCase() does not change s — it hands you a new string and leaves the old one exactly as it was. That is all immutability means.asha, not ASHA. The uppercase version was made and thrown away, because nothing can alter the original string. Students meet this bug in Unit 1 without being told the word for it.So the question "how do I make a class immutable?" really means: how do I stop anyone changing my object after it is built? There are only three ways in, and the recipe closes all three.
private.final.private and final.final so no subclass can add mutable behaviour.Every route to changing it is closed before the program runs:
private and final, assigned only in the constructor.final, so no subclass can reintroduce change.String as the example. It is immutable, which is why s.concat("x") returns a new string rather than altering s.You have now met all four principles of object-oriented programming. Three came in Unit 1; the fourth was the section above.
abstract class or an interface names reserve() without saying how any particular booking works. Modules 3 and 5.
balance is private; deposit() checks before changing it. This module.
extends. ReserveTrain extends Reservation and gets printReceipt() free. Unit 1, used throughout Unit 2.
Reservation variable holding a train booking runs the train's reserve(). Unit 1, seen again in Modules 3 and 5.
Worth writing out in the answer if time allows — one short program demonstrating every pillar at once.
Four comments mark the four pillars. Booking is abstract and hides how confirming works; paid is private with a checked setter; TrainBooking extends; and a Booking variable runs the train's confirm().
Every field could be public and the program would still run. Access control is not about making things work — it is about what happens next.
private balance can only change through a method that checks the amount first. A public one can be set to minus a million by any line anywhere.private and every class at default. Widen only when something genuinely needs the access, and only as far as it needs. Narrowing later breaks code; widening later never does.Access specifiers exist to serve one idea, and naming it correctly is worth a mark on its own.
Two halves, and both are needed:
private so no outside line can reach them.public methods that can check, adjust or refuse before anything changes.A private balance with a public deposit() that rejects negative amounts is encapsulation. A public balance is not, no matter how many methods sit beside it — because the guard can simply be walked around.
You have been doing this since Module 2 without the name. ClassMonitor hid name and offered getName(); the Singleton hid its constructor and offered getInstance(). Encapsulation is the principle; access specifiers are the tool that enforces it.
private, default, protected, public.privateprotectedpublicOne class showing all four levels, run from inside itself where every one is reachable — then the same fields read from another package, where three are refused.
Then say what changes from outside. Move the reader to another package and only owner still prints — branch, code and pin each fail with "is not visible", for the three different reasons in the table above.
public or default. It cannot be private or protected — those apply to members inside a class.public class must sit in a file of the same name. That is why Paper lives in Paper.java.protected is wider than default, not narrower. It grants everything default grants, then adds subclasses elsewhere.package lineYou copy an old .java file into college.exams using your file manager rather than Eclipse. The file still says nothing about a package, or says the old one.
The fix: add package college.exams; as line 1. Better still, move files with Eclipse's own Refactor → Move, which rewrites the line for you. This is the same mismatch from Module 6, except Eclipse catches it the instant it happens instead of letting it fail at run time.
protected are the sameThey overlap heavily, which is exactly why they get confused. One column separates them.
protectedOne row differs. That row is the entire distinction, and it is exactly what chunk 5 demonstrated: PracticalPaper reached marks from another package because it inherited, and could not reach code for the same reason it never could.
A BankAccount class in package bank.core. Pick the right level for each, and say why in one line.
1. balance — must never be changed except through the class's own methods.
2. deposit() — the whole program, including other packages, must be able to call it.
3. calculateInterest() — subclasses like SavingsAccount in bank.products need it, but nobody else should.
4. AuditLog — a helper class used only by other classes inside bank.core.
private double balance; — sealed inside the class, so every change must go through a method that can check it. This is encapsulation in one word.public void deposit(...) — it is part of the intended interface, so it must be reachable from any package.protected double calculateInterest() — subclasses sit in a different package, so default would refuse them. protected is the only level that opens that one door without opening it to everybody.class AuditLog — no word at all. Default keeps it visible inside bank.core and invisible outside. Note it cannot be private: a top-level class only has public or default available.shop.billing has a field with no access word. Which of these can read it? (a) another class in shop.billing (b) a subclass in shop.staff (c) any class in shopshop.staff is a different package, and inheriting does not help — that is protected's power, not default's. And shop is a different package again: shop and shop.billing are separate, not parent and child in any access sense.private? Answer in two lines.private means "visible only inside the enclosing class". A top-level class has no enclosing class, so private would leave it visible to nothing at all — an unusable class.public or default at the top level. A nested class does have an enclosing class, so there private is legal — which ties back to Module 4.Paper is unchanged from chunk 4.
Examiner is in college.exams, the same package as Paper.Packages are finished. Module 8 opens Exception Handling — the largest topic in the unit.
Everything you have written so far has worked. That is because nothing has been asked to do the impossible yet.
Ask Java to divide by zero and it cannot produce an answer. It has two options: pretend, or stop. It stops — and it tells you exactly why.
src in Package Explorer → New → Package, name it marks, press Finish. Skip this once the package exists.marks package → New → Class.Average in Name, and tick public static void main(String[] args).Ticking the main box matters. Every program in this module is run directly, so each class needs its own main. Forget the tick and you can add it by hand — but the wizard is quicker.
Three things in that output are worth reading carefully:
ArithmeticException: / by zero. Java tells you what went wrong, in words.Average.java:11. Click that in Eclipse and the cursor lands on the exact statement.The words get used loosely in conversation, so here is what each means precisely in Java.
try/catch is useless here — Module 3's "Cannot instantiate" was one of these.Error (the Java class)A run-time problem you cannot sensibly deal with — the JVM running out of memory, for instance. Technically catchable; in practice, leave it alone. Module 9 shows where it sits.Note the word "run time". This is not a compiler error — the program compiled perfectly. Module 3's "Cannot instantiate" was caught before running; this one only appears once it is running with real values.
try and catch — fixing that exact crashYou cannot stop division by zero being impossible. What you can do is tell Java: if this goes wrong, here is what to do instead of stopping.
try holds the risky code. catch holds what to do if it fails. Only one of the two ever runs to completion — either the try finishes, or control jumps to the catch.e is the exception object itself, carrying the message.Compare that with the crash on the last page. Same impossible division, same line. But now Done. printed — the program survived and carried on. That is the entire purpose of exception handling.
Printing your own sentence is friendlier, but it throws away Java's detail. When you want both, use the exception object:
if and print a message?A fair question, and for the small example above the if is genuinely fine. Nobody should throw an exception where a simple check will do.
That works. So the honest answer is not "exceptions are better" — it is that an if stops being enough as soon as one of these three things is true.
return; works. If it returned an int, what would you return on failure? 0 is a real average. -1 is a lie the caller must remember to check for. There is no number that means "this did not work".if can never do.if and printAverage.java — one catch around the divisionResultCard.java — three catches plus finallyThe rule of thumb: use if when this method can handle the problem itself. Throw when it cannot, and somebody further up must be told.
And note what if cannot prevent at all. You can check subjects == 0 because you wrote that line. You cannot write an if in front of every array access in a program, and you certainly cannot check for a problem inside code somebody else wrote. Exceptions catch the failures you did not predict — which is most of them.
catch (Exception e) { } compiles, hides the problem completely, and leaves nobody — including you — any way of knowing something went wrong.
at ... lines are the call stack — which method called which, innermost first. When no catch matches, the exception propagates up that stack, method by method, until something catches it or the program stops. The top line says what went wrong; the lines below say how you got there.catch blocksOne try can go wrong in more than one way, and each way may deserve a different response. You are allowed as many catch blocks after a single try as there are things that can fail.
Because line 10 never ran. Line 9 threw, so the rest of the try was abandoned immediately — the division never happened at all.
This catches people out constantly. A try block does not "run everything and collect the failures". It stops at the first one. To see the second message, you would have to fix line 9 first.
catch (Exception e) first and every later catch becomes unreachable — Eclipse reports "Unreachable catch block". Always list the specific types first and the general one last.
finally — the block that always runsSome work must happen whether things went well or badly. Closing a file, releasing a seat, printing a footer. finally is where that goes.
finally block runs every time — after a successful try, after a catch has handled a failure, even if the method returns from inside the try. If you must be sure something happens, put it here.The first line differs between the two runs. The highlighted line does not. That is finally doing its one job.
Hundreds of exception types exist. Three account for most of what a student actually hits, and all three have appeared already in this module.
10.0 / 0 gives Infinity and throws nothing at all.
ArrayIndexOutOfBounds literally says an array index went out of bounds — the message then tells you which one.try/catch a compile error. Exception handling protects you from run-time problems only. If Eclipse is showing red before you press Run, no amount of catch will help.One try, two catch blocks, one finally. This is the shape the exam asks for, and the shape Module 10's larger questions are built from.
Trace it once and the whole module is in that output:
No new ideas. Just trace the order carefully.
1. Which letters print, and in what order?
2. Which letter never prints, and why?
3. If line 5 were 5 / 1 instead, what would change?
A B D E FF still prints: the program survived, so execution continued past the whole try/catch/finally.5 / 1 nothing throws, so you get A B C E F. C appears and D disappears — the catch is skipped because there was nothing to catch. E prints either way, which is the whole point of finally.Exception is the general type that every exception falls under, so putting it first catches everything — nothing is ever left for the specific block below.Exception last if you want it at all. Java checks top to bottom and takes the first match, so the order you write them is the priority order.try at the top of main and one catch (Exception e) at the bottom. Now nothing ever crashes." What is wrong with that?Module 9 keeps the marks package and adds exception types, throw versus throws, and your own exception classes.
throw vs throws, Custom ExceptionsEvery exception in Module 8 behaved the same way: the program compiled fine, then failed while running. Those are only half the story.
Java splits exceptions into two families, and the difference is not about severity. It is about whether the compiler forces you to deal with it.
RuntimeException is unchecked. Everything else under Exception is checked. That single line of inheritance decides whether the compiler will nag you.Error covers things like running out of memory. They are technically catchable, but there is nothing sensible you could do about them, so leave them alone.
Both families in the diagram trace back to one class: Throwable. It is the only type Java allows after the word throw, and the only type a catch block can name.
Throwable is the root. Nothing can be thrown unless it descends from it. It supplies getMessage() and printStackTrace() — which is why every exception you have met has them.Exception is the branch for problems a program can reasonably recover from. Everything in this unit lives here.Error is the other branch — failures of the machine itself, like StackOverflowError and OutOfMemoryError. Technically catchable; in practice never caught, because nothing sensible can be done about them.Exception misses the top of the tree.catch (Throwable t) in real code. It swallows Error too, so a program out of memory carries on pretending it is fine. It is shown above only to prove the hierarchy. catch (Exception e) is the widest net worth casting.Two marks, so the examiner wants a table and two named examples — not an essay.
Exception, but not RuntimeExceptionRuntimeExceptionIOExceptionArithmeticExceptionThe clearest way to show the difference in an answer is one line of each. The unchecked one compiles; the checked one does not.
If the question says "with examples", a short program scores better than two names alone.
src in Package Explorer → New → Package, name it marks, press Finish. Skip this once the package exists.marks package → New → Class.InvalidMarkException in Name, and tick public static void main(String[] args).One exception to the rule: do not tick main for an exception class. It is never run on its own — it exists to be thrown by other classes. Tick it for MarkEntry and the rest, which do have a main.
The difference is invisible in the output — both were caught and both printed. It shows up in the editor: remove the second try/catch and the file stops compiling, while removing the first changes nothing until the program runs.
IOException and ArithmeticException are enough. An unnamed example scores nothing.throw and throwsOne letter apart, and they do entirely different jobs. This is the most commonly confused pair in the whole topic, so take them one at a time.
throw is an action. It happens right now, on this line, inside a method body. You are creating an exception object and setting it off deliberately. Singular, and always followed by new.throws is a warning label. It sits in the method's signature and tells anyone calling it: "this may fail in that way — be ready." Nothing happens when it runs; it is a declaration, not an action.throwthrowsthrow new InvalidMarkException(...) in the bodyvoid post(int v) throws InvalidMarkException on the signaturethrows at all?
Because line 11 throws a plain Exception, which is checked. Remove throws Exception from line 6 and the compiler refuses to build:
The method has two honest options: handle it internally with its own try/catch, or admit it might escape by declaring throws. It cannot stay silent. Had line 11 thrown an unchecked exception instead, no declaration would be needed — which is the practical consequence of chunk 1's split.
Java's built-in exceptions describe programming faults: bad index, null reference, divide by zero. They have no word for "that admission number does not belong to this college". For rules that belong to your problem, you write your own.
Exception. Give it a constructor that passes a message up to the parent. That is the entire requirement — there is no special syntax to learn.RuntimeException instead and it becomes unchecked.
Exception, which already knows how to store it. That is what makes e.getMessage() work later. Without this line the message is simply lost.
super(m) really needed, or is it just ceremony?It is needed, and here is exactly why. The message is not stored by your class. It is stored by Exception, in a field you cannot reach directly. super(m) is the only way to put it there.
e.getMessage() givessuper(m);nullLeave it out and the class still compiles and still throws — but every message prints as null, which quietly ruins the output of every exam answer. This is the one place in the unit where super genuinely earns its keep; you will not need it anywhere else here.
If you want no message at all, write the class with no constructor whatsoever and throw it bare. That is simpler, and perfectly valid — but then the catch block can only print text you wrote by hand, not the numbers that caused the failure.
Line 20 never ran. Same rule as Module 8 — the throw on line 19 abandoned the rest of the try immediately, so 55 was never recorded.
You could have used IllegalArgumentException and saved a file. Here is what the custom class buys instead.
catch (InvalidMarkException e) tells the next reader exactly which rule was broken. catch (Exception e) tells them nothing.Exception makes the compiler force every caller to deal with it — a rule that matters is not left to memory.The message is built at the moment of failure, so it carries the real number. That is why a custom exception takes a String rather than hard-coding its text — a fixed message could not have said "0 seats left".
Module 8's multiple-catch shape, now with one of your own types alongside a built-in one. This is the pattern Module 10's four-mark questions are built from.
Three things to notice, each a rule from earlier in this unit:
InvalidMarkException block to the one that matched.finally still closed the entry.1. Which word goes in each blank?
InsufficientFundsException class.RuntimeException instead of Exception, what would change?
throws (the label on the method). Line 3 takes throw (the action, followed by new). The giveaway is new — only throw is ever followed by an object.throws would no longer be required, and callers could ignore it entirely — the compiler would stop insisting. For a money rule that is the wrong choice: you want the compiler forcing every caller to think about it.throws and finally.InvalidAgeException, and a method vote(int age) that throws it below 18 and prints a confirmation otherwise. Call it twice from main to show both outcomes.Exception is checked, so the method must either handle it or declare it — it cannot simply throw and stay silent.RuntimeException "so I don't have to write throws everywhere." What is the trade-off they are making?throws clauses, no compiler nagging.Exception and let the compiler enforce it. Reserve RuntimeException for faults that mean the code itself is wrong, which is exactly how Java uses it for NullPointerException.Module 10 answers the five remaining exception questions in full, using the classes built here.
Modules 8 and 9 built the parts separately. This is all of them working at once: a custom exception, a built-in one, multiple catch blocks ordered correctly, throws on the method, and finally closing up.
marks package → New → Class.Office and tick public static void main(String[] args).Six features in one 38-line file: a custom exception, throws, throw, two catch blocks, a built-in exception type, and finally. Every exam question below is a variation on this shape.
Two marks: one sentence of explanation, one short program. Keep it small — a long answer wastes time you need elsewhere.
try can fail in several different ways. Each catch handles one type, Java checks them top to bottom, and runs only the first whose type matches.a[5] = 10 / 0; has a bad index and a division by zero. Java evaluates the right-hand side first, so the division fails before the index is ever used.
Swap it to a[5] = 10 / 2; and the other catch runs instead. Worth mentioning in the answer if you have room — it shows you know only one exception can be thrown at a time.
Four classes, one hierarchy, one custom exception. Plan it before writing: one parent, two children, one exception class.
Why this scores four marks and a simpler answer would not:
issue() is written once in the parent but behaves differently per child, because minimum() is abstract. That is Module 3 doing its job here.Five named exceptions in one program. The trick is knowing which line produces each — write that list before you write any code.
new BankAccount[-2]
list[9] on a array of 3
Object[] that really holds Strings, given a number
try ever runs. Write all five catch blocks, then show two runs with one variable changed, exactly as above. Say in one line that changing size, the index, or the amount triggers each in turn.The new idea here is not the exception — it is the loop. The try/catch sits inside a loop that keeps going until the input is good.
Three details the examiner is looking for:
check(), so a throw skips it and the loop repeats.Three named types, so the program must be able to trigger each one. Drive it from a single variable and show three runs.
One variable, three runs, three different catch blocks — and finally printing on every one. Writing it this way lets a four-mark answer demonstrate all three types without needing three separate programs.
Exception for everythingIt also blocks anything below it — place it first and every specific catch after becomes an unreachable-block error. Catch the narrowest type that fits, and wrap only the lines that can actually fail.
This is worse than the crash it replaces. A crash at least tells you something went wrong; an empty catch hides it and the program carries on as though the work was done.
e.getMessage(). If you genuinely have nothing to do about a failure, that is a sign the exception should be declared with throws and handled by whoever called you.
Say each answer aloud before opening it. If you can name the hinge of each question, you can plan any exception answer in the hall.
Which single idea does each question hinge on?
1. Multiple catch for one try · 2. Insurance hierarchy · 3. BankAccount array
4. Invalid age loop · 5. Three named types · 6. Checked vs unchecked
issue() method serves both children because minimum() is abstract — Module 3 carrying the weight.HealthPolicy whose minimum is 30000, and show the output when it is issued 25000.main:
issue(), no new exception, no new catch block. Adding a policy type costs one method.ArrayStoreException, and why can it not happen in the version shown?list is declared BankAccount[] and only BankAccount objects are ever stored in it. The compiler would reject anything else before the program ran.Object[], and a BankAccount is an Object. Only at run time does Java see the array is really a String[] and refuse. Worth one line in the answer — it shows you know why this exception exists at all.Exception Handling is finished. Module 11 begins Multithreaded Programming with a fresh package.
Every program you have written so far did one thing, then the next, then the next. One line finished before the following line began.
A thread is a second line of execution inside the same program, running at the same time as the first.
Picture a college canteen kitchen.
The table above is the answer; this proves the middle row. Both threads read and change the same plates variable, which two separate processes could never do.
In this run both threads printed 2: each added 1 to the same shared plates, so each saw the other's change too. Another run can print the lines in the other order, or show 1 and 2. Separate processes each get their own copy and would both print 1. That sharing is the convenience — and, from Module 12 onward, the danger.
Threadsrc → New → Package, name it kitchen, press Finish.kitchen → New → Class, name it Cook, tick public static void main(String[] args).Two steps only: say your class is a Thread, and write what it should do inside run().
Because start() does not wait. It hands the work to a new thread and returns straight away, so main reaches line 14 while the cook is still getting going.
Run it a few times. The order may swap. That is not a bug — with two threads running, neither is promised to finish first. Getting comfortable with that uncertainty is most of what this module is for.
start() and everything else Java already wrote.
run().
extends Thread.run() with the work.start() — never run().RunnableSame job, written differently. Instead of being a thread, your class describes work and hands it to a thread.
Line 13 is the only real difference: the work is handed to a Thread, and that thread is started.
extends Threadimplements Runnablec.start()new Thread(w).start()Cook extends ThreadWasher implements RunnableThread and the class can never extend anything else. Runnable costs nothing and leaves that choice open, which is why real code prefers it.One thread proves nothing. Two threads running together show the thing that makes this topic different from everything before it.
Your own output will differ again. Run it five times and note how many distinct orderings you see — that is a better lesson than any explanation.
A thread passes through five states. Each move is caused by a specific event, and naming those events is what the exam question wants.
start() has not been called. It is not running and never will unless you start it.start() has been called. It is ready and waiting for the system to give it a turn.run() is executing now.sleep(), or waiting for something another thread holds. It returns to Runnable when the wait ends.run() finished. The thread is done for good — calling start() again throws an exception.Call run() yourself instead of start() and everything still compiles, still prints, and looks correct. But no thread was ever created.
The output names the culprit. Line 12 printed main — it ran on the main thread, like any ordinary method call. Line 13 printed Thread-1, a genuinely new thread. Printing the thread's name is the quickest way to prove which one you actually got.
1. What does this print, and why is that a trick question?
Runnable over extends Thread?
Chopping onions and done, but either order is possible. start() returns immediately, so line 3 often wins. Any answer claiming one fixed order has missed the point of the module.extends Thread spends the parent and blocks the class from extending anything else. Runnable leaves that free.Server class using Runnable that prints "Serving table" five times. Start two of them from main.run() instead of start(). That is the usual cause of suspiciously tidy output — the work ran on the main thread as an ordinary method call, so of course the order is perfect. No thread was ever created.run():
main, there is no second thread. A real one prints Thread-0, Thread-1 and so on.new Cook() (b) after start() but before it gets a turn (c) during sleep() (d) after run() returnsstart() on it again throws IllegalThreadStateException.Module 12 keeps the kitchen package and gives the cooks one shared thing to fight over.
Module 11 ended on an uncomfortable fact: the order two threads run in is not yours to choose. Java gives you two things that influence it, and it is worth being clear that only one of them actually works.
setPriority(n) — a hint, from 1 to 10. You are suggesting which thread matters more. The system may act on it, or ignore it entirely.Thread.sleep(ms) — sleep() guarantees that this thread pauses for at least that long. It does not decide which thread runs next, so the order can change from run to run.Priority is a hint to the scheduler, not a promise about order.
kitchen package → New → Class, name it Paced, tick public static void main(String[] args).Compare this with Module 11's messy interleaving. Each thread steps aside for 200ms after printing, which spreads the lines out. sleep() guarantees that this thread pauses for at least that long. It does not decide which thread runs next, so the order can change from run to run. The console shows one real run.
a.setPriority(10) and b.setPriority(1) may change the order on your laptop and change nothing in the lab. If your program only works at certain priorities, it is broken — the next chunk shows what actually goes wrong.
sleep() must be wrapped in try/catch because it throws a checked InterruptedException — Module 9's rule, met here in real code for the first time.
You have booked a cinema seat online. So has everyone. Now picture two people tapping seat A4 at the same instant.
Booking a seat is two steps, not one: check whether it is free, then mark it taken. If a second thread checks in the gap between those two steps, it also sees "free".
The pause on line 14 widens the gap between the look and the take, so both threads usually pass line 10 before either reaches line 20. Without the pause the same race still exists, but it shows up rarely — which is exactly what makes these bugs expensive: they pass every test, then happen on a busy Friday evening.
synchronized means only one thread may be inside it at a time. Any other thread that arrives waits at the door until the first one leaves.The look-then-take pair can no longer be split, because a second thread cannot get in halfway.
Two things changed, and only one of them matters:
synchronized on line 8. This is the fix. One thread inside book() at a time, so nobody can look while somebody else is taking.synchronized guards a method, so the two steps that must stay together need to live in one.synchronizedBooking.java — Asha and Ravi both get A4SafeBooking.java — Ravi is told it is goneModule 2 left something open. getInstance() checks whether the monitor exists, and builds one if not — look, then take. The same shape as the seat.
So what happens if two threads call it at the same instant? Both see an empty slot, and both build a monitor. The Singleton quietly stops being single.
One line printed, from two calls. That was already true in Module 2 with a single thread. synchronized is what keeps it true when several threads call at once.
getInstance() is synchronized" is one line that shows you understand the pattern rather than just reciting it — and it connects two syllabus topics, which examiners notice.SafeBooking.book() is thread safe; Booking.run() is not. Saying a method "is thread safe" is the compact way to claim exactly what synchronized bought you.synchronized allows only one thread inside a method at a time; the others wait.One seat, two threads. Remove synchronized from line 6 and both can print got it, leaving seats at −1.
Say in one line that without the keyword the count can go negative. A negative number of seats is the kind of concrete wrongness that earns the second mark.
synchronized is not "safer" — it makes threads queue for no reason, and Module 13 shows how that leads to something worse.Two threads run this. It usually prints 200. Sometimes it prints less.
1. Why can the total come out below 200?
2. What one word fixes it, and where?
3. Would making count final help?
40 before either writes, both write 41 — two increments, one gained. Exactly the seat problem with a number instead of a seat.static synchronized void bump(). One thread completes its whole loop before the other starts, so no read can land between another thread's read and write.final means the value can never change — but the whole point is to change it. final answers "may this change?"; synchronized answers "who may change it, and when?" Different questions, as Module 7 put it.Counter class where two threads each add 1000 to a shared total, safely. Print the total at the end.join() makes main wait for each thread to finish. Without them, main prints the total while the threads are still counting — and you get some number below 2000 for a completely different reason.synchronized." What do you say?synchronized? Explain.Module 13 closes Multithreaded Programming with inter-thread communication and deadlock.
Module 12 stopped two threads colliding. This module handles a different situation: one thread has nothing to do until another thread does something.
A cook makes one plate at a time. A server takes plates away. What should the server do when the counter is empty?
wait() and notify() are for.synchronized method or block. Call one outside and the program compiles, then throws IllegalMonitorStateException the moment it runs.wait() releases a lock, so it must be holding one first. You cannot let go of something you never picked up.kitchen package → New → Class, name it Counter. Leave main unticked — it is shared data, not a program.Canteen, this time with main ticked.Canteen with the green ▶.The counter holds one plate. The cook puts a plate down; the server picks it up. Neither may act when it is the other's turn.
wait(), and stepped aside. The cook then put a plate down and notified. Order is no longer luck — it is the condition deciding.
while on lines 9 and 20, and not if?
Because being notified does not guarantee the condition is still true. Another thread may get in first and take the plate again before this one resumes.
while makes the thread recheck after waking. if checks once and then trusts, which is how this pattern quietly breaks with more than two threads.
Remember it as: wait in a loop, never in an if. It is one word, and it is the difference between code that works with two threads and code that works with any number.
wait() beats checking in a loopA server could just keep asking "is there a plate?" forever. Here is what stepping aside buys instead.
wait() lets go, so the other thread can actually get in and change the thing being waited for. A spin loop inside synchronized would hold the door shut and wait forever.notify() tells the waiting thread the moment something changes, rather than up to a whole polling interval later.while (empty) wait(); says plainly what the thread needs. A spin loop says only that it is busy.synchronized alone is enough — wait() and notify() add machinery you would not need.wait() and notify(). Checking in a loop instead of waiting is called busy waiting or spinning. Both names are worth using in an answer.Two cooks. One knife, one chopping board. Each needs both to work.
Read the output carefully. This is the signature of a deadlock:
Two words swapped, and the program finishes. Whoever gets the knife first now holds it until done, and the other waits its turn rather than holding something hostage.
Everything that goes wrong with threads in this unit is one of these four. Each has a symptom you can recognise without a debugger.
Thread.currentThread().getName() — if it says main, there is your answer. Module 11.
synchronized blocks in opposite orders. This module.
wait() should sit inside a while. This module.
synchronizedBooking.java — the double bookingStuck.java — the knife and the boardThe pairing worth remembering: the fix for one is the cause of the other. Lock too little and data breaks; lock too much, carelessly, and everything stops. Threads are the art of locking exactly enough.
Say each answer aloud before opening it. If you can name the symptom, you can diagnose any threading question in the hall.
1. A program prints two lines then stops responding, with no error. What is wrong, and what is the fix?
2. A counter should reach 2000 and prints 1997. Which of the four mistakes is it?
3. Explain a race condition and a deadlock to a classmate in one sentence each, using our two examples.
synchronized. Not deadlock — the program finished. count = count + 1 is read, add, write; two threads read the same value and one increment is lost. Three lost here.IllegalMonitorStateException the moment it runs. Why, and what is the one-word fix?
synchronized. wait() releases the lock the thread is holding — but this thread never took one, so there is nothing to release.A and B. One transfers A→B, the other B→A, and each locks the source account then the destination. What happens, and how would you fix it without removing either lock?Every syllabus topic in Unit 2 is now covered. Module 14 recaps the unit; Module 15 is a timed self-test.
synchronized is what keeps it single when threads call at once.new Reservation() is a compile error.c.new Principal() — read it as "ask c to make me a Principal".package line must match the folder path exactly.privateprotectedpublicfinal = cannot change. A top-level class may only be public or default.throw is the action, inside the body. throws is the label, on the signature. Checked = the compiler insists; unchecked = it stays quiet.synchronized and one agreed lock order.Thirteen modules produced one Eclipse project with nine packages. This is the whole of it in one place.
The same four moves produced every file above. Worth having them in one place.
src → New → Package. Type the full dotted name — college.exams, not one level at a time.Unit2Project → Export → General → Archive File gives you a single zip of everything. Import it on any machine with File → Import → Existing Projects into Workspace. Worth doing before the exam — a lab machine being reimaged is not a good day to discover this.Module 6's manual route, in case you are ever on a machine without an IDE.
javac takes a file path with backslashes and .java. java takes a class name with dots and no extension. Run both from the folder above the package.
Employee. It must also be printable and saveable. Can it be? Explain in one sentence, and write the class header.Paper is in college.exams with a protected int marks. Which of these can read it? (a) another class in college.exams (b) a subclass in college.office (c) an unrelated class in college.officeprivate. Anyone can still write new Registrar() and get a second one, so the slot and the method achieve nothing.private Registrar() { }. All three pieces are needed together — one slot, a locked door, one official way in.getInstance() should also be synchronized, or two threads calling at once can both pass line 9. Modules 2 and 12.abstract itself.Employee and the two capabilities cost nothing.
extends comes first, then implements, interfaces comma-separated. Module 5.protectedprotected includes everything default allows.protected opens that default does not.A D EArrayIndexOutOfBoundsException, so B never prints — the rest of the try is abandoned.ArithmeticException, which does not match, so C is skipped. The second catches Exception, which every exception falls under, so D prints.finally. Module 8.throw or throwsthrows. It is a label on the method signature, warning callers this may fail that way.throw. It is the action, happening now, inside the body.new: only throw is ever followed by an object. throws is followed by a type. Module 9.Throwable and splits into Error and Exceptionextends Exception, and super(message) because the language requires itjoin()synchronizedEvery previous-year question landed in this unit, with the shape of a full-mark answer and where the worked version lives.
getInstance(). Show the same object returned twice with a == b printing true.abstract void reserve() plus one shared concrete method. Two subclasses each writing reserve(). A driver holding both in Reservation variables, with output.public or default.final when a value or behaviour must not vary; protected when subclasses need access but the wider program must not. Both narrow what the rest of the program can do.protected — only its members can. That boundary is what the question is testing.private final, set in the constructor; no setters; class final. Name String as the example.IOException and ArithmeticException. Unnamed examples score nothing.finally prints on every one.extends Thread, override run(), create an object, call start() — never run(). Show the output and note the order may vary.synchronized admits one at a time; two users booking one seat.You started with an empty Eclipse workspace. You now have a project of forty-four files covering every syllabus item, and you have seen each of the eighteen exam questions answered with a program that actually runs. Nothing here was described to you without being shown.
Every module stays open. The three worth returning to before an exam are Module 14 for the one-card-per-topic revision, Module 10 for the exception programs, and Module 13 for the race-versus-deadlock distinction that separates a good answer from a full one.
Terms are listed in the order you meet them. Each says where it is taught, so you can jump back to the module if the one-line version isn't enough.
new.Unit 1== tests.Unit 1main and run the classes you actually want to demonstrate.Unit 1static field exists once, shared by everything.Module 2static. Needs no outer object, and cannot read the outer object's fields.Module 4static. Tied to one particular outer object, and can read its private data.Module 4};.Module 4InterfaceName.method(), never inherited.Module 5package line in a file must match the folder it sits in.Module 6college.exams.Paper, not just Paper.Module 6javac produces — the .class file. Not readable by you, and not machine code either; it is what Java runs.Module 6private, default, protected, or public.Module 7.java source into .class bytecode.Module 6main tickbox in the New Class wizard.Module 2