0% found this document useful (0 votes)
2 views29 pages

Java Exam Notes

This document provides comprehensive notes on Java programming, covering its overview, differences from C++, history, installation of the JDK, and key features. It emphasizes Java's design goals of platform independence, memory safety, and automatic memory management, while also detailing the architecture of Java and its data types. The notes serve as a study guide for understanding Java's principles and preparing for exams.

Uploaded by

kesarsingh4107
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views29 pages

Java Exam Notes

This document provides comprehensive notes on Java programming, covering its overview, differences from C++, history, installation of the JDK, and key features. It emphasizes Java's design goals of platform independence, memory safety, and automatic memory management, while also detailing the architecture of Java and its data types. The notes serve as a study guide for understanding Java's principles and preparing for exams.

Uploaded by

kesarsingh4107
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

JAVA PROGRAMMING

Concept-First Exam Notes

A theory + code companion built to build genuine understanding —


not memorisation.
1. Overview of Java
Java is a general-purpose, class-based, object-oriented programming language designed to have as few
implementation dependencies as possible. The single biggest idea behind Java is captured in Sun Microsystems'
original slogan: "Write Once, Run Anywhere" (WORA). A programmer writes code once, compiles it into an
intermediate form, and that same compiled output runs unmodified on any device that has a Java Virtual
Machine — Windows, Linux, macOS, or embedded hardware.

Instead of memorising that Java is "portable, robust, secure, etc.", understand WHY each property exists. Every
feature of Java traces back to a design decision made to solve a real problem C and C++ had. Keep asking yourself
"what problem does this solve?" as you read — that's what will let you write original exam answers instead of
recalled lists.

Why Java was needed


•​ C and C++ compile directly to machine code for one specific CPU/OS combination — a program compiled
for Windows x86 will not run on a Mac. This is called being platform-dependent.
•​ C++ gives direct memory access via pointers, which is fast but dangerous — a wrong pointer can crash the
system or open a security hole.
•​ C/C++ require the programmer to manually free memory (free()/delete). Forgetting to do this causes
memory leaks; a large, long-running program (think embedded consumer devices, which is literally what
Java was invented for) cannot tolerate this.
Java's entire design — bytecode, the JVM, automatic garbage collection, no pointer arithmetic — is a direct
response to these three problems. That is the single narrative to hold in your head for this whole unit.

💡 Exam tip: If an exam question asks "why was Java developed" or "give the objectives of Java", structure your answer
around: platform independence, memory safety (no manual pointers), and automatic memory management (garbage
collection). Everything else is a supporting detail.

2. Difference between C++ and Java


Both are object-oriented and share C-like syntax (curly braces, semicolons, similar keywords), which is why
comparison questions are common. The differences all follow from Java choosing safety and portability over raw
low-level control.

Aspect C++ Java

Platform Compiles to native machine code; Compiles to bytecode; runs on any JVM
dependency platform-dependent — platform-independent

Memory Manual (new/delete, malloc/free); Automatic Garbage Collection reclaims


management programmer manages the heap unused objects

Pointers Explicit pointers and pointer arithmetic No pointer arithmetic exposed to the
allowed programmer (references are used
internally, safely)
Aspect C++ Java

Multiple Supported directly for classes (can cause Not supported for classes; achieved
inheritance the Diamond Problem) safely via interfaces

Compilation Source compiled straight to machine Source compiled to bytecode (.class),


code (.exe) then interpreted/JIT-compiled by the JVM

Operator Supported Not supported (kept out to reduce


overloading complexity/ambiguity)

