0% found this document useful (0 votes)
7 views39 pages

BCA Sem4 Java CompleteNotes

The document provides comprehensive notes for BCA Semester 4 Java Programming, covering all four units aligned with the IPU and Indian University BCA pattern. It includes foundational concepts of Object-Oriented Programming, Java basics, and practical applications, along with exam preparation tips and a structured study plan. Key topics include OOP principles, Java features, architecture, and data types, making it a valuable resource for students preparing for internal assessments and external exams.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views39 pages

BCA Sem4 Java CompleteNotes

The document provides comprehensive notes for BCA Semester 4 Java Programming, covering all four units aligned with the IPU and Indian University BCA pattern. It includes foundational concepts of Object-Oriented Programming, Java basics, and practical applications, along with exam preparation tips and a structured study plan. Key topics include OOP principles, Java features, architecture, and data types, making it a valuable resource for students preparing for internal assessments and external exams.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

BCA SEMESTER 4

JAVA PROGRAMMING
COMPLETE TEXTBOOK-LEVEL NOTES

Covering All 4 Units | IPU & Indian University BCA Pattern


40% Internal Assessment + 60% External Exam Preparation
Based on: Herbert Schildt (TB1) | Trilochan Tarai (TB2) | E. Balaguruswamy (RB1)
Includes: Theory | Full Java Programs | OOP Concepts | Viva Q&A | Exam Tips | 6-Month Plan

Prepared in the style of a Senior BCA Professor & University Examiner

UNIT – I: OOP PARADIGM & JAVA BASICS


1. UNIT INTRODUCTION
Unit I establishes the foundational philosophy of Object-Oriented Programming and introduces Java
— the language that made OOP accessible to the world. Java powers Android apps, enterprise
backends, banking systems, and billions of devices globally. For BCA students, Java is often the
first serious OOP language — the concepts learned here form the bedrock of modern software
development.
Exam Weightage: Unit I carries 20–25 marks. OOP concepts, Java features, JVM architecture,
data types, operators, and control structures are all high-frequency questions.
Reference: TB1 Chapters 1, 2, 3, 5, 6 | TB2 Chapters 2, 3, 4, 5, 6, 7, 8

2. OBJECT-ORIENTED PARADIGM
2.1 Procedural vs Object-Oriented Development
Programming paradigms define the style and approach to writing programs. Two dominant
paradigms in the history of software development are Procedural Programming and Object-Oriented
Programming (OOP).
Procedural Programming (C, Pascal, FORTRAN): Programs are sequences of instructions
organised into functions/procedures. The program focuses on WHAT TO DO — a step-by-step
recipe. Data and functions are separate. Data is passed between functions. As programs grow
large, data becomes difficult to protect and manage. Changes in data structure require changes
throughout the code.
Object-Oriented Programming: Programs are organised around OBJECTS — entities that combine
data (attributes) and behaviour (methods) together. The program focuses on WHAT THINGS EXIST
and HOW THEY INTERACT. Data is protected inside objects and accessed only through defined
interfaces. Mirrors the real world — everything is modelled as an object.
Aspect Procedural Programming Object-Oriented Programming
Focus Procedures/functions (actions) Objects (entities with data +
behaviour)
Data Global or passed between Encapsulated within objects
functions
Reusability Function reuse (limited) Inheritance and polymorphism
enable high reuse
Data Security Low — data often global, High — encapsulation hides
accessible internal data
Approach Top-down design Bottom-up design
Real-world modelling Poor fit Excellent fit
Example languages C, Pascal, FORTRAN Java, C++, Python, C#
Maintenance Harder as size grows Easier — changes localised to
objects
EXAM TIP: Procedural vs OOP is a common 5-mark or 7-mark question. Use the table above but
ALSO give a real-world example: a 'Car' in OOP has attributes (colour, speed) and methods
(accelerate(), brake()) — it is a self-contained unit. In procedural programming, these would be
separate variables and functions with no natural connection.

2.2 Basic Concepts of Object-Oriented Programming


1. Class
A Class is a blueprint or template for creating objects. It defines the attributes (data members/fields)
and behaviours (methods) that all objects of that class will have. A class does not occupy memory
by itself — it is a definition, like an architectural plan for a building. Example: A 'Car' class defines
that all cars have attributes (brand, colour, speed) and can perform actions (start(), stop(),
accelerate()).
class Car {
String brand; // attribute
int speed; // attribute
void start() { [Link](brand + " started"); } // method
}

2. Object
An Object is an instance of a class — a specific, concrete realisation of the class blueprint in
memory. Objects occupy memory. Each object has its own copy of the class's instance variables.
Multiple objects can be created from one class, each with different attribute values. Example:
'myCar' is an object of the 'Car' class with brand='Honda' and speed=120.
Car myCar = new Car(); // Creating an object
[Link] = "Honda"; // Setting attribute
[Link](); // Calling method

3. Encapsulation
Encapsulation is the mechanism of bundling data (attributes) and the methods that operate on that
data together within a single unit (class), AND restricting direct access to some of the object's
components. It is achieved using access modifiers (private, protected, public) and getter/setter
methods. Encapsulation is also described as data hiding. The internal state of an object is hidden
from the outside — external code can only interact through the public interface.
class BankAccount {
private double balance; // hidden — cannot be accessed directly
public void deposit(double amount) { balance += amount; }
public double getBalance() { return balance; } // controlled access
}

4. Inheritance
Inheritance is the mechanism by which one class (subclass/child class) acquires the properties and
methods of another class (superclass/parent class). It promotes CODE REUSABILITY — common
functionality is written once in the parent class and inherited by all child classes. Java uses the
'extends' keyword for inheritance.
class Animal {
void eat() { [Link]("Animal eats"); }
}
class Dog extends Animal { // Dog inherits from Animal
void bark() { [Link]("Dog barks"); }
}
// Dog object can call both eat() and bark()