Header files Uses header files (#include) Uses packages and import statements

Global Allowed outside classes Everything must be inside a class (except


variables/functions a few edge cases)

Goto statement Present Removed (reserved but unused keyword)

Thread/Exception Not built into the language core (library Built into the language itself
support dependent) ([Link], try-catch as core
syntax)

💡 Exam tip: A favourite one-line exam answer: "C++ compiles to platform-specific machine code, while Java compiles to
platform-independent bytecode executed by the JVM." This single sentence explains almost every other difference in the
table.

3. History of Java
Understanding the story makes the dates stick automatically — you won't need to rote-learn them.

•​ 1991 — James Gosling, along with Mike Sheridan and Patrick Naughton at Sun Microsystems, started a
project called the Green Project. Their goal was to build software for consumer electronics — TVs, set-top
boxes, toasters. These devices used many different, incompatible CPU chips.
•​ Naming — The language was first called Oak (after a tree outside Gosling's office), then renamed Green,
and finally Java — reportedly inspired by Java coffee.
•​ The core insight — Because consumer electronics used so many different processors, the team designed a
language that compiled to an intermediate, machine-independent format (bytecode), interpreted at
runtime by a small piece of software (the interpreter/VM) written specifically for each device. This is
precisely the portability model Java still uses today, just repurposed later for the Internet.
•​ 1995 — Java 1.0 was formally released to the public by Sun Microsystems, right as the World Wide Web
was exploding — the WORA idea turned out to be perfect for a web where an applet needed to run inside
any user's browser on any operating system.
•​ 2009–2010 — Sun Microsystems was acquired by Oracle Corporation, which owns and maintains Java
today.
•​ Modern releases — Java now follows a fast six-month release cycle (Java 9 onward) with Long-Term
Support (LTS) versions such as Java 8, 11, 17, and 21 being the ones most commonly used in industry.
💡 Exam tip: If asked "who is the father of Java" — James Gosling. If asked the original name — Oak. These two one-liners
cover most rote-recall questions on history.
4. Installation of JDK
JDK = Java Development Kit. It is the full package a developer needs to write, compile, and run Java programs (as
opposed to the JRE, which only runs them — covered in section 6).

Conceptual steps (works the same on Windows/Linux/macOS)


•​ Download the JDK installer for your OS from Oracle's site or an open-source distribution such as Eclipse
Temurin (OpenJDK).
•​ Run the installer, which places files such as javac (compiler), java (launcher), jar, javadoc, etc. into a bin
folder, e.g. C:\Program Files\Java\jdk-21\bin.
•​ Set the JAVA_HOME environment variable to point to the JDK install directory, and add %JAVA_HOME%\bin
(or $JAVA_HOME/bin on Linux/macOS) to the system PATH variable, so the java and javac commands can
be typed from any terminal location.
•​ Verify the installation from a terminal/command prompt:
javac -version
java -version

Compiling and running your first program


// File name MUST match the public class name: [Link]
public class HelloWorld {
public static void main(String[] args) {
[Link]("Hello, World!");
}
}

From the terminal, in the same folder:


javac [Link] // compiles source -> [Link] (bytecode)
java HelloWorld // JVM loads the .class file and executes it

💡 Exam tip: Exam questions sometimes ask to explain each step above with reasons — javac converts .java
(human-readable source) into .class (bytecode); java then launches the JVM which interprets/JIT-compiles that bytecode
into native instructions and runs it.

5. Features of JDK
The JDK is a superset — it contains everything needed to develop AND run Java applications.

•​ Compiler (javac): converts .java source files into .class bytecode files.
•​ JRE (bundled inside): provides the runtime environment (JVM + core libraries) so compiled code can
actually execute.
•​ Interpreter/Loader (java command): launches the JVM and runs the bytecode.
•​ Debugger (jdb): lets developers step through code, inspect variables, and set breakpoints.
•​ Archiver (jar): packages multiple .class files (and resources) into a single distributable .jar file.
•​ Documentation generator (javadoc): auto-generates HTML API documentation from specially formatted
comments in the source code.
•​ Additional development tools: javap (class file disassembler), jconsole/jvisualvm (monitoring), and others
depending on JDK version.
💡 Exam tip: A clean one-line definition to reproduce: "JDK = JRE + development tools (compiler, debugger, etc.) required to
write and compile Java programs."

6. Difference between JDK and JRE (and JVM)


This trio is one of the most frequently asked theory questions. The cleanest way to hold it in memory is as three
nested boxes, each one bigger than the last:

•​ JVM (innermost) — Java Virtual Machine. An abstract computing engine that actually executes bytecode. It
performs class loading, bytecode verification, memory management (the heap, garbage collection), and
just-in-time compilation to native machine code. The JVM is what makes Java platform-independent —
every OS has its own JVM implementation, but all of them understand the same bytecode.
•​ JRE (middle box) — Java Runtime Environment = JVM + core class libraries ([Link], [Link], [Link], etc.)
+ supporting files. This is everything an end user needs to simply RUN an existing Java application — no
development tools included.
•​ JDK (outer box) — Java Development Kit = JRE + development tools (javac, jar, javadoc, debugger). This is
what a programmer installs to WRITE and COMPILE Java programs.

Feature JVM JRE JDK

Full form Java Virtual Machine Java Runtime Java Development Kit
Environment

Purpose Executes bytecode Provides environment Provides environment to


to run Java apps develop + run Java apps

Contains Class loader, bytecode JVM + core libraries JRE + compiler, debugger,
verifier, execution other dev tools
engine

Who needs it Used internally by JRE End users running Java Developers writing Java
apps apps

Platform independent? Implementation is Platform-specific Platform-specific package


platform-specific, but package
abstract spec is
common

💡 Exam tip: Draw the nested-boxes diagram (JDK ⊃ JRE ⊃ JVM) in the exam — markers give credit for the diagram even
before you write a word.

7. Architecture of Java — Portability


This is the mechanism behind "Write Once, Run Anywhere", and it is worth understanding step by step rather
than remembering as a diagram.

The journey of a Java program


•​ 1. Source code (.java) — you write human-readable code following Java syntax.
•​ 2. Compilation (javac) — the Java compiler does NOT produce machine code for a specific CPU (unlike
C++). Instead it produces bytecode (.class file) — a fixed, platform-neutral instruction set designed for the
JVM.
•​ 3. Class loading — when you run java ClassName, the JVM's Class Loader subsystem locates the .class file
and loads it into memory.
•​ 4. Bytecode verification — the Bytecode Verifier checks the loaded code for illegal operations (stack
overflows, illegal type casts, access violations) before execution — this is a security layer that plain
compiled C/C++ machine code has no equivalent of.
•​ 5. Execution engine — this interprets bytecode line-by-line, AND simultaneously a Just-In-Time (JIT)
compiler identifies frequently executed ("hot") code and compiles that portion directly into native machine
code for speed. This is why Java gets the safety of interpretation with performance close to compiled
languages.
Because the .class bytecode file itself never changes across platforms, and only the JVM implementation differs
per OS, the exact same .class file runs identically on Windows, Linux, and macOS. This is the literal mechanism of
platform independence — not a marketing claim.
[Link] (source code - human readable)
|
| javac (compiler)
v
[Link] (bytecode - platform independent)
|
| java (launches JVM)
v
---------------------------------------------------
| JVM (different native implementation per OS) |
| Class Loader -> Bytecode Verifier -> Execution |
| Engine (Interpreter + JIT Compiler) |
---------------------------------------------------
|
v
Native machine instructions run on Windows / Linux / Mac

💡 Exam tip: A commonly asked exact-wording question is "Explain the JVM architecture." Mention these subsystems by
name in order: Class Loader Subsystem → Runtime Data Areas (Method Area, Heap, Stack, PC Register, Native Method
Stack) → Execution Engine (Interpreter + JIT + Garbage Collector).

8. Features of Java
Rather than memorising a list, tie every feature back to the C++ problems from Section 1 — that connection is
what an examiner is really testing.
Feature What it means Why it matters

Simple Removed complex C++ features: no Shorter learning curve, fewer subtle
pointers, no operator overloading, no bugs
multiple class inheritance, automatic
memory management

Object-Oriented Almost everything is an object; based on Promotes modular, reusable,


classes, encapsulation, inheritance, maintainable code
polymorphism

Platform Source compiles to bytecode, not native "Write Once, Run Anywhere"
Independent machine code

Secure No explicit pointers, bytecode verifier, Untrusted code (e.g. from the web)
class loader, security manager, runs can't easily access memory or the local
inside a JVM sandbox filesystem

Robust Strong compile-time type checking, Fewer crashes; the compiler catches
automatic garbage collection, mandatory many bugs before runtime
exception handling

Architecture-neutral Data type sizes (int, long, etc.) are fixed Same numeric behaviour on every
by spec, not by hardware machine

Portable No implementation-dependent aspects; Consequence of architecture neutrality


bytecode + fixed data type sizes travel + platform independence
unchanged

Multithreaded Built-in support for concurrent execution Efficient use of CPU; responsive
via the Thread class / Runnable interface applications

Interpreted (and Bytecode is interpreted by the JVM, with Balances startup speed and runtime
compiled) JIT compiling hot paths to native code performance

High Performance JIT compilation brings speed close to Removes most of the historical "Java is
natively compiled languages slow" criticism

Distributed Rich networking libraries ([Link]), RMI, Was designed with the Internet age in
support building networked/distributed mind
applications easily

Dynamic Classes are loaded on demand at Can adapt to an evolving runtime


runtime; supports reflection environment

💡 Exam tip: A very common one-mark/two-mark question is simply "List the features of Java." The mnemonic
S-O-P-S-R-A-P-M-I-H-D-D (Simple, OOP, Platform independent, Secure, Robust, Architecture-neutral, Portable,
Multithreaded, Interpreted, High performance, Distributed, Dynamic) can help, but understanding the table above means
you never truly forget it.
9. Data Types in Java
Java is a strongly, statically typed language — every variable's type is known and checked at compile time. Data
types split into two fundamentally different categories, and this distinction underlies almost every later topic
(parameter passing, the String pool, object references, etc.).

9.1 Primitive data types (8 total)


Primitives store the actual value directly in the memory location (usually stack memory for local variables). They
are NOT objects, have no methods, and their size is fixed by the Java specification regardless of OS/hardware
(this is the 'architecture-neutral' feature from Section 8 in action).

Type Size Default Range / Notes

byte 1 byte 0 -128 to 127; used to save memory in large arrays

short 2 bytes 0 -32,768 to 32,767

int 4 bytes 0 -2,147,483,648 to 2,147,483,647; the default


choice for whole numbers

long 8 bytes 0L Very large integers; literal needs an 'L' suffix, e.g.
10000000000L

float 4 bytes 0.0f Single precision decimal; literal needs an 'f' suffix

double 8 bytes 0.0d Double precision decimal; default type for


decimal literals

char 2 bytes '\u0000' A single Unicode character (unsigned) — note: 2


bytes, unlike C's 1 byte, because Java supports
Unicode

boolean 1 bit false Only true or false; not interchangeable with 0/1
(JVM-dependent) like in C

9.2 Non-primitive (reference) data types


Reference types — classes, interfaces, arrays, String — do not store the value directly. A reference variable stores
the memory address (reference) of an object that actually lives on the heap. This distinction (value on stack vs
pointer-to-heap-object) is exactly what governs 'pass by value' behaviour for objects, discussed in Section 14.
int x = 10; // x directly holds the value 10 (stack)

String s = new String("Hi"); // s holds a REFERENCE; the actual


// String object lives on the heap

💡 Exam tip: Classic exam trap: 'Is Java pass-by-value or pass-by-reference?' Correct answer: Java is ALWAYS pass-by-value.
For objects, the value being copied is the reference (address) itself — so the caller and callee point at the same object, but
the reference variable itself is still copied, not shared. See Section 14 for a worked example.

10. Variables in Java


A variable is a named piece of memory that holds a value of a specific data type. Every variable in Java must be
declared with a type before use (static typing).
int age = 20; // declaration + initialization
String name; // declaration only
name = "Riya"; // assignment

10.1 Types of variables (and their scope / lifetime)


This is the classic 'scope and lifetime' theory question — three kinds of variables, distinguished by WHERE they
are declared:

(a) Local variables


•​ Declared inside a method, constructor, or block (including for-loop headers, if-blocks, etc.).
•​ Scope: only within that method/block — cannot be accessed outside it.
•​ Lifetime: created when the method is invoked (pushed onto the stack frame), destroyed the moment the
method returns/block exits.
•​ Must be explicitly initialized before use — local variables have NO default value, and the compiler will
throw an error if you try to use one before assigning it.

(b) Instance variables (non-static fields)


•​ Declared inside a class but OUTSIDE any method — one copy is created per object.
•​ Scope: accessible throughout the class (and outside via object reference, subject to access modifiers).
•​ Lifetime: created when the object is created (new), destroyed when the object becomes eligible for
garbage collection.
•​ Automatically initialized to a default value (0, null, false, etc.) if not set explicitly.

(c) Static variables (class variables)


•​ Declared with the static keyword inside a class, outside any method.
•​ Scope: shared across ALL objects of the class — only ONE copy exists in memory regardless of how many
objects are created.
•​ Lifetime: created when the class is first loaded by the JVM, destroyed when the program/class unloads — it
exists independent of any object.
class Counter {
static int count = 0; // static: shared by every object
int id; // instance: unique per object

Counter() {
count++; // increments the SAME variable for all objects
id = count; // each object gets its own id
}

void show() {
int local = 5; // local: exists only during this call
[Link]("id=" + id + " count=" + count);
}
}

public class Test {


public static void main(String[] args) {
Counter c1 = new Counter(); // id=1, count=1
Counter c2 = new Counter(); // id=2, count=2
[Link](); // id=1 count=2
[Link](); // id=2 count=2 <-- count is shared!
}
}

💡 Exam tip: A great differentiator sentence for exams: 'Instance variables get a separate copy per object; static variables
get exactly one copy shared by the whole class; local variables live and die within a single method call.'

11. Class and Objects

11.1 What is a class?


A class is a user-defined blueprint or template that defines the properties (fields/variables) and behaviours
(methods) that objects of that type will have. A class itself does not occupy memory for its data — it's a
specification, like an architectural blueprint of a house, not the house itself.

11.2 What is an object?


An object is a runtime instance of a class — the actual 'house' built from the blueprint. Every object has three
defining characteristics: state (the values held in its fields), behaviour (what methods it can perform), and
identity (a unique reference distinguishing it from every other object, even one with identical state).
class Car {
String color; // state
int speed;

void accelerate() { // behaviour


speed += 10;
}
}

public class Demo {


public static void main(String[] args) {
Car myCar = new Car(); // object created on the heap
[Link] = "Red"; // set state
[Link](); // invoke behaviour
[Link]([Link] + " " + [Link]);
}
}

💡 Exam tip: Exam phrasing to reuse: 'A class is a logical construct; an object is a physical reality that exists in memory (on
the heap) at runtime.'

12. Object-Oriented Programming: Meaning and Features


Object-Oriented Programming (OOP) is a programming paradigm built around the idea of bundling data and the
functions that operate on that data into a single unit called an object — instead of writing a program as a
sequence of instructions acting on separate data (the old procedural style used in C).

The four pillars of OOP


1. Encapsulation
Wrapping data (fields) and the methods that operate on that data into a single unit (class), while restricting
direct outside access to the internal state — usually by making fields private and exposing controlled access
through public getter/setter methods. This protects an object's internal consistency (nobody can set an invalid
value directly) and hides implementation details, so the internal logic can change later without breaking code
that uses the class.
class BankAccount {
private double balance; // hidden from outside

public void deposit(double amt) {


if (amt > 0) balance += amt; // validation enforced here
}
public double getBalance() {
return balance;
}
}