5. Polymorphism
Polymorphism (Greek: 'many forms') is the ability of a single interface (method name) to represent
different underlying forms (implementations). One name — many behaviours. Two types: Compile-
time polymorphism (Method Overloading — same method name, different parameters, resolved at
compile time). Runtime polymorphism (Method Overriding — subclass provides its own
implementation of parent's method, resolved at runtime through dynamic dispatch).

6. Abstraction
Abstraction is the process of hiding complex implementation details and showing only the essential
features to the user. It focuses on WHAT an object does rather than HOW it does it. Achieved
through abstract classes and interfaces in Java. Example: When you drive a car, you use the
steering wheel and pedals (interface) without needing to understand the engine mechanics
(implementation).

7. Message Passing
In OOP, objects communicate by sending messages to each other. A message is a request to an
object to execute one of its methods. In Java, this is implemented by calling methods on object
references: [Link]() is a message sent to the myCar object requesting execution of its start()
method.

2.3 Applications and Benefits of OOP


Applications: GUI applications (Swing, JavaFX). Web development (Spring Framework). Android
mobile development. Game development. Simulation systems. AI and machine learning
frameworks. Banking and financial systems. Enterprise resource planning (ERP) systems.
Benefits: Modularity: Each object is a self-contained module — easy to understand, test, and
maintain independently. Code Reusability: Inheritance eliminates duplication — write once, reuse
everywhere. Scalability: Easy to add new objects without disturbing existing code. Data Security:
Encapsulation protects data from unauthorised access. Maintainability: Changes to one object do
not cascade through the entire system. Real-world modelling: Natural mapping from problem
domain to code.

3. JAVA BASICS
3.1 History of Java
Java was developed at Sun Microsystems by James Gosling and his team (known as the 'Green
Team'), originally for consumer electronics embedded systems in 1991, under the codename 'Oak.'
When the internet boom arrived, Java was repositioned as a platform-independent language for the
web and officially released as Java 1.0 in 1995 with the famous slogan 'Write Once, Run Anywhere'
(WORA).
Key milestones: 1991: Green Project begins (James Gosling). 1995: Java 1.0 officially released by
Sun Microsystems. 1996: Java Development Kit (JDK) 1.0 released. 1998: Java 2 introduced
(J2SE, J2EE, J2ME). 2006: Java made open-source under GPL. 2010: Oracle Corporation acquires
Sun Microsystems and Java. Present: Java remains one of the most popular programming
languages globally (TIOBE Index consistently top 3).

3.2 Features of Java


Java's widespread adoption is driven by a set of carefully designed features:
1. Simple: Java was designed to be easy to learn, especially for programmers familiar with
C/C++. It eliminates complex features of C++ like pointers, multiple inheritance, and explicit
memory management (through automatic garbage collection).
2. Object-Oriented: Java is built entirely around OOP principles — everything (except primitive
types) is an object. Java enforces the OOP paradigm more strictly than C++.
3. Platform-Independent (Write Once, Run Anywhere): Java code is compiled not to machine-
specific binary but to platform-neutral BYTECODE (.class files). This bytecode runs on any
machine that has a JVM (Java Virtual Machine) installed. Windows bytecode runs on Linux,
Mac, Android — unchanged.
4. Robust: Java eliminates error-prone features (explicit pointers, memory management).
Strong type checking at compile time. Automatic garbage collection prevents memory leaks.
Exception handling mechanism makes programs resilient.
5. Secure: Java was designed with security as a priority. No explicit pointer manipulation
prevents illegal memory access. The Security Manager controls what resources Java
programs can access. Bytecode verification prevents malicious code from running.
6. Architecture-Neutral: Java's bytecode is designed to be independent of computer
architecture. The same .class file runs on 32-bit and 64-bit systems without recompilation.
7. Portable: Beyond architecture neutrality, Java's primitive data types have fixed sizes across
all platforms (int is always 32 bits in Java, unlike C where it depends on the platform). This
ensures consistent behaviour.
8. High Performance: While interpreted languages are slower than compiled ones, Java's Just-
In-Time (JIT) compiler converts bytecode to native machine code at runtime, significantly
improving performance. Modern JVMs achieve near-native performance.
9. Multithreaded: Java has built-in support for multithreading — allowing multiple threads of
execution to run concurrently within a single program. This is essential for responsive GUIs,
servers, and taking advantage of multi-core processors.
10. Distributed: Java was designed for the distributed internet environment. It has extensive
networking libraries ([Link]) supporting TCP/IP protocols, URL handling, and HTTP/FTP.
Java's RMI (Remote Method Invocation) and EJB enable distributed computing.
11. Dynamic: Java programs can carry extensive runtime type information. Classes are loaded
dynamically as needed. This allows programs to adapt at runtime — loading classes based
on user input or configuration.
12. Interpreted: Java bytecode is executed by the JVM interpreter. This enables platform
independence and allows code to be checked at runtime.

3.3 Difference Between Java and C++


Feature Java C++
Platform Platform-independent (bytecode Platform-dependent (compiles
+ JVM) to native code)
Pointers No explicit pointers (references Full pointer support
only)
Memory Management Automatic (Garbage Collection) Manual (new/delete)
Multiple Inheritance Not supported for classes (use Supported
interfaces)
Operator Overloading Not supported Supported
Header Files Not used (imports) Used (.h files)
goto Not used Available (discouraged)
Default Arguments Not supported Supported
Preprocessor Not used Uses preprocessor (#define,
#include)
Thread Support Built-in ([Link]) Through libraries
Exception Handling Checked and unchecked Unchecked only
exceptions
Main method public static void main(String[] int main(int argc, char* argv[])
args)
Compilation To bytecode (.class) To machine code (.exe/.out)

3.4 Java Architecture — JDK, JVM, JRE


JVM — Java Virtual Machine
The JVM is an abstract computing machine that provides the runtime environment for executing
Java bytecode. It is the cornerstone of Java's platform independence. The JVM has three primary
functions: Loads .class files (Class Loader). Verifies bytecode for safety (Bytecode Verifier).
Executes bytecode (Execution Engine — Interpreter + JIT Compiler).
JVM is platform-dependent — there is a different JVM implementation for Windows, Linux, and
macOS. But the bytecode it executes is platform-independent. This is why Java achieves WORA:
platform-independent bytecode + platform-specific JVM.
JVM Components: Class Loader (loads .class files into memory). Method Area (stores class
metadata). Heap (runtime memory for objects — garbage collected). Stack (method call frames and
local variables). PC Register (current instruction counter). Native Method Stack (for native code
calls). Execution Engine (interprets/JIT compiles bytecode to native code).

JRE — Java Runtime Environment


JRE = JVM + Java Class Libraries (standard library). The JRE provides everything needed to RUN
Java programs. If you only want to run (not develop) Java applications, you need the JRE. It does
NOT include development tools (compiler, debugger).

JDK — Java Development Kit


JDK = JRE + Development Tools (javac compiler, javadoc, jar, debugger, etc.). The JDK is needed
to DEVELOP Java programs. It includes everything a developer needs: the compiler (javac) to
compile source code to bytecode, the JRE to run the compiled programs, and additional tools for
documentation and packaging.
Hierarchy: JDK ⊃ JRE ⊃ JVM (JDK contains JRE which contains JVM)
Java Source Code (.java) → javac Compiler → Bytecode (.class) → JVM → Native Machine Code
→ Execution
EXAM TIP: JDK/JVM/JRE distinction is a guaranteed 5-mark question. Draw the containment
diagram: JDK ⊃ JRE ⊃ JVM, and explain what each adds. The key phrase: JVM provides platform
independence; JDK provides development capability.
4. JAVA TOKENS
Tokens are the smallest individual units of a Java program — the building blocks from which all
Java code is constructed. The Java compiler breaks source code into tokens during lexical analysis.
• Keywords: Reserved words with predefined meanings in Java (class, int, if, while, public,
static, void, etc.). Cannot be used as identifiers. Java has 50+ keywords.
• Identifiers: Names given to variables, methods, classes, and other program elements by the
programmer. Rules: Must start with a letter, underscore (_), or dollar sign ($). Can contain
letters, digits, underscore, or dollar sign. Case-sensitive (myVar ≠ MyVar). Cannot be a
keyword. Examples: myVariable, calculateSum, Employee.
• Literals: Fixed constant values directly written in the source code. Integer literals: 42, 0xFF
(hex), 0b1010 (binary). Float literals: 3.14f, 2.5. Double literals: 3.14, 2.7E10. Character
literals: 'A', '\n'. String literals: "Hello World". Boolean literals: true, false. Null literal: null.
• Operators: Symbols that perform operations on operands (+, -, *, /, %, ++, --, ==, !=, &&, ||,
etc.).
• Separators: Characters used to separate tokens (parentheses (), braces {}, brackets [],
semicolon ;, comma ,, period .).
• Comments: Not tokens in the compilation sense, but part of Java programs. Single-line: //
comment. Multi-line: /* comment */. Documentation: /** doc comment */.

5. JAVA DATA TYPES


Java is a strongly typed language — every variable must have a declared type, and the type
determines what values can be stored and what operations can be performed.

5.1 Primitive Data Types


Java has 8 primitive data types — these are fundamental, built-in types that directly store values
(not objects):
Type Size Range Default Example
byte 8 bits (1 byte) -128 to 127 0 byte b = 100;
short 16 bits (2 bytes) -32,768 to 32,767 0 short s = 5000;
int 32 bits (4 bytes) -2^31 to 2^31-1 0 int n = 100000;
long 64 bits (8 bytes) -2^63 to 2^63-1 0L long l =
99999999L;
float 32 bits (4 bytes) ±3.4×10^38 (7 0.0f float f = 3.14f;
decimal digits)
double 64 bits (8 bytes) ±1.8×10^308 (15 0.0 double d = 3.14;
decimal digits)
char 16 bits (2 bytes) 0 to 65535 '\u0000' char c = 'A';
(Unicode)
boolean 1 bit true or false false boolean flag =
(implementation- true;
dependent)
NOTE: Java's char is 16-bit (2 bytes) to support Unicode, unlike C's 8-bit char. This is one of the
significant differences from C/C++.

5.2 Non-Primitive (Reference) Types


Reference types store the memory address (reference) of objects rather than the value directly.
Examples: Classes (String, Integer, Scanner, user-defined classes), Arrays, Interfaces. The default
value of any reference type is null.
6. VARIABLES — SCOPE AND LIFETIME
A variable is a named memory location that stores a value. In Java, every variable must be declared
with a type before use.

6.1 Types of Variables by Scope


1. Local Variables
Declared inside a method, constructor, or block. Only accessible within the block where declared.
NOT initialised by default — must be explicitly initialised before use (compiler error otherwise).
Lifetime: Created when the block is entered, destroyed when the block exits.
void myMethod() {
int x = 10; // local variable — must initialise
[Link](x); // valid
}
// x is NOT accessible here — destroyed when method exits

2. Instance Variables (Non-static Fields)


Declared inside a class but OUTSIDE any method. Each object of the class gets its own copy of
instance variables. Accessible from any method of the class using the object reference.
Automatically initialised to default values (0 for numbers, false for boolean, null for objects).
Lifetime: Created when the object is created (new keyword), destroyed when the object is garbage
collected.
class Student {
String name; // instance variable — default null
int rollNo; // instance variable — default 0
}

3. Class Variables (Static Fields)


Declared with the 'static' keyword inside a class. Only ONE copy exists per class — shared by all
objects of the class. Accessible using the class name ([Link]). Initialised when the
class is loaded. Lifetime: From class loading until program termination.
class Counter {
static int count = 0; // class variable — shared
}
// All Counter objects share the SAME count variable

7. OPERATORS IN JAVA
Category Operators Example
Arithmetic +, -, *, /, % (modulo), ++ a+b, a%b, a++
(increment), -- (decrement)
Relational/Comparison ==, !=, >, <, >=, <= a > b → true/false
Logical && (AND), || (OR), ! (NOT) (a>0) && (b>0)
Bitwise & (AND), | (OR), ^ (XOR), ~ a & b, a << 2
(NOT), << (left shift), >> (right
shift)
Assignment =, +=, -=, *=, /=, %= a += 5 means a = a+5
Conditional (Ternary) condition ? val_if_true : max = (a>b) ? a : b;
val_if_false
instanceof Tests if object is instance of a obj instanceof String
class
String concatenation + operator with String "Hello" + " World"
Operator Precedence (highest to lowest): Postfix (++, --) → Unary (!, ~, +, -, prefix ++/--) →
Multiplicative (*, /, %) → Additive (+, -) → Shift (<< >>) → Relational (< > <= >=) → Equality (== !=)
→ Bitwise AND (&) → Bitwise XOR (^) → Bitwise OR (|) → Logical AND (&&) → Logical OR (||) →
Ternary (?:) → Assignment (=, +=, etc.)

8. CONTROL STRUCTURES
8.1 Selection Statements
if-else
if (condition) {
// executes if condition is true
} else if (condition2) {
// executes if condition2 is true
} else {
// executes if all conditions are false
}

switch Statement
switch (expression) {
case value1:
// statements
break; // without break, falls through to next case
case value2:
// statements
break;
default:
// executes if no case matches
}
The expression in switch must be: byte, short, int, char, String (Java 7+), or enum. The break
statement prevents fall-through to the next case.

8.2 Looping Statements


for loop
for (initialisation; condition; update) {
// body — executes while condition is true
}
// Example: print 1 to 10
for (int i = 1; i <= 10; i++) {
[Link](i);
}

Enhanced for loop (for-each) — Java 5+


for (type variable : array_or_collection) {
// process each element
}
int[] arr = {1, 2, 3, 4, 5};
for (int num : arr) {
[Link](num); // prints each element
}

while loop
while (condition) {
// body — executes while condition is true
// condition checked BEFORE each iteration
}

do-while loop
do {
// body — executes at least ONCE
// condition checked AFTER each iteration
} while (condition);
Key difference: while loop may execute 0 times (if condition is false initially); do-while always
executes at least once.

break and continue


break; // exits the loop or switch immediately
continue; // skips the rest of current iteration, goes to next

9. ARRAYS IN JAVA
An array is a fixed-size, ordered collection of elements of the same data type. In Java, arrays are
objects — they are created on the heap and accessed through a reference variable.

9.1 Single-Dimensional Arrays


// Declaration + Allocation + Initialisation
int[] arr = new int[5]; // declares and allocates, default 0
int[] arr = {10, 20, 30, 40, 50}; // declaration with initialisation

// Accessing elements (0-indexed)


arr[0] = 100; // modify first element
[Link](arr[2]); // access third element
[Link]([Link]); // array length property

// Traversing with for loop


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

9.2 Multi-Dimensional Arrays (2D)


// 2D array — matrix
int[][] matrix = new int[3][4]; // 3 rows, 4 columns
int[][] matrix = {{1,2,3}, {4,5,6}, {7,8,9}}; // with initialisation

// Traversing 2D array
for (int i = 0; i < [Link]; i++) {
for (int j = 0; j < matrix[i].length; j++) {
[Link](matrix[i][j] + "\t");
}
[Link]();
}
NOTE: Java supports 'jagged arrays' — 2D arrays where each row can have a different length.
Example: int[][] jagged = new int[3][]; jagged[0]=new int[2]; jagged[1]=new int[4]; This is not possible
in C/C++ with standard 2D arrays.

10. INTERNAL ASSESSMENT SUPPORT — UNIT I


Viva Questions with Answers
Q1: What does 'Write Once, Run Anywhere' mean in Java?
Answer: Java source code is compiled by the Java compiler (javac) not into platform-specific
machine code, but into platform-neutral bytecode (.class files). This bytecode can be executed on
any machine that has a JVM (Java Virtual Machine) installed — Windows, Linux, Mac, Android —
without any modification or recompilation. The JVM interprets/JIT-compiles the bytecode to the
native machine code of the specific platform. Since the JVM is platform-dependent but the bytecode
is platform-independent, the same .class file runs everywhere.

Q2: What is the difference between JDK, JRE, and JVM?


Answer: JVM (Java Virtual Machine) is the engine that executes bytecode — it provides the runtime
environment. JRE (Java Runtime Environment) = JVM + Java standard class libraries. If you only
need to RUN Java programs, install JRE. JDK (Java Development Kit) = JRE + development tools
(javac compiler, javadoc, jar archiver, debugger). If you need to DEVELOP Java programs, install
JDK. Hierarchy: JDK contains JRE which contains JVM.

Q3: What is encapsulation and how is it achieved in Java?


Answer: Encapsulation is the bundling of data (attributes) and methods that operate on that data
into a single unit (class), AND restricting direct access to the internal data (data hiding). In Java: (1)
Declare attributes as private — cannot be accessed from outside the class. (2) Provide public getter
and setter methods for controlled access. This ensures data integrity — external code cannot set a
negative age or invalid email format if the setter validates input.

Important Long Questions


13. Compare procedural and object-oriented programming. What are the basic concepts of
OOP? (10 marks)
14. What are the features of Java? Explain any 8 features in detail. (10 marks)
15. Explain Java architecture — JDK, JVM, JRE — with a diagram showing how Java code is
compiled and executed. (10 marks)
16. Compare Java with C++ across at least 8 parameters. (10 marks)
17. Explain data types in Java. What is the difference between primitive and reference types? (7
marks)
18. Explain scope and lifetime of variables in Java — local, instance, and class variables. (7
marks)

UNIT – II: CLASSES, INHERITANCE, INTERFACES &


POLYMORPHISM
1. UNIT INTRODUCTION
Unit II is the core OOP unit — where Java's object-oriented power is fully realised. Understanding
classes, inheritance, interfaces, and polymorphism is essential for writing professional Java code
and is the foundation of every major Java framework (Spring, Hibernate, Android). This unit is both
conceptually rich and practically important.
Exam Weightage: Unit II carries 25–30 marks — the highest-weighted unit. Classes/objects,
inheritance, method overriding, abstract classes, interfaces, and polymorphism are ALL exam-
critical topics.
Reference: TB1 Chapters 7, 8, 9 | TB2 Chapters 9, 10, 11

2. CREATING A CLASS
2.1 Class Structure
A Java class is the fundamental building block of OOP programs. It encapsulates data (fields) and
behaviour (methods). The general class structure:
class ClassName {
// 1. Fields (attributes/instance variables)
dataType fieldName;

// 2. Constructor(s)
ClassName(parameters) { ... }

// 3. Methods (behaviours)
returnType methodName(parameters) { ... }
}

COMPLETE CLASS EXAMPLE


class Student {
// Fields
private String name;
private int rollNo;
private double marks;
static int count = 0; // class variable

// Constructor
Student(String name, int rollNo, double marks) {
[Link] = name; // 'this' refers to current object
[Link] = rollNo;
[Link] = marks;
count++; // increment class variable
}

// Methods
String getName() { return name; }
void setName(String name) { [Link] = name; }

void display() {
[Link](rollNo + ": " + name + " - " + marks);
}

static void showCount() { // static method


[Link]("Total students: " + count);
}
}

// Using the class


Student s1 = new Student("Alice", 101, 85.5);
Student s2 = new Student("Bob", 102, 90.0);
[Link]();
[Link](); // output: Total students: 2

2.2 Constructors
A Constructor is a special method that initialises a newly created object. It has the same name as
the class and no return type (not even void). It is called automatically when an object is created
using the 'new' keyword.
Types of Constructors:

Default Constructor
A no-argument constructor. If the programmer does not define any constructor, Java automatically
provides a default constructor that initialises all fields to their default values (0, null, false). Once you
define any constructor, Java's automatic default constructor is NO LONGER provided.
class Box {
int length, width;
Box() { // default constructor
length = 1; width = 1;
}
}

Parameterised Constructor
A constructor that takes arguments to initialise fields with specific values.
class Box {
int length, width;
Box(int l, int w) { // parameterised constructor
length = l; width = w;
}
}

Constructor Overloading
Having multiple constructors in the same class with different parameter lists — same as method
overloading for constructors.

Copy Constructor
Creates a new object as a copy of an existing object.
Box(Box other) { // copy constructor
[Link] = [Link];
[Link] = [Link];
}
Box b1 = new Box(5, 3);
Box b2 = new Box(b1); // b2 is a copy of b1

2.3 Access Modifiers


Modifier Same Class Same Package Subclass Everywhere
private ✓ ✗ ✗ ✗
default (no ✓ ✓ ✗ ✗
modifier)
protected ✓ ✓ ✓ ✗
public ✓ ✓ ✓ ✓
Best practice: Use private for all fields (encapsulation), public for methods that form the class's
interface, protected for methods/fields to be inherited, and default for package-internal utilities.

2.4 The 'this' Keyword


'this' is a reference to the CURRENT OBJECT — the object on which the method is being called.
Uses:
• Disambiguate instance variables from local variables with the same name: [Link] =
name;
• Call another constructor of the same class: this(param1, param2); — must be first statement
• Pass the current object as a parameter: someMethod(this);
• Return the current object from a method: return this;
class Rectangle {
int length, width;
Rectangle(int length, int width) {
[Link] = length; // [Link] = instance var, length = parameter
[Link] = width;
}
Rectangle() {
this(1, 1); // calls Rectangle(int,int) — must be first line
}
}

2.5 static Keyword


The static keyword creates class-level members — belonging to the CLASS rather than any
individual object. One copy exists regardless of how many objects are created.

Static Variables
Shared by all objects of the class. Accessed via [Link]. Useful for counters,
constants, and shared configuration.

Static Methods
Can be called without creating an object ([Link]()). Cannot access instance
variables or instance methods directly (no 'this'). Can only directly access other static members.
Example: [Link](), [Link]() are static methods.

Static Block
A block of code executed ONCE when the class is first loaded by the JVM. Used for complex static
variable initialisation.
class Config {
static String dbUrl;
static int maxConnections;

static { // static initialisation block


dbUrl = "jdbc:mysql://localhost/mydb";
maxConnections = 10;
[Link]("Config class loaded");
}
}

2.6 final Keyword


The final keyword restricts modification in three contexts:
• final variable: A constant — its value cannot be changed after initialisation. Naming
convention: ALL_CAPS. Example: final double PI = 3.14159;
• final method: Cannot be overridden in subclasses. Used to prevent modification of critical
logic.
• final class: Cannot be extended (subclassed). Example: [Link] is final. Immutable
classes are typically final.
final class ImmutablePoint {
final int x, y;
ImmutablePoint(int x, int y) { this.x = x; this.y = y; }
// Cannot subclass this class
// x and y cannot be reassigned
}

2.7 String Class and Key Methods


String in Java is a class (not a primitive type) in [Link] package. Strings are IMMUTABLE in Java
— once created, their content cannot be changed. Any 'modification' creates a new String object.
Method Description Example
length() Returns number of characters "Hello".length() → 5
charAt(i) Returns character at index i "Hello".charAt(1) → 'e'
substring(i) Returns substring from index i "Hello".substring(2) → "llo"
substring(i,j) Returns substring from i to j-1 "Hello".substring(1,3) → "el"
indexOf(str) Returns index of first occurrence "Hello".indexOf('l') → 2
toUpperCase() Converts to uppercase "hello".toUpperCase() →
"HELLO"
toLowerCase() Converts to lowercase "HELLO".toLowerCase() →
"hello"
trim() Removes leading/trailing " hi ".trim() → "hi"
whitespace
equals(str) Compares content "hi".equals("hi") → true
equalsIgnoreCase(s) Case-insensitive comparison "Hi".equalsIgnoreCase("HI") →
true
contains(str) Checks if string contains "Hello".contains("ell") → true
substring
replace(old,new) Replaces occurrences "Hello".replace('l','L') → "HeLLo"
split(regex) Splits string into array "a,b,c".split(",") → ["a","b","c"]
compareTo(s) Lexicographic comparison "A".compareTo("B") → negative
NOTE: ALWAYS use .equals() to compare String content, NEVER use == (which compares
references/addresses, not content). str1 == str2 may be false even if they contain the same
characters.

3. INHERITANCE
Inheritance is one of the four pillars of OOP. It allows a new class (subclass) to inherit the properties
and methods of an existing class (superclass), enabling code reuse and establishing an IS-A
relationship between classes.
class Superclass { ... }
class Subclass extends Superclass { ... } // 'extends' keyword
3.1 Types of Inheritance in Java
Single Inheritance
One subclass inherits from ONE superclass. The simplest and most common form.
class Animal { void eat() { ... } }
class Dog extends Animal { void bark() { ... } }

Multilevel Inheritance
Class B inherits from A, Class C inherits from B (a chain of inheritance).
class A { }
class B extends A { } // B inherits from A
class C extends B { } // C inherits from B (and indirectly from A)

Hierarchical Inheritance
Multiple subclasses inherit from the SAME superclass.
class Animal { }
class Dog extends Animal { } // Dog is-a Animal
class Cat extends Animal { } // Cat is-a Animal
class Bird extends Animal { } // Bird is-a Animal

Multiple Inheritance
Java does NOT support multiple inheritance through classes (to avoid the 'Diamond Problem' —
ambiguity when two parent classes have the same method). However, Java achieves multiple
inheritance through INTERFACES (a class can implement multiple interfaces).
NOTE: Diamond Problem: If class C extends both A and B, and both A and B have a method m(),
which m() does C inherit? Java avoids this ambiguity by not allowing multiple class inheritance.
Interfaces solve this because they don't provide implementation (or use default methods with explicit
override requirement).

3.2 super Keyword


'super' is a reference to the IMMEDIATE PARENT CLASS object. Uses:
• Access parent class fields: [Link]
• Call parent class methods: [Link]()
• Call parent class constructor: super(params) — must be first statement in subclass
constructor
class Animal {
String name;
Animal(String name) { [Link] = name; }
void display() { [Link]("Animal: " + name); }
}

class Dog extends Animal {


String breed;
Dog(String name, String breed) {
super(name); // call Animal's constructor
[Link] = breed;
}
@Override
void display() {
[Link](); // call Animal's display()
[Link]("Breed: " + breed);
}
}
3.3 Method Overriding
Method Overriding occurs when a subclass provides its own implementation of a method that is
already defined in its superclass. The method in the subclass has the SAME name, SAME
parameter list, and SAME (or covariant) return type as the method in the superclass.
Rules for overriding: Same method signature (name + parameters). Return type must be same or a
subtype (covariant). Cannot reduce access modifier (public → protected is NOT allowed). Cannot
throw broader checked exceptions. Cannot override static or final methods. Use @Override
annotation (optional but strongly recommended — catches errors).
class Shape {
double area() { return 0; }
}
class Circle extends Shape {
double radius;
Circle(double r) { [Link] = r; }
@Override
double area() { return [Link] * radius * radius; } // overrides Shape's
area()
}
Covariant Return Type: The overriding method's return type can be a subtype of the parent
method's return type (since Java 5).
class Animal {
Animal getInstance() { return new Animal(); }
}
class Dog extends Animal {
@Override
Dog getInstance() { return new Dog(); } // Dog is subtype of Animal —
covariant
}

3.4 Abstract Class


An abstract class is a class declared with the 'abstract' keyword. It represents an incomplete
concept — it may have abstract methods (methods without a body) that MUST be implemented by
concrete subclasses. An abstract class CANNOT be instantiated (you cannot create objects of it
directly).
abstract class Shape {
String colour;
Shape(String colour) { [Link] = colour; }

abstract double area(); // abstract method — no body, MUST be overridden


abstract double perimeter();

void displayColour() { // concrete method — has body, inherited as-is


[Link]("Colour: " + colour);
}
}

class Circle extends Shape {


double radius;
Circle(double r, String c) { super(c); [Link] = r; }

@Override
double area() { return [Link] * radius * radius; } // MUST implement
@Override
double perimeter() { return 2 * [Link] * radius; }
}
A subclass of an abstract class must either: (1) Implement ALL abstract methods, OR (2) Also be
declared abstract itself.

4. INTERFACES AND PACKAGES


4.1 Interface
An Interface is a completely abstract type that defines a CONTRACT — a set of method signatures
(and optionally constants) that implementing classes MUST provide. An interface is declared with
the 'interface' keyword. Interfaces achieve: (1) 100% abstraction (traditionally), (2) Multiple
inheritance in Java, (3) Loose coupling between components.
Key rules for interfaces: All methods are public abstract by default (before Java 8). All fields are
public static final (constants) by default. A class implements an interface using 'implements'
keyword. A class CAN implement multiple interfaces. Since Java 8: interfaces can have default
methods (with body) and static methods. Since Java 9: interfaces can have private methods.
interface Drawable {
double PI = 3.14159; // implicitly public static final
void draw(); // implicitly public abstract
void resize(double factor);
}

interface Colourable {
void setColour(String colour);
}

class Circle implements Drawable, Colourable { // multiple interfaces


double radius;
String colour;

@Override
public void draw() { [Link]("Drawing circle"); }
@Override
public void resize(double f) { radius *= f; }
@Override
public void setColour(String c) { colour = c; }
}

4.2 Abstract Class vs Interface


Aspect Abstract Class Interface
Declaration abstract class Name { } interface Name { }
Methods Can have abstract AND Traditionally only abstract
concrete methods (default methods since Java 8)
Fields Can have instance variables Only constants (public static
final)
Constructor Can have constructors Cannot have constructors
Access modifiers Any access modifier All methods public by default
Extends/Implements Class extends abstract class Class implements interface
Multiple inheritance A class extends ONE abstract A class implements MULTIPLE
class interfaces
IS-A vs CAN-DO IS-A relationship (Vehicle→Car) CAN-DO / capability (Flyable,
Serializable)
When to use Sharing code among closely Define contract for unrelated
related classes classes
EXAM TIP: Abstract Class vs Interface is a guaranteed 10-mark question in most exams. Memorise
the comparison table. Key phrase: Abstract class for IS-A relationship among related classes;
Interface for CAN-DO capabilities across unrelated classes. Java 8 default methods blur some
distinctions but the fundamental design philosophy remains.

4.3 Packages
A Package is a namespace that organises related classes and interfaces. Packages serve two main
purposes: Prevent naming conflicts (two classes can have the same name if in different packages,
like [Link] vs [Link]). Provide access control (package-private members are only
accessible within the same package).
Types of packages: Built-in packages ([Link] — automatically imported, [Link], [Link],
[Link], [Link], [Link]). User-defined packages — created by the programmer.
// Creating a package — first statement in source file
package [Link];

public class MathUtils {


public static int add(int a, int b) { return a + b; }
}

4.4 Importing a Package


// Import specific class
import [Link];

// Import all classes from package (wildcard)


import [Link].*;

// [Link] is automatically imported — no need to import


// String, Math, System, Object are all in [Link]

// Fully qualified name — no import needed


[Link] sc = new [Link]([Link]);

5. POLYMORPHISM
5.1 Method Overloading (Compile-time / Static Polymorphism)
Method Overloading is having multiple methods in the SAME CLASS with the SAME NAME but
different parameter lists (different number of parameters, different types, or different order of types).
The compiler determines which overloaded method to call based on the arguments at 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; }
String add(String a, String b) { return a + b; } // concatenation
}
Calculator c = new Calculator();
[Link](1, 2); // calls int add(int, int)
[Link](1.5, 2.5); // calls double add(double, double)
[Link](1, 2, 3); // calls int add(int, int, int)
NOTE: Return type alone is NOT sufficient to overload methods — Java won't allow two methods
with same name and same parameters but different return types. Overloading is resolved by the
PARAMETER LIST only.

5.2 Dynamic Binding (Runtime / Dynamic Polymorphism)


Dynamic Binding (also called Late Binding or Runtime Polymorphism) is the mechanism by which a
method call is resolved at RUNTIME based on the actual type of the object, not the declared type of
the reference variable. It is achieved through method overriding and object references to parent
types.
class Animal {
void sound() { [Link]("Animal makes a sound"); }
}
class Dog extends Animal {
@Override
void sound() { [Link]("Dog barks"); }
}
class Cat extends Animal {
@Override
void sound() { [Link]("Cat meows"); }
}

// Dynamic binding in action


Animal a;
a = new Dog(); // Animal reference holds Dog object
[Link](); // OUTPUT: "Dog barks" — Dog's sound() called, not Animal's!
a = new Cat(); // Same reference now holds Cat object
[Link](); // OUTPUT: "Cat meows"
The key: 'Animal a' — the REFERENCE TYPE is Animal. 'new Dog()' — the ACTUAL OBJECT
TYPE is Dog. When [Link]() is called, Java looks at the actual object type (Dog) at runtime to
decide which sound() to call. This is Dynamic Binding.

5.3 Casting Objects


Object casting converts an object reference from one type to another in the inheritance hierarchy.

Upcasting (Implicit / Automatic)


Converting a subclass reference to a superclass reference. Always safe — no explicit cast needed.
A Dog IS-A Animal, so treating a Dog as an Animal is always valid.
Dog d = new Dog();
Animal a = d; // Upcasting — implicit, safe