2. Abstraction
Showing only the essential features of an object while hiding the complex internal implementation. When you
call [Link](item), you don't need to know HOW the list resizes its internal array — you only see the 'what', not
the 'how'. Achieved in Java via abstract classes and interfaces.

3. Inheritance
A mechanism where one class (child/subclass) acquires the fields and methods of another class
(parent/superclass), enabling code reuse and establishing an 'is-a' relationship. Covered fully in Section 17.

4. Polymorphism
The ability of the same method name/reference to take multiple forms depending on context ('poly' = many,
'morph' = forms). Covered fully in Section 18.

💡 Exam tip: Standard exam definition to reproduce: 'OOP is a programming approach based on the concept of objects,
which combine data and behaviour, and is built on four pillars: Encapsulation, Abstraction, Inheritance, and Polymorphism.'
Always give the four pillars with one line each — this is the single most repeated theory question in any Java paper.

13. Assigning Object Reference Variables


Because objects live on the heap and variables hold references (Section 9.2), assigning one object reference
variable to another does NOT copy the object — it copies the address, so both variables now point to the SAME
object in memory.
class Point {
int x, y;
}

public class RefDemo {


public static void main(String[] args) {
Point p1 = new Point();
p1.x = 10;

Point p2 = p1; // p2 now points to the SAME object as p1


p2.x = 99; // modifies the shared object

[Link](p1.x); // prints 99, NOT 10!


[Link](p1 == p2); // true - same reference
}
}

If instead you wanted p2 to be an independent copy, you would need to explicitly create a new object and copy
field values (or implement Cloneable / a copy constructor) — simple assignment (=) never does this for objects.

💡 Exam tip: A very common 'find the output' question exploits exactly this behaviour. Always ask: 'is this a primitive (value
copied) or an object reference (address copied)?' before predicting output.

14. Methods — Parameters and Return Types


A method is a named block of code that performs a task and can be invoked/called. General syntax:
accessModifier returnType methodName(parameterType paramName, ...) {
// body
return value; // omitted if returnType is void
}

14.1 Passing different parameter types


Java is strictly pass-by-value — always. What differs between primitives and objects is WHAT value gets copied.

•​ Primitive arguments: a fresh copy of the actual value is passed. Changes made to the parameter inside the
method do NOT affect the caller's original variable.
•​ Object arguments: a copy of the reference (address) is passed. The method's local reference variable and
the caller's variable now point at the SAME heap object, so changes made THROUGH that reference (e.g.,
modifying a field) DO reflect back — but reassigning the parameter to a brand-new object inside the
method does NOT affect the caller's original reference.
static void changePrimitive(int n) {
n = 999; // only the local copy changes
}

static void changeObjectField(Point p) {


p.x = 999; // modifies the SHARED object -> visible outside
}

static void reassignObject(Point p) {


p = new Point(); // p now points elsewhere; caller's reference unaffected
}
public static void main(String[] args) {
int a = 5;
changePrimitive(a);
[Link](a); // 5 (unchanged)

Point pt = new Point();


pt.x = 1;
changeObjectField(pt);
[Link](pt.x); // 999 (changed!)

reassignObject(pt);
[Link](pt.x); // still 999 (reassignment inside method didn't leak out)
}

14.2 Methods with different return types


// returns nothing
void printMessage() {
[Link]("Hello");
}

// returns a primitive
int square(int n) {
return n * n;
}

// returns an object
String greet(String name) {
return "Hello, " + name;
}

// returns an array
int[] getEvenNumbers() {
return new int[]{2, 4, 6, 8};
}

14.3 Variable arguments (varargs) and default/overloaded parameters


Java doesn't support default parameter values (unlike C++/Python), but it does support varargs — a method that
accepts a variable number of arguments of the same type, using triple-dot syntax:
static int sum(int... nums) { // can be called as sum(), sum(1,2), sum(1,2,3)...
int total = 0;
for (int n : nums) total += n;
return total;
}

💡 Exam tip: Best exam one-liner: 'Java always passes by value. For object references, the value copied is the address itself,
which is why field modifications through a passed object are visible to the caller, but reassigning the parameter is not.'

15. Constructors
A constructor is a special block of code, syntactically resembling a method, that is automatically invoked when an
object is created with new. Its job is to initialize the object's state.

15.1 Rules for constructors