Downcasting (Explicit)
Converting a superclass reference back to a subclass reference. Requires explicit cast. Can throw
ClassCastException at runtime if the object is not actually of the subclass type. Use instanceof to
check before downcasting.
Animal a = new Dog(); // upcast
Dog d = (Dog) a; // downcast — explicit cast, safe here

// UNSAFE: ClassCastException at runtime!


Animal a2 = new Cat();
Dog d2 = (Dog) a2; // ERROR: Cat object cannot be cast to Dog

5.4 instanceof Operator


The instanceof operator tests whether an object is an instance of a specified class or interface.
Returns true or false. Used to safely check before downcasting.
Animal a = new Dog();

if (a instanceof Dog) {
Dog d = (Dog) a; // safe downcast
[Link]();
}

[Link](a instanceof Animal); // true


[Link](a instanceof Dog); // true
[Link](a instanceof Cat); // false

5.5 Generic Programming


Generics (introduced in Java 5) allow classes, interfaces, and methods to operate on TYPED
PARAMETERS — writing code that works with any data type while providing compile-time type
safety. Without generics, you'd use Object references everywhere, losing type safety and requiring
explicit casts.
// Without generics — unsafe
ArrayList list = new ArrayList();
[Link]("Hello");
String s = (String) [Link](0); // requires cast, can throw ClassCastException