•​ Must have the SAME name as the class.
•​ Has NO return type — not even void (this is what distinguishes it from a method, even a method that
happens to share the class's name).
•​ Can be overloaded (multiple constructors with different parameter lists) — this is called constructor
overloading.
•​ If you write NO constructor at all, the compiler automatically supplies a no-argument 'default constructor'.
The moment you write even one constructor yourself, that automatic default constructor disappears.

15.2 Types of constructors


class Student {
String name;
int age;

// 1. Default (no-argument) constructor - written explicitly here


Student() {
name = "Unknown";
age = 0;
}

// 2. Parameterized constructor
Student(String n, int a) {
name = n;
age = a;
}

// 3. Copy constructor (Java has no built-in one like C++; we write our own)
Student(Student other) {
[Link] = [Link];
[Link] = [Link];
}
}

public class Test {


public static void main(String[] args) {
Student s1 = new Student(); // calls default constructor
Student s2 = new Student("Amit", 21); // calls parameterized constructor
Student s3 = new Student(s2); // calls copy constructor
}
}

15.3 Constructor chaining with this()


One constructor of a class can call another constructor of the SAME class using this(...), avoiding duplicated
initialization code:
class Box {
int l, b, h;
Box() {
this(1, 1, 1); // calls the 3-arg constructor below
}
Box(int side) {
this(side, side, side);
}
Box(int l, int b, int h) {
this.l = l; this.b = b; this.h = h;
}
}

💡 Exam tip: Important restriction: this() must be the FIRST statement in a constructor, and you cannot form a circular chain
(constructor A calling B calling back to A).

16. this and super Keywords

16.1 the 'this' keyword


'this' is a reference to the CURRENT object — the object on which the currently executing method/constructor
was invoked. Common uses:

•​ Disambiguating instance fields from parameters with the same name (this.x = x).
•​ Invoking another constructor of the same class — constructor chaining (this(...), Section 15.3).
•​ Passing the current object as an argument to another method (someMethod(this)).
•​ Returning the current object from a method, to support method chaining (return this;).
class Employee {
int id;
Employee(int id) {
[Link] = id; // '[Link]' = field, plain 'id' = parameter
}
}

16.2 the 'super' keyword


'super' refers to the immediate PARENT class object/context. It is the counterpart of 'this', but reaching one level
up the inheritance chain. Common uses:

•​ [Link] — access a field of the parent class that has been hidden/shadowed by a same-named field
in the child class.
•​ [Link]() — explicitly call the parent class's version of a method that the child has overridden.
•​ super(...) — call the parent class's constructor; like this(), it must be the FIRST statement in a constructor. If
you don't write it, Java automatically inserts a call to the parent's no-arg constructor.
class Animal {
String type = "Animal";
Animal() { [Link]("Animal constructor"); }
void sound() { [Link]("Some generic sound"); }
}
class Dog extends Animal {
String type = "Dog";
Dog() {
super(); // explicit call to Animal() - optional here, added by
compiler anyway
[Link]("Dog constructor");
}
void sound() {
[Link](); // calls Animal's version first
[Link]("Bark");
}
void printTypes() {
[Link]([Link]); // Dog
[Link]([Link]); // Animal
}
}

this super

Refers to the current class's own object Refers to the immediate parent class's part of the
object

Used to call a sibling constructor of the same class Used to call a constructor of the parent class

Resolves ambiguity between fields/params in the Resolves hiding/overriding between parent and child
same class members

💡 Exam tip: Both this() and super() must be the FIRST line of a constructor, and a constructor cannot contain both — only
one or the other.

17. Garbage Collection


In C/C++, the programmer manually frees heap memory. Forgetting to do so causes a memory leak; freeing
memory that's still in use causes a dangling pointer / crash. Java's Garbage Collector (GC) removes this entire
class of bugs by automatically reclaiming memory occupied by objects that are no longer reachable/usable by
the program.

17.1 How an object becomes eligible for GC


•​ Nulling a reference: obj = null; — if no other variable references that object, it becomes eligible.
•​ Reassigning the reference to point elsewhere: obj = new SomeObject(); — the old object, if unreferenced
elsewhere, becomes eligible.
•​ An object created entirely inside a method with no reference escaping the method becomes eligible the
moment the method returns (its local variable goes out of scope).
•​ Island of isolation: two or more objects reference only each other, but nothing from the live program
references any of them — all become eligible together.

17.2 How GC actually runs


The GC runs on a separate, low-priority daemon thread managed automatically by the JVM. You (the
programmer) cannot force immediate collection — you can only REQUEST it via [Link](), which is merely a
hint the JVM is free to ignore. Most JVMs use a generational strategy: new objects are allocated in a 'Young
Generation'; objects that survive several collection cycles get promoted to an 'Old Generation', which is collected
less frequently since long-lived objects are statistically less likely to become garbage soon.
class Demo {
protected void finalize() { // deprecated since Java 9, shown for concept only
[Link]("Object being garbage collected");
}
}

public class GCTest {


public static void main(String[] args) {
Demo d = new Demo();
d = null; // object now unreachable -> eligible for GC
[Link](); // REQUEST garbage collection (not guaranteed to run
immediately)
}
}

💡 Exam tip: Key exam distinction: '[Link]() only suggests garbage collection to the JVM; it does not guarantee it will
run.' Also remember finalize() is deprecated in modern Java — mention this if asked about it, it shows currency of
knowledge.

18. Inheritance
Inheritance lets a new class (subclass/derived/child) reuse fields and methods of an existing class
(superclass/base/parent), using the extends keyword. It models an 'IS-A' relationship — e.g., a Dog IS-A Animal.
class Animal {
void eat() { [Link]("This animal eats food"); }
}

class Dog extends Animal { // Dog inherits eat() automatically


void bark() { [Link]("Dog barks"); }
}

public class Test {


public static void main(String[] args) {
Dog d = new Dog();
[Link](); // inherited from Animal
[Link](); // defined in Dog
}
}

18.1 Types of inheritance in Java


Type Description Supported directly in Java?

Single One subclass extends one superclass Yes

Multilevel A chain: C extends B, B extends A Yes

Hierarchical Multiple subclasses extend the same one Yes


superclass
Type Description Supported directly in Java?

Multiple (classes) One subclass extends more than one NOT supported for classes —
superclass directly causes the Diamond Problem

Hybrid A combination of the above Achieved only through


interfaces, not classes

18.2 Why Java doesn't allow multiple class inheritance


If class C extended both classes A and B, and both A and B defined a method with the identical signature, the
compiler would face an unresolvable ambiguity about which version C should inherit — this is called the
Diamond Problem. Java sidesteps it entirely by allowing a class to extend only ONE class, while still allowing it to
implement MULTIPLE interfaces (interfaces historically had no conflicting implementation code to inherit, only
method signatures — and even with Java 8's default methods, the language forces you to explicitly resolve any
conflict, so ambiguity is never silent).
interface Flyable { void fly(); }
interface Swimmable { void swim(); }

class Duck implements Flyable, Swimmable { // "multiple inheritance" of TYPE, safely


public void fly() { [Link]("Duck flies"); }
public void swim() { [Link]("Duck swims"); }
}

💡 Exam tip: Very common question: 'Why doesn't Java support multiple inheritance?' Answer with the Diamond Problem
by name, and immediately mention that interfaces provide a safe substitute — that's the complete expected answer.

19. Polymorphism
Polymorphism means 'one interface, many implementations' — the same method name behaves differently
depending on the object or arguments involved. Java supports two kinds:

19.1 Compile-time (static) polymorphism — Method Overloading


Multiple methods in the SAME class share the same name but differ in parameter list (number, type, or order of
parameters). The compiler decides which version to call based on the arguments used at the call site — hence
'compile-time'.
class Calculator {
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
int add(int a, int b, int c) { return a + b + c; }
}
// The compiler picks the right add() by matching argument types/count at compile time.

19.2 Runtime (dynamic) polymorphism — Method Overriding


A subclass provides its own specific implementation of a method already defined in its superclass, with the
IDENTICAL signature. Which version actually executes is decided at RUNTIME, based on the actual object type
(not the reference type) — this mechanism is called dynamic method dispatch.
class Shape {
double area() { return 0; }
}
class Circle extends Shape {
double radius;
Circle(double r) { radius = r; }
@Override
double area() { return [Link] * radius * radius; }
}
class Square extends Shape {
double side;
Square(double s) { side = s; }
@Override
double area() { return side * side; }
}

public class Test {


public static void main(String[] args) {
Shape s; // reference type is Shape
s = new Circle(5);
[Link]([Link]()); // Circle's area() runs - decided at RUNTIME

s = new Square(4);
[Link]([Link]()); // now Square's area() runs
}
}

This example is the classic exam demonstration of 'a superclass reference variable can hold a subclass object',
and of WHY that matters — the actual method invoked depends on the object created with new, not on the
declared type of the variable.

💡 Exam tip: Table below is one of the most frequently reproduced comparisons — memorising the table isn't necessary if
you understand 'overloading = same class, different parameters, decided at compile time' vs 'overriding = parent-child
classes, identical signature, decided at runtime.'

20. Method Overloading vs Method Overriding — Full Comparison


Aspect Overloading Overriding

Classes involved Same class (or a subclass adding new Two classes in an inheritance relationship
variants) (parent-child)

Method signature Must differ (parameters differ in Must be IDENTICAL (same name,
type/number/order) parameters, return type*)

Binding time Compile-time (static binding) Runtime (dynamic binding)

Return type Can differ freely Must be same, or a covariant subtype


Aspect Overloading Overriding

Purpose Provide multiple ways to call a Let a subclass customize/replace inherited


similarly-named operation behaviour

Access modifier rule No restriction Overriding method cannot have a MORE


restrictive access modifier than the
parent's

@Override Not applicable Recommended (compiler then verifies


annotation correctness)

💡 Exam tip: *Covariant return types (Java 5+) allow the overriding method to return a subtype of the original return type
— a small but sometimes-tested detail.

21. String, StringBuffer, and StringBuilder

21.1 String — immutability, and the String Pool


A String object in Java is IMMUTABLE — once created, its character sequence can never be changed. Any
operation that appears to 'modify' a String (like concatenation) actually creates a brand-new String object and
leaves the original untouched.
String s = "Hello";
[Link](" World"); // creates a NEW string, but result is discarded here!
[Link](s); // still prints "Hello" - original unchanged

s = [Link](" World"); // now s is REASSIGNED to the new object


[Link](s); // prints "Hello World"

Java optimizes memory for string LITERALS via the String Constant Pool (part of the heap): when you write String
s1 = "Java";, the JVM checks the pool first — if "Java" already exists there, s1 just points to the existing object
instead of creating a duplicate. Using new String("Java") deliberately bypasses the pool and forces a brand-new
object on the heap.
String s1 = "Java";
String s2 = "Java";
[Link](s1 == s2); // true - both point to the SAME pooled object

String s3 = new String("Java");


[Link](s1 == s3); // false - s3 is a distinct heap object
[Link]([Link](s3)); // true - content is equal (equals() checks
VALUE)

💡 Exam tip: Golden rule for exams and interviews: use == to compare references/identity, use .equals() to compare
content. This String pool question is asked almost every semester.

10 commonly used String methods


String s = " Java Programming ";

[Link]() // 20 -> number of characters


[Link](2) // 'J' -> character at given index
[Link]() // "Java Programming" -> removes leading/trailing whitespace
[Link]() // " JAVA PROGRAMMING "
[Link]() // " java programming "
[Link](2, 6) // "Java" -> extract from index 2 (incl.) to 6 (excl.)
[Link]('a', 'A') // replaces all occurrences of 'a' with 'A'
[Link]("Programming") // returns starting index of the substring, or -1
[Link]("Java Programming") // content comparison, ignores leading/trailing spaces? NO
- exact match needed
[Link](" ") // splits into a String array by the given delimiter

21.2 StringBuffer and StringBuilder — mutable alternatives


Because String is immutable, repeatedly concatenating strings in a loop creates many throwaway objects,
wasting memory and CPU. StringBuffer and StringBuilder solve this by being MUTABLE — internally, they
maintain a resizable character array that is modified in place rather than creating a new object every time.

Aspect StringBuffer StringBuilder

Mutability Mutable Mutable

Thread safety Synchronized (thread-safe) - safe for NOT synchronized - faster, but not
multithreaded access thread-safe

Performance Slightly slower due to synchronization Faster in single-threaded scenarios


overhead

Introduced in JDK 1.0 JDK 1.5, as a faster alternative when


thread-safety isn't needed

When to use Multiple threads modify the same string Single-threaded string building (most
concurrently common case, e.g. loops)

5 commonly used methods (identical API for both classes)


StringBuilder sb = new StringBuilder("Hello");

[Link](" World"); // "Hello World" -> adds text at the end


[Link](5, ","); // "Hello, World" -> inserts at given index
[Link](); // "dlroW ,olleH" -> reverses the character sequence
[Link](0, 5); // removes characters from index 0 (incl.) to 5 (excl.)
[Link](0, 1, "X"); // replaces characters in the given index range

💡 Exam tip: A precise exam sentence: 'String is immutable and safest for constant text; StringBuilder is mutable and fastest
for single-threaded string building; StringBuffer is mutable and synchronized, making it safe (but slower) for multithreaded
use.'

22. The Object Class


[Link] is the ROOT of the entire Java class hierarchy — every class you write, whether or not you say
'extends Object' explicitly, implicitly extends Object. This is why every object in Java automatically has certain
baseline behaviours.