// With generics — type-safe


ArrayList<String> list = new ArrayList<String>();
[Link]("Hello");
String s = [Link](0); // no cast needed, compiler checks type
// [Link](42); // COMPILE ERROR — can only add String

// Generic class
class Pair<T, U> {
T first;
U second;
Pair(T f, U s) { first=f; second=s; }
}
Pair<String, Integer> p = new Pair<>("Alice", 25);

6. INTERNAL ASSESSMENT SUPPORT — UNIT II


Viva Questions with Answers
Q1: What is the difference between method overloading and method overriding?
Answer: Method Overloading is defining multiple methods with the SAME NAME but DIFFERENT
PARAMETER LISTS in the SAME CLASS. Resolved at COMPILE TIME (static polymorphism).
Return type alone cannot overload. Method Overriding is providing a DIFFERENT
IMPLEMENTATION of a method ALREADY DEFINED IN THE PARENT CLASS in the SUBCLASS.
Must have same name, same parameters, same (or covariant) return type. Resolved at RUNTIME
(dynamic polymorphism). Overloading = same class, different signatures. Overriding = different
classes (parent/child), same signature.

Q2: Why does Java not support multiple inheritance through classes?
Answer: Java avoids multiple inheritance through classes due to the 'Diamond Problem': if class C
extends both A and B, and both A and B define a method m(), it is ambiguous which version C
inherits. Java solves this by: (1) Not allowing multiple class inheritance (only single class inheritance
with 'extends'). (2) Allowing multiple interface implementation — since interfaces traditionally have
no method bodies, there's no implementation conflict. With Java 8's default methods, if two
interfaces provide the same default method, the implementing class MUST override it, explicitly
resolving the ambiguity.

Q3: What is an abstract class and when would you use it over an interface?
Answer: An abstract class is a class declared with 'abstract' keyword that cannot be instantiated. It
can have both abstract methods (no body, must be overridden) and concrete methods (with body,
inherited as-is). Use abstract class when: (1) Sharing code among closely related classes with an
IS-A relationship (Animal→Dog). (2) You need instance variables (not just constants). (3) You want
to provide some default implementation. Use interface when: (1) Defining a capability/contract for
unrelated classes (Flyable, Serializable). (2) You need multiple inheritance. (3) You want complete
abstraction of the API from implementation.

Important Long Questions


19. Explain constructors in Java — types of constructors with code examples. (10 marks)
20. Explain 'this' keyword and 'super' keyword with examples. (7 marks)
21. What is inheritance in Java? Explain its types with code examples. Why is multiple
inheritance not supported through classes? (10 marks)
22. Compare abstract class and interface across 8 parameters. (10 marks)
23. Explain method overloading and method overriding with examples and key differences. (10
marks)
24. Explain dynamic binding in Java with code example. What is the role of polymorphism? (10
marks)
25. Explain the static keyword — static variable, static method, static block with examples. (7
marks)

UNIT – III: USING I/O — STREAMS AND FILE I/O


1. UNIT INTRODUCTION
Unit III covers Java's I/O (Input/Output) system — how Java programs read data from and write
data to files, the console, and network connections. Java's I/O system is built on the concept of
STREAMS — sequential flows of data. Understanding Java I/O is essential for any application that
reads configuration files, processes data files, logs information, or communicates over networks.
Exam Weightage: Unit III carries 15–20 marks. Byte streams vs character streams,
FileInputStream/FileOutputStream, FileReader/FileWriter, BufferedReader/BufferedWriter, and try-
with-resources are common exam topics.
Reference: TB1 Chapters 11, 12 | TB2 Chapter 13

2. ELEMENTARY CONCEPTS OF INPUT/OUTPUT


In Java, all I/O is based on STREAMS. A Stream is a sequential flow of data — an ordered
sequence of bytes (or characters) flowing from a source to a destination.
• Input Stream: A stream from which data is READ (input to the program). Source can be a
file, keyboard, network socket, or another program.
• Output Stream: A stream to which data is WRITTEN (output from the program). Destination
can be a file, monitor, network socket, or another program.
Java's I/O classes are in the [Link] package. The class hierarchy is based on four abstract base
classes:
Byte-Oriented Character-Oriented
Input InputStream (abstract base) Reader (abstract base)
Output OutputStream (abstract base) Writer (abstract base)
Every input class extends InputStream or Reader; every output class extends OutputStream or
Writer.

3. BYTE STREAMS
Byte streams handle I/O of RAW BINARY DATA — sequences of bytes (8 bits each). They are
suitable for: binary files (images, audio, video, compiled code), any file where you want to work at
the raw byte level, and when exact byte copying is needed.
The base classes are [Link] and [Link]. All byte stream classes
descend from these.

3.1 Key Byte Stream Classes


Class Type Purpose
FileInputStream Input Reads bytes from a file
FileOutputStream Output Writes bytes to a file
BufferedInputStream Input Adds buffering to InputStream
for efficiency
BufferedOutputStream Output Adds buffering to OutputStream
for efficiency
DataInputStream Input Reads primitive Java types from
byte stream
DataOutputStream Output Writes primitive Java types to
byte stream
ObjectInputStream Input Deserialises objects (reads
Object from stream)
ObjectOutputStream Output Serialises objects (writes Object
to stream)
ByteArrayInputStream Input Reads from byte array (in-
memory stream)
PrintStream Output Writes formatted text
([Link] is a PrintStream)

3.2 Reading and Writing Using Byte Streams


FILEINPUTSTREAM — READING BYTES FROM FILE
import [Link].*;

public class ReadBytesExample {


public static void main(String[] args) throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream("[Link]");
int byteData;
while ((byteData = [Link]()) != -1) { // read() returns -1 at EOF
[Link]((char) byteData); // cast byte to char
}
} catch (FileNotFoundException e) {
[Link]("File not found: " + [Link]());
} finally {
if (fis != null) [Link](); // ALWAYS close in finally
}
}
}
NOTE: [Link]() returns the next BYTE as an int (0-255), or -1 when the end of file is reached. The
-1 check is essential to detect EOF.
FILEOUTPUTSTREAM — WRITING BYTES TO FILE
import [Link].*;

public class WriteBytesExample {


public static void main(String[] args) throws IOException {
FileOutputStream fos = null;
try {
// Second parameter true = append mode (false = overwrite)
fos = new FileOutputStream("[Link]", false);
String data = "Hello, Java File I/O!";
[Link]([Link]()); // write byte array
[Link]("Written successfully");
} finally {
if (fos != null) [Link]();
}
}
}

COPY FILE USING BYTE STREAMS — CLASSIC EXAMPLE


import [Link].*;

public class FileCopyByte {


public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("[Link]");
FileOutputStream fos = new FileOutputStream("[Link]");
int b;
while ((b = [Link]()) != -1) {
[Link](b);
}
[Link]();
[Link]();
[Link]("File copied successfully");
}
}

4. AUTOMATICALLY CLOSING A FILE — try-with-resources


Java 7 introduced the try-with-resources statement, which automatically closes resources (streams,
connections) when the try block exits — whether normally or through an exception. This eliminates
the need for explicit finally blocks just for closing resources, prevents resource leaks, and makes
code cleaner and safer.
Any object that implements the [Link] interface can be used as a resource in try-
with-resources. All Java I/O streams implement AutoCloseable.
COPY FILE WITH TRY-WITH-RESOURCES — CLEAN MODERN APPROACH
import [Link].*;
public class FileCopyAutoClose {
public static void main(String[] args) {
// Resources declared in try() are AUTOMATICALLY closed
try (FileInputStream fis = new FileInputStream("[Link]");
FileOutputStream fos = new FileOutputStream("[Link]")) {

int b;
while ((b = [Link]()) != -1) {
[Link](b);
}
[Link]("File copied");
} catch (IOException e) {
[Link]("I/O Error: " + [Link]());
}
// fis and fos are AUTOMATICALLY closed here — no finally needed
}
}
EXAM TIP: Try-with-resources is a modern Java best practice and a common exam question. Key
points: (1) Introduced in Java 7. (2) Resources are automatically closed at end of try block. (3)
Resources must implement AutoCloseable. (4) Multiple resources separated by semicolons. (5)
Eliminates resource leak bugs.

5. CHARACTER-BASED STREAMS
Character streams handle I/O of UNICODE TEXT DATA — sequences of 16-bit Unicode
characters. They are specifically designed for text files and automatically handle character
encoding/decoding (converting between bytes and characters). Always prefer character streams
over byte streams for text files.
The base classes are [Link] and [Link].
Class Type Purpose
FileReader Input Reads characters from a text file
FileWriter Output Writes characters to a text file
BufferedReader Input Buffered reading; has readLine()
method
BufferedWriter Output Buffered writing; has newLine()
method
InputStreamReader Bridge Converts byte stream to
character stream
OutputStreamWriter Bridge Converts character stream to
byte stream
PrintWriter Output Formatted text output (print,
println, printf)
StringReader Input Reads from String in-memory
StringWriter Output Writes to String buffer
Aspect Byte Streams Character Streams
Data unit byte (8 bits) char (16 bits, Unicode)
Best for Binary files (images, audio) Text files (.txt, .csv, .java)
Base classes InputStream / OutputStream Reader / Writer
Example pair FileInputStream / FileReader / FileWriter
FileOutputStream
Buffered version BufferedInputStream / BufferedReader / BufferedWriter
BufferedOutputStream
Character encoding Does not handle Handles automatically

6. FILE I/O USING CHARACTER STREAMS