Key methods provided by Object (and commonly overridden)


Method Purpose

toString() Returns a String representation of the object; default is ClassName@hashcode


— almost always overridden for meaningful output

equals(Object o) Compares this object to another for logical equality; default implementation
just compares references (same as ==) unless overridden

hashCode() Returns an integer hash used by hash-based collections (HashMap, HashSet);


MUST be overridden consistently whenever equals() is overridden

getClass() Returns the runtime Class object, useful for reflection

clone() Creates and returns a copy of the object (class must implement Cloneable)

finalize() Called by GC before reclaiming the object (deprecated since Java 9)

wait()/notify()/notifyAll() Used for thread synchronization/communication


class Student {
String name;
int roll;
Student(String n, int r) { name = n; roll = r; }

@Override
public String toString() {
return "Student[name=" + name + ", roll=" + roll + "]";
}

@Override
public boolean equals(Object o) {
if (!(o instanceof Student)) return false;
Student s = (Student) o;
return [Link] == [Link] && [Link]([Link]);
}
}

public class Test {


public static void main(String[] args) {
Student s1 = new Student("Anu", 1);
[Link](s1); // auto-calls toString() -> Student[name=Anu,
roll=1]
}
}

💡 Exam tip: Frequently tested rule: 'Whenever you override equals(), you must also override hashCode(), so that two
equal objects always produce the same hash code' — otherwise hash-based collections like HashMap/HashSet break
silently.

23. Enhanced for Loop (for-each)


Introduced in Java 5, the enhanced for loop provides simpler syntax to iterate over arrays and any Collection
(List, Set, etc.), removing the need to manually manage an index variable and reducing off-by-one errors.
int[] numbers = {10, 20, 30, 40};

// Traditional for loop


for (int i = 0; i < [Link]; i++) {
[Link](numbers[i]);
}

// Enhanced for loop - reads "for each int n in numbers"


for (int n : numbers) {
[Link](n);
}

// Works identically for Collections


import [Link].*;
List<String> names = [Link]("Amit", "Riya", "Zoe");
for (String name : names) {
[Link](name);
}

•​ Limitation: you cannot access or modify the index, and you cannot easily remove elements from a
collection while enhanced-for-looping over it (throws ConcurrentModificationException).
•​ Internally, for Collections it uses the Iterator interface behind the scenes — this is worth mentioning if
asked 'how does for-each work internally'.
💡 Exam tip: If a question asks for the LIMITATION of enhanced-for, the standout answer is: 'You cannot access the loop
index, and you cannot safely modify the collection's structure while iterating it.'

24. File Handling in Java


File handling is done primarily through the [Link] package (and the newer [Link] package). The central
class for representing a file/directory path is [Link]; actual reading/writing is done through Stream or
Reader/Writer classes.

24.1 Byte streams vs Character streams


•​ Byte streams (InputStream/OutputStream and subclasses like FileInputStream/FileOutputStream) —
handle raw binary data, 1 byte at a time. Used for images, audio, any non-text file.
•​ Character streams (Reader/Writer and subclasses like FileReader/FileWriter,
BufferedReader/BufferedWriter) — handle text data, automatically dealing with character encoding. Used
for .txt/.csv and similar text files.

24.2 Writing to a file


import [Link];
import [Link];

public class WriteDemo {


public static void main(String[] args) {
try (FileWriter writer = new FileWriter("[Link]")) {
[Link]("Hello, File Handling!\n");
[Link]("Second line.");
} catch (IOException e) {
[Link]("Error writing file: " + [Link]());
}
// try-with-resources automatically closes 'writer' even if an exception occurs
}
}
24.3 Reading from a file
import [Link];
import [Link];
import [Link];

public class ReadDemo {


public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("[Link]"))) {
String line;
while ((line = [Link]()) != null) {
[Link](line);
}
} catch (IOException e) {
[Link]("Error reading file: " + [Link]());
}
}
}

24.4 The File class — checking/creating/deleting


import [Link];
import [Link];

public class FileOpsDemo {


public static void main(String[] args) throws IOException {
File f = new File("[Link]");
if (![Link]()) {
[Link]();
}
[Link]("Name: " + [Link]());
[Link]("Path: " + [Link]());
[Link]("Size (bytes): " + [Link]());
[Link]();
}
}

💡 Exam tip: Note the try-with-resources syntax (try (Resource r = ...) {...}) — introduced in Java 7, it automatically calls
close() on the resource, which is exactly what a 'best practice' exam answer should mention when discussing file I/O.

25. Exception Handling


An exception is an event that disrupts the normal flow of a program's instructions during execution (e.g., dividing
by zero, accessing an invalid array index, a file that doesn't exist). Java's exception handling mechanism lets you
gracefully detect and respond to such events instead of letting the program crash abruptly — this maps directly
back to the 'Robust' feature discussed in Section 8.

25.1 The exception class hierarchy


[Link]
/ \
Error Exception
(serious, JVM-level, / \
not meant to be Checked Unchecked (RuntimeException
caught, e.g. Exceptions and its subclasses)
OutOfMemoryError) (must be handled e.g. NullPointerException,
or declared, ArrayIndexOutOfBoundsException,
e.g. IOException, ArithmeticException
SQLException)

•​ Checked exceptions are checked by the COMPILER at compile time — the compiler forces you to either
handle them (try-catch) or declare them (throws). Example: IOException.
•​ Unchecked exceptions (RuntimeException and its subclasses) are NOT checked at compile time — they
usually represent programming bugs (like dividing by zero) that surface only at runtime.
•​ Errors represent serious problems (like running out of memory) that applications generally should not try
to catch or recover from.

25.2 try, catch, finally, throw, throws


public class ExceptionDemo {
static int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("Cannot divide by zero"); // 'throw' - actually
raises an exception
}
return a / b;
}

public static void main(String[] args) {


try {
int result = divide(10, 0);
[Link](result);
} catch (ArithmeticException e) { // catches ONLY ArithmeticException (and
its subtypes)
[Link]("Error: " + [Link]());
} catch (Exception e) { // a broader fallback catch block
[Link]("Some other error occurred");
} finally {
[Link]("This always runs - cleanup code goes here");
}
}
}