6.1 FileWriter — Writing Text to a File
import [Link].*;

public class FileWriterExample {


public static void main(String[] args) {
try (FileWriter fw = new FileWriter("[Link]")) {
[Link]("Alice,101,85.5\n");
[Link]("Bob,102,90.0\n");
[Link]("Charlie,103,78.3\n");
[Link]("Data written to file");
} catch (IOException e) {
[Link]("Error: " + [Link]());
}
}
}
FileWriter constructor: new FileWriter("[Link]") — creates/overwrites file. new FileWriter("[Link]",
true) — opens in append mode (adds to existing content).

6.2 FileReader — Reading Text from a File


import [Link].*;

public class FileReaderExample {


public static void main(String[] args) {
try (FileReader fr = new FileReader("[Link]")) {
int ch;
while ((ch = [Link]()) != -1) { // read() returns char as int, -1 at
EOF
[Link]((char) ch);
}
} catch (FileNotFoundException e) {
[Link]("File not found: " + [Link]());
} catch (IOException e) {
[Link]("Read error: " + [Link]());
}
}
}

6.3 BufferedReader and BufferedWriter — Efficient Line-by-Line I/O


Buffered streams wrap around FileReader/FileWriter to add an internal buffer, reducing the number
of physical disk accesses (disk I/O is slow; reading/writing in chunks is much faster).
BufferedReader adds the crucial readLine() method — reads an entire line as a String.
import [Link].*;

public class BufferedIOExample {


public static void main(String[] args) {
// WRITE with BufferedWriter
try (BufferedWriter bw = new BufferedWriter(new FileWriter("[Link]")))
{
[Link]("Line 1: Introduction to Java");
[Link](); // platform-independent newline
[Link]("Line 2: OOP Concepts");
[Link]();
[Link]("Line 3: I/O Streams");
} catch (IOException e) { [Link](); }

// READ with BufferedReader


try (BufferedReader br = new BufferedReader(new FileReader("[Link]")))
{
String line;
int lineNum = 1;
while ((line = [Link]()) != null) { // readLine() returns null
at EOF
[Link](lineNum + ": " + line);
lineNum++;
}
} catch (IOException e) { [Link](); }
}
}
NOTE: [Link]() returns the content of the line WITHOUT the newline character. It returns null
(not -1 like byte read()) at end of file. Always check for null to detect EOF when using readLine().

7. INTERNAL ASSESSMENT SUPPORT — UNIT III


Viva Questions with Answers
Q1: What is the difference between byte streams and character streams?
Answer: Byte Streams operate on raw binary data in 8-bit bytes. Base classes: InputStream and
OutputStream. Suitable for binary files (images, audio, compiled code) or any file where you work at
the raw byte level. Key classes: FileInputStream, FileOutputStream. Character Streams operate on
Unicode text in 16-bit characters. Base classes: Reader and Writer. Suitable for text files — they
automatically handle character encoding (converting bytes to chars and vice versa). Key classes:
FileReader, FileWriter, BufferedReader, BufferedWriter. For text processing, ALWAYS use
character streams to avoid encoding issues.

Q2: What is try-with-resources and why is it important?


Answer: Try-with-resources (Java 7+) is a try statement that declares resources in parentheses
after the 'try' keyword. These resources are automatically closed when the try block exits, whether
normally or through an exception. Resources must implement AutoCloseable/Closeable. It is
important because: (1) Eliminates resource leaks (forgetting to close streams causes file locks and
memory leaks). (2) Simplifies code by removing finally{close()} boilerplate. (3) Properly handles the
case where both the try block AND the close() method throw exceptions (suppressed exceptions
mechanism).

Important Long Questions


26. What is a stream in Java? Explain byte streams and character streams with class
hierarchies. (10 marks)
27. Write a Java program to read from a file using FileReader and write to another file using
FileWriter. (10 marks)
28. Explain BufferedReader and BufferedWriter. Write a program to read a file line by line and
display with line numbers. (10 marks)
29. What is try-with-resources? How does it help in file handling? Rewrite a file copy program
using try-with-resources. (7 marks)
30. Write a Java program to copy the contents of one file to another using byte streams
(FileInputStream and FileOutputStream). (10 marks)

UNIT – IV: EXCEPTION HANDLING & MULTITHREADED


PROGRAMMING
1. UNIT INTRODUCTION
Unit IV covers two of Java's most powerful and professionally critical features: Exception Handling
— the mechanism that makes Java programs robust and resilient — and Multithreading — Java's
built-in ability to run multiple tasks concurrently. These features distinguish Java as an enterprise-
grade language and are essential knowledge for any professional Java developer.
Exam Weightage: Unit IV carries 20–25 marks. Exception hierarchy, try/catch/finally/throw/throws,
user-defined exceptions, thread lifecycle, and synchronisation are all very high-frequency exam
topics.
Reference: TB1 Chapters 17, 18

2. EXCEPTION HANDLING
2.1 What is an Exception?
An Exception is an ABNORMAL CONDITION or ERROR that arises during the execution of a
program, disrupting the normal flow of instructions. In Java, exceptions are objects — instances of
classes that extend [Link]. Exception handling is Java's structured mechanism for
detecting, reporting, and recovering from runtime errors.
Without exception handling: The JVM prints an error message and terminates the program abruptly
— no recovery, no cleanup, no user-friendly error message. With exception handling: The program
can detect the error, handle it gracefully, inform the user appropriately, perform cleanup operations,
and potentially continue executing.
Definition: An exception is an event that disrupts the normal flow of the program. In Java,
exceptions are objects representing error conditions, and the exception handling mechanism
provides a structured way to detect and respond to them.

2.2 Exception Class Hierarchy


All exception and error classes in Java extend [Link]. The hierarchy:
Throwable (root of all exceptions and errors)
├── Error: Serious problems that programs should NOT try to catch — usually JVM-level
problems. Examples: OutOfMemoryError, StackOverflowError, VirtualMachineError.
└── Exception: Conditions that programs SHOULD catch and handle.
├── RuntimeException (Unchecked): Programming errors — not enforced by compiler.
Examples: NullPointerException, ArrayIndexOutOfBoundsException, ClassCastException,
ArithmeticException.
└── Non-RuntimeException (Checked): Exceptional conditions that are EXPECTED and
MUST be handled. Compiler enforces either catch or declare (throws). Examples: IOException,
FileNotFoundException, SQLException, ClassNotFoundException.
Category Examples Compiler Enforced? Cause
Error OutOfMemoryError, No — should not catch JVM/system failure
StackOverflowError
Checked Exception IOException, YES — must catch or External factors
FileNotFoundException declare
, SQLException
Unchecked NullPointerException, No — optional to catch Programming bugs
(RuntimeException) ArrayIndexOutOfBound
s, ClassCastException

2.3 try, catch, finally


The fundamental try-catch-finally block is the core of Java exception handling:
try {
// Code that might throw an exception
// 'Risky' code goes here
} catch (ExceptionType1 e) {
// Handles ExceptionType1 and its subclasses
[Link]("Error: " + [Link]());
} catch (ExceptionType2 e) {
// Handles ExceptionType2
} catch (Exception e) {
// Handles any other Exception (catch-all — place LAST)
} finally {
// ALWAYS executes — whether exception occurred or not
// Used for cleanup (closing resources, releasing locks)
}
Important rules: Multiple catch blocks are allowed — the MOST SPECIFIC exception class must
come BEFORE the more general one. catch(Exception e) must be the LAST catch block (otherwise
it would catch everything before more specific handlers). The finally block ALWAYS executes —
even if: no exception occurs, an exception is caught, an exception is NOT caught (finally still runs
before propagation), or even if there's a return statement in try/catch.
COMPLETE EXCEPTION HANDLING EXAMPLE
import [Link];

public class DivisionExample {


public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
try {
[Link]("Enter numerator: ");
int num = [Link]();
[Link]("Enter denominator: ");
int den = [Link]();
int result = num / den; // ArithmeticException if den==0
[Link]("Result: " + result);
} catch (ArithmeticException e) {
[Link]("Cannot divide by zero: " + [Link]());
} catch (Exception e) {
[Link]("Unexpected error: " + [Link]());
} finally {
[Link]("Thank you for using calculator"); // always runs
[Link]();
}
}
}

2.4 throw Keyword


The throw keyword explicitly THROWS an exception from within the code. You 'throw' an exception
object to signal that an error condition has occurred. Used to: throw built-in exceptions for invalid
inputs, throw user-defined exceptions.
void validateAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative: " + age);
}
if (age > 150) {
throw new ArithmeticException("Unrealistic age: " + age);
}
[Link]("Valid age: " + age);
}

2.5 throws Keyword


The throws keyword is used in a method SIGNATURE to declare that the method might throw one
or more checked exceptions, which the CALLER must handle. It is a way of propagating exceptions
up the call stack rather than handling them locally.
// This method declares it might throw IOException
void readFile(String filename) throws IOException, FileNotFoundException {
FileReader fr = new FileReader(filename); // throws FileNotFoundException
// ... read file
[Link](); // throws IOException
}

// Caller MUST handle or re-declare


void processFile() throws IOException {
readFile("[Link]"); // must handle IOException or re-throw
}
// OR
void processFileSafe() {
try {
readFile("[Link]");
} catch (IOException e) {
[Link]("File error: " + [Link]());
}
}
Keyword Purpose Used in
try Encloses risky code that might Code block
throw exception
catch Handles a specific exception After try block
type
finally Always-execute cleanup code After catch block(s)
throw Explicitly throws an exception Inside a method body
object
throws Declares that a method might Method signature
throw exceptions
2.6 User-Defined Exceptions
Custom exception classes can be created by extending Exception (for checked exceptions) or
RuntimeException (for unchecked exceptions). User-defined exceptions allow you to create domain-
specific, meaningful error types that make your code more readable and maintainable.
// Custom checked exception
class InsufficientFundsException extends Exception {
private double amount;

InsufficientFundsException(double amount) {
super("Insufficient funds. Short by: ₹" + amount);
[Link] = amount;
}

double getAmount() { return amount; }


}

class BankAccount {
private double balance;

BankAccount(double balance) { [Link] = balance; }

void withdraw(double amount) throws InsufficientFundsException {


if (amount > balance) {
throw new InsufficientFundsException(amount - balance);
}
balance -= amount;
[Link]("Withdrew: ₹" + amount + ", Balance: ₹" + balance);
}
}

// Usage
BankAccount account = new BankAccount(1000);
try {
[Link](1500);
} catch (InsufficientFundsException e) {
[Link]([Link]()); // Insufficient funds. Short by: ₹500.0
}
EXAM TIP: User-defined exception is a common 10-mark question. Show: (1) A class extending
Exception or RuntimeException, (2) Constructor calling super(message), (3) Custom fields, (4) A
class that throws this exception, (5) Main method that catches it.

3. MULTITHREADED PROGRAMMING
3.1 Multithreading Fundamentals
Multithreading is the ability of a program to execute MULTIPLE THREADS concurrently. A Thread is
the smallest unit of execution within a process. Multithreading allows: Better utilisation of CPU
(especially multi-core processors). Improved responsiveness (UI remains active while background
tasks run). Efficient server handling (multiple client requests processed simultaneously).
Difference from Multitasking: Multitasking = multiple PROCESSES running concurrently (OS-level).
Multithreading = multiple THREADS within a SINGLE PROCESS running concurrently. Threads
within the same process share: heap memory, static variables, open files, and code segment. Each
thread has its own: stack, program counter, and registers.
Benefits: Improved performance on multi-core systems. Better resource utilisation. Responsive user
interfaces. Efficient server design (web servers handle each request in a separate thread).

3.2 Life Cycle of a Thread


A Java thread goes through the following states during its lifetime:
31. NEW: Thread object created with 'new Thread()' but start() has NOT been called. The thread
is not yet scheduled for execution.
32. RUNNABLE: Thread's start() method has been called. Thread is eligible to run — it may be
actually running (selected by OS scheduler) or waiting for its turn on the CPU. In Java,
there's no distinction between 'ready' and 'running' at the API level.
33. BLOCKED: Thread is waiting to acquire a monitor lock (to enter a synchronized
block/method that another thread currently holds).
34. WAITING: Thread is waiting indefinitely for another thread to perform a specific action.
Caused by: [Link](), [Link](). Can only be woken by another thread calling
notify()/notifyAll() or the joined thread completing.
35. TIMED_WAITING: Thread is waiting for a SPECIFIED TIME. Caused by: [Link](ms),
[Link](ms), [Link](ms).
36. TERMINATED (DEAD): Thread has finished execution — its run() method has returned, or
an uncaught exception terminated it. Cannot be restarted.
State transitions: NEW → RUNNABLE (start()). RUNNABLE → BLOCKED (waiting for lock).
RUNNABLE → WAITING (wait() or join()). RUNNABLE → TIMED_WAITING (sleep() or timed wait).
BLOCKED/WAITING/TIMED_WAITING → RUNNABLE (lock acquired, notify(), timeout expires).
RUNNABLE → TERMINATED (run() completes).
EXAM TIP: Thread lifecycle diagram is a guaranteed 5-mark or 7-mark question. Draw the states as
ovals connected by labeled arrows showing the method calls or events that cause each transition.
Show all 6 states clearly.

3.3 Creating Threads — Two Approaches


Method 1: Extending Thread Class
class MyThread extends Thread {
String taskName;
int count;

MyThread(String name, int count) {


[Link] = name;
[Link] = count;
}

@Override
public void run() { // run() defines the thread's task
for (int i = 1; i <= count; i++) {
[Link](taskName + ": iteration " + i),
try {
[Link](100); // pause 100ms
} catch (InterruptedException e) {
[Link](taskName + " interrupted");
}
}
[Link](taskName + " completed");
}
}

// Creating and starting threads


MyThread t1 = new MyThread("Task-A", 5);
MyThread t2 = new MyThread("Task-B", 3);
[Link](); // DO NOT call run() directly — that would NOT create a new thread
[Link](); // t1 and t2 run CONCURRENTLY

Method 2: Implementing Runnable Interface


class MyRunnable implements Runnable {
String taskName;

MyRunnable(String name) { [Link] = name; }

@Override
public void run() {
for (int i = 1; i <= 5; i++) {
[Link](taskName + ": " + i);
}
}
}

// Create Thread objects wrapping Runnable


MyRunnable r1 = new MyRunnable("Task-A");
MyRunnable r2 = new MyRunnable("Task-B");
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
[Link]();
[Link]();

// With lambda (Java 8+) — most concise way


Thread t3 = new Thread(() -> {
for(int i=1; i<=3; i++) [Link]("Lambda thread: " + i);
});
[Link]();
Aspect Extending Thread Implementing Runnable
Inheritance Uses up the single inheritance Leaves class free to extend
slot another class
Flexibility Less flexible — class IS a More flexible — class HAS a
Thread task
OOP Design Tight coupling (class is a thread) Better separation of concerns
Preferred? Simple cases Recommended — better design
Lambda support No Yes (Runnable is functional
interface)
NOTE: ALWAYS call start() not run() to create a new thread. Calling run() directly just executes the
method on the current thread — no new thread is created, no concurrency.

3.4 Thread Methods


Method Description
start() Starts the thread — creates new thread and calls
run()
run() Defines the thread's task — override this method
sleep(ms) Causes current thread to pause for specified
milliseconds; throws InterruptedException
join() Calling thread waits for THIS thread to finish
before continuing
join(ms) Waits at most ms milliseconds for thread to finish
isAlive() Returns true if thread has been started and not
yet terminated
getName() Returns thread's name
setName(name) Sets thread's name
getPriority() Returns thread's priority (1-10)
setPriority(n) Sets thread priority: MIN_PRIORITY=1,
NORM_PRIORITY=5, MAX_PRIORITY=10
interrupt() Interrupts a sleeping/waiting thread; causes
InterruptedException
currentThread() Static method — returns reference to currently
executing thread

THREAD METHODS DEMONSTRATION


class ThreadDemo extends Thread {
ThreadDemo(String name) { super(name); } // set thread name

public void run() {


[Link](getName() + " started");
try { [Link](500); } catch (InterruptedException e) {}
[Link](getName() + " finished");
}
}

ThreadDemo t1 = new ThreadDemo("Worker-1");


ThreadDemo t2 = new ThreadDemo("Worker-2");
[Link]();
[Link]();
[Link]("Main thread waiting for workers...");
try {
[Link](); // main thread waits for t1 to finish
[Link](); // then waits for t2 to finish
} catch (InterruptedException e) { [Link](); }
[Link]("All workers done. Main continues.");

4. SYNCHRONISATION
When multiple threads access SHARED RESOURCES (variables, objects, files) concurrently, they
may produce incorrect results — this is called a RACE CONDITION. Synchronisation is Java's
mechanism to ensure that only ONE THREAD at a time can execute a critical section of code that
accesses shared resources.
Java's synchronisation is based on the concept of a MONITOR (also called an intrinsic lock or
mutex). Every Java object has an associated monitor. When a thread enters a synchronized
block/method, it acquires the object's monitor — no other thread can enter any synchronized
block/method of the SAME OBJECT until the first thread releases the monitor.
RACE CONDITION DEMONSTRATION — WHY SYNCHRONISATION IS NEEDED
class Counter {
int count = 0;
void increment() {
count++; // NOT atomic: read count, add 1, write — 3 operations!
} // Two threads can interleave here → incorrect result
}
Counter c = new Counter();
Thread t1 = new Thread(() -> { for(int i=0;i<1000;i++) [Link](); });
Thread t2 = new Thread(() -> { for(int i=0;i<1000;i++) [Link](); });
[Link](); [Link](); [Link](); [Link]();
[Link]([Link]); // Expected: 2000, Actual: ??? (race condition!)

4.1 Synchronised Methods


Declaring a method with the 'synchronized' keyword ensures that only ONE THREAD can execute
that method on a GIVEN OBJECT at any time. The thread acquires the object's monitor when it
enters, and releases it when it exits.
class SyncCounter {
int count = 0;

synchronized void increment() { // synchronized method


count++; // Now only one thread at a time
}

synchronized int getCount() {


return count;
}
}

SyncCounter sc = new SyncCounter();


Thread t1 = new Thread(() -> { for(int i=0;i<1000;i++) [Link](); });
Thread t2 = new Thread(() -> { for(int i=0;i<1000;i++) [Link](); });
[Link](); [Link](); [Link](); [Link]();
[Link]([Link]()); // ALWAYS 2000 — race condition fixed!

4.2 Synchronised Statement (Synchronised Block)


Instead of synchronising the entire method, a synchronised block allows synchronising only a
SPECIFIC CRITICAL SECTION of code. This is more fine-grained and can improve performance —
threads only need to wait for the critical section, not the entire method.
class PartialSync {
int count = 0;
Object lock = new Object(); // separate lock object (or use 'this')

void doWork() {
// Non-critical code — multiple threads can run this simultaneously
[Link]([Link]().getName() + " working");

synchronized (this) { // synchronized block — only one thread at a time


count++; // critical section
}

// More non-critical code


}
}
Aspect Synchronized Method Synchronized Block
Scope Entire method Only specified block of code
Granularity Coarse — locks entire method Fine — locks only critical
section
Performance Lower if method has non-critical Higher — less lock contention
code
Lock object 'this' object (or class for static) Any object specified
Use when All method code is critical Only part of method is critical
EXAM TIP: Synchronisation is a guaranteed 10-mark question. Demonstrate: (1) Show the race
condition problem with code (incorrect count). (2) Fix it with synchronized method or block. (3)
Explain the monitor/lock concept. (4) Show join() to wait for threads. Common marks lost: not
showing the race condition first, not explaining WHY synchronisation is needed.

5. INTERNAL ASSESSMENT SUPPORT — UNIT IV