'throws' (different from 'throw') is used in a method signature to DECLARE that a method might throw a checked
exception, delegating the responsibility of handling it to the CALLER:
import [Link].*;

static void readFile(String path) throws IOException { // declares, doesn't handle


FileReader fr = new FileReader(path);
}

public static void main(String[] args) {


try {
readFile("[Link]");
} catch (IOException e) { // the caller is now forced to handle it
[Link]("File not found!");
}
}

25.3 Custom (user-defined) exceptions


class InsufficientBalanceException extends Exception {
InsufficientBalanceException(String message) {
super(message); // pass message up to the Exception superclass
}
}

class Account {
double balance = 500;
void withdraw(double amt) throws InsufficientBalanceException {
if (amt > balance) {
throw new InsufficientBalanceException("Insufficient funds!");
}
balance -= amt;
}
}

💡 Exam tip: Common exam distinction: 'throw' is a statement used to actually raise a SINGLE exception instance; 'throws'
is a keyword in a method signature that lists the checked exception TYPES a method might raise, forcing callers to handle
them.

26. JDBC — Java Database Connectivity


JDBC is a standard Java API ([Link] package) that provides a uniform way for Java applications to connect to and
interact with relational databases (MySQL, Oracle, PostgreSQL, etc.), regardless of which specific database
vendor is used underneath.

26.1 The core idea — JDBC Drivers


A JDBC Driver is the piece of software that translates the standard JDBC API calls made by your Java code into the
specific network protocol/calls understood by a particular database vendor's server. Sun/Oracle defined FOUR
types of drivers; this syllabus focuses on Types 1, 3, and 4.

26.2 Type 1 — JDBC-ODBC Bridge Driver


Translates JDBC calls into ODBC (Open Database Connectivity, a Microsoft-era standard) calls, which are then
handled by an ODBC driver that talks to the actual database. It essentially 'bridges' Java to an already-existing
ODBC driver.
Java Application
|
v
JDBC API
|
v
JDBC-ODBC Bridge Driver (translates JDBC -> ODBC calls)
|
v
ODBC Driver (native, OS-specific)
|
v
Database

•​ Requires an ODBC driver to be installed and configured on the CLIENT machine — platform-dependent,
since ODBC itself is largely a Windows technology.
•​ Slow — every call passes through an extra translation layer (JDBC to ODBC), and native code is invoked
(breaks pure-Java portability).
•​ Deprecated/removed in modern JDK versions (removed since Java 8) — mention this if asked about its
status today.

26.3 Type 3 — Network Protocol (Middleware) Driver


A pure-Java client-side driver sends database calls to a middleware/application server over the network using a
vendor-independent protocol; that middle-tier server then translates the request into the specific protocol of
whichever target database, and can even connect to MULTIPLE different databases.
Java Application (Client)
|
v
JDBC API + Type 3 Driver (pure Java, no vendor-specific code on client)
|
v (network protocol, e.g. over sockets)
Middleware / Application Server
|
v (translates to vendor-specific protocol)
Actual Database Server

•​ Fully platform-independent (pure Java on the client side).


•​ Supports connecting to multiple different databases through a single middleware server — good for large
enterprise systems.
•​ Extra network hop through the middleware adds complexity and some latency; requires maintaining that
middleware server.

26.4 Type 4 — Thin (Pure Java / Native-Protocol) Driver


A 100% pure-Java driver that converts JDBC calls DIRECTLY into the network protocol used natively by the specific
database server — no ODBC layer, no middleware. This is the MOST WIDELY USED driver type today (e.g., MySQL
Connector/J, Oracle's ojdbc driver).
Java Application
|
v
JDBC API + Type 4 Driver (pure Java, talks the DB's own wire protocol directly)
|
v
Database Server
•​ Best performance among all driver types — no intermediate translation layers.
•​ Fully platform-independent, since it's pure Java with no native code involved.
•​ Downside: tied to one specific database vendor's protocol — you need a different Type 4 driver per
database product.

Type Name Key trait

Type 1 JDBC-ODBC Bridge Uses ODBC driver; platform-dependent;


deprecated

Type 3 Network Protocol (Middleware) Pure Java client; routes through a middle-tier
server; multi-database capable

Type 4 Thin / Native Protocol Pure Java; talks directly to DB; fastest; most widely
used today

26.5 Basic JDBC code — the 5 standard steps


import [Link].*;

public class JdbcDemo {


public static void main(String[] args) {
try {
// Step 1: Load/register the driver (often automatic in modern JDBC 4.0+)
[Link]("[Link]");

// Step 2: Establish the connection


Connection con = [Link](
"jdbc:mysql://localhost:3306/school", "root", "password");

// Step 3: Create a Statement object


Statement stmt = [Link]();

// Step 4: Execute a query and process the ResultSet


ResultSet rs = [Link]("SELECT id, name FROM students");
while ([Link]()) {
[Link]([Link]("id") + " - " + [Link]("name"));
}

// Step 5: Close the connection to release resources


[Link]();

} catch (ClassNotFoundException | SQLException e) {


[Link]();
}
}
}

💡 Exam tip: The '5 steps' (Load driver -> Get connection -> Create statement -> Execute query -> Close connection) is
exactly what examiners expect for 'write basic JDBC code' — reproduce them as commented steps even if you can't recall
exact syntax, since the structure carries most of the marks.

Quick Revision — One-Line Answers


•​ Java = platform-independent because it compiles to bytecode run by a JVM, not to native machine code.
•​ JDK = JRE + development tools; JRE = JVM + core libraries; JVM = the engine that executes bytecode.
•​ Java is always pass-by-value; for objects, the VALUE being copied is the reference (address).
•​ this refers to the current object; super refers to the immediate parent class.
•​ Overloading = same class, different parameters, resolved at compile time.
•​ Overriding = parent-child classes, identical signature, resolved at runtime (dynamic dispatch).
•​ String is immutable; StringBuilder is fast/unsynchronized; StringBuffer is slower/synchronized (thread-safe).
•​ Java has no multiple class inheritance (avoids the Diamond Problem); interfaces provide a safe alternative.
•​ Garbage Collection automatically reclaims memory of unreachable objects — no manual free() needed.
•​ JDBC Type 4 (Thin driver) is pure Java, talks directly to the DB, and is the most commonly used driver today.

You might also like