Viva Questions with Answers
Q1: What is the difference between checked and unchecked exceptions?
Answer: Checked Exceptions are exceptions that the COMPILER forces you to handle — either with
a try-catch block or by declaring them in the method signature with 'throws'. They extend Exception
but NOT RuntimeException. Examples: IOException, FileNotFoundException, SQLException. They
represent conditions outside the program's control (file not found, network error). Unchecked
Exceptions (RuntimeExceptions) are not enforced by the compiler — you may catch them but are
not required to. They extend RuntimeException. Examples: NullPointerException,
ArrayIndexOutOfBoundsException, ClassCastException. They typically represent programming
bugs that should be fixed, not caught.

Q2: What is the difference between throw and throws?


Answer: 'throw' is a STATEMENT inside a method body that ACTUALLY THROWS an exception
object: throw new IllegalArgumentException("Invalid"); The throw statement terminates the current
method immediately and propagates the exception up the call stack. 'throws' is a KEYWORD in the
METHOD SIGNATURE that DECLARES the checked exceptions that the method MIGHT throw:
void readFile() throws IOException { ... }; It tells callers what exceptions to expect and handle.
Simple memory aid: throw DOES it (actually throws); throws DECLARES it (announces what might
happen).

Q3: What happens if we call run() instead of start() for a thread?


Answer: Calling run() directly executes the run() method as a NORMAL METHOD CALL on the
CURRENT THREAD — no new thread is created. The code in run() executes sequentially on the
main thread (or whatever thread called run()), just like any regular method call. There is NO
concurrency. Only start() creates a new, independent OS thread and schedules it for execution. The
new thread then calls run() internally on its own execution context. This is why you must ALWAYS
call start() to achieve multithreading.

Important Long Questions


37. What is exception handling? Explain the exception class hierarchy. Differentiate between
checked and unchecked exceptions. (10 marks)
38. Explain try, catch, finally, throw, and throws with examples. (15 marks)
39. Write a Java program to create a user-defined exception class for insufficient funds in a bank
account. (10 marks)
40. What is multithreading? Explain the lifecycle of a thread with a diagram. (10 marks)
41. Explain the two ways to create threads in Java. Compare Thread class vs Runnable
interface. (10 marks)
42. What is synchronisation? Why is it needed? Explain synchronised methods and
synchronised blocks with code. (10 marks)
6-MONTH STUDY PLAN — JAVA PROGRAMMING
SMART & REALISTIC 6-MONTH ROADMAP
MONTH 1 — OOP FOUNDATIONS & JAVA BASICS (Unit I)
• Week 1-2: OOP concepts (class, object, encapsulation, inheritance, polymorphism,
abstraction). OOP vs Procedural table.
• Week 3: Java history, all 12 features, Java vs C++ comparison table, JDK/JVM/JRE
architecture diagram.
• Week 4: Data types, variables (scope and lifetime), operators, control structures with code
examples.
Action: Install JDK. Write and run: Hello World, simple calculator, array programs, basic OOP
classes. Run every code example by hand.

MONTH 2 — OOP IN DEPTH (Unit II Part 1)


• Week 1: Classes — constructors (all types), this keyword, access modifiers. Write 3
complete class programs.
• Week 2: static keyword (variable/method/block), final keyword, String class methods.
Practice 10 String programs.
• Week 3: Inheritance — all types, super keyword. Write multilevel and hierarchical inheritance
programs.
• Week 4: Method overriding, covariant return type, abstract class. Write shape hierarchy
program.

MONTH 3 — INTERFACES & POLYMORPHISM (Unit II Part 2)


• Week 1: Interfaces — creation, implementing, multiple interfaces. Compare abstract class vs
interface.
• Week 2: Packages — creation and import. Dynamic binding with complete animal/shape
polymorphism examples.
• Week 3: Method overloading vs overriding. Casting and instanceof. Generics.
• Week 4: Full Unit II revision. Write comprehensive programs using all OOP features
together.
Action: Write a mini-project: a Library Management System or Student Management System using
OOP concepts.

MONTH 4 — I/O STREAMS (Unit III)


• Week 1: Stream hierarchy. Byte streams — FileInputStream, FileOutputStream. Write file
copy program.
• Week 2: Character streams — FileReader, FileWriter, BufferedReader, BufferedWriter. Line-
by-line reading.
• Week 3: Try-with-resources. Practice all I/O programs until they can be written from memory.
• Week 4: Unit III revision. Write 5 different file I/O programs.

MONTH 5 — EXCEPTIONS & THREADS (Unit IV)


• Week 1: Exception hierarchy, checked vs unchecked, try/catch/finally with multiple
examples.
• Week 2: throw vs throws. User-defined exceptions. Nested try-catch.
• Week 3: Thread lifecycle (draw 10 times). Thread class approach. Runnable approach.
Thread methods.
• Week 4: Synchronisation — race condition demo → synchronized method → synchronized
block.

MONTH 6 — EXAM PREPARATION


• Week 1: Write full answers for top 10 exam questions — by hand, timed.
• Week 2: All comparison tables from memory. All code examples from memory.
• Week 3: One-page notes per unit. Keyword lists. Diagram practice (thread lifecycle, Java
architecture).
• Week 4: Solve 2-3 past papers. Final light revision.

LAST-DAY REVISION: QUICK SUMMARY — ALL 4 UNITS


UNIT I — KEY FACTS
• OOP: Class (blueprint), Object (instance), Encapsulation (data hiding), Inheritance (code
reuse), Polymorphism (many forms), Abstraction (hide complexity), Message Passing
• Procedural: top-down, data separate. OOP: bottom-up, data+behaviour together in objects.
• Java features: Simple, OOP, Platform-independent (WORA), Robust, Secure, Architecture-
neutral, Portable, High-performance (JIT), Multithreaded, Distributed, Dynamic, Interpreted
• JVM: executes bytecode (platform-specific). JRE = JVM + class libraries (to run). JDK = JRE
+ dev tools (to develop)
• Java code (.java) → javac → bytecode (.class) → JVM → native execution
• Java vs C++: no pointers, no multiple inheritance, no operator overloading, garbage
collection, 16-bit char, JVM
• Data types: byte(1B), short(2B), int(4B), long(8B), float(4B), double(8B), char(2B), boolean
• Variable scope: local (method), instance (object), static/class (class-level)

UNIT II — KEY FACTS


• Constructor: same name as class, no return type. Default, parameterised, copy constructor
types
• this: current object reference. super: parent class reference
• Access modifiers: private (class only) < default (package) < protected (package+subclass) <
public (everywhere)
• static: class-level. Can call without object. Cannot access instance members directly.
• final variable: constant. final method: cannot override. final class: cannot extend.
• String: immutable. Use .equals() not == for comparison.
• Inheritance types: Single, Multilevel, Hierarchical. Multiple: NOT supported (use interfaces).
• super(): call parent constructor (must be first line). @Override annotation for method
overriding.
• Abstract class: cannot instantiate, can have abstract+concrete methods, can have instance
variables.
• Interface: cannot instantiate, all methods public abstract (default), all fields public static final.
• Polymorphism: Overloading (compile-time, same class, different params) vs Overriding
(runtime, parent-child, same signature)
• Dynamic binding: Animal ref = new Dog(); → [Link]() calls DOG's sound at runtime
• instanceof: checks type before downcast. Generics: type-safe collections with <T>
UNIT III — KEY FACTS
• Stream: sequential data flow. Input = reading. Output = writing.
• Byte streams: InputStream/OutputStream. For binary data. FileInputStream,
FileOutputStream.
• Character streams: Reader/Writer. For text data. FileReader, FileWriter, BufferedReader,
BufferedWriter.
• read() returns int: byte value (0-255) or -1 at EOF (byte streams). char as int or -1 (char
streams).
• readLine(): reads full line as String, returns null at EOF. Only in BufferedReader.
• try-with-resources (Java 7+): auto-closes AutoCloseable resources. No finally needed for
close().
• FileWriter(file, true): append mode. FileWriter(file): overwrite mode.
• [Link](): platform-independent line separator.

UNIT IV — KEY FACTS


• Exception: abnormal runtime condition. Throwable → Error (don't catch) / Exception (catch)
• Checked: compiler-enforced (IOException, FileNotFoundException, SQLException). Must
catch or declare throws.
• Unchecked (RuntimeException): not enforced (NullPointerException,
ArrayIndexOutOfBoundsException, ClassCastException).
• try{risky} catch(Type e){handle} finally{always runs}
• Most specific exception class must come BEFORE general in multiple catch blocks.
• throw: actually throws exception object. throws: declares method might throw (in signature).
• User-defined: extend Exception (checked) or RuntimeException (unchecked). Call
super(message) in constructor.
• Thread states: NEW → RUNNABLE ← BLOCKED/WAITING/TIMED_WAITING →
TERMINATED
• Create thread: extend Thread (override run()) OR implement Runnable (implement run(),
wrap in Thread).
• ALWAYS call start() not run(). start() creates new thread; run() is just a method call.
• Thread methods: sleep(ms), join(), isAlive(), getName(), getPriority(), interrupt()
• Race condition: multiple threads accessing shared data → incorrect results.
• synchronized method: only one thread can execute per object at a time.
• synchronized block: finer granularity — lock only critical section, not whole method.

TOP 10 EXAM QUESTIONS — JAVA


43. OOP concepts with definitions and code examples for each (10 marks)
44. Java features — explain any 8 (10 marks)
45. JDK, JVM, JRE — differences and Java execution process diagram (10 marks)
46. Java vs C++ comparison table — 8+ parameters (10 marks)
47. Constructors — all types with code + this and super keywords (10 marks)
48. Abstract class vs Interface — full comparison table + code examples (10 marks)
49. Method overloading vs method overriding — differences + code examples (10 marks)
50. Dynamic binding / runtime polymorphism — code demonstration (10 marks)
51. Exception handling — hierarchy, try/catch/finally/throw/throws, user-defined exception
program (15 marks)
52. Multithreading — lifecycle diagram, creating threads (both methods), synchronisation with
race condition demo (15 marks)

You might also like