0% found this document useful (0 votes)
4 views119 pages

java core basics

The document provides an overview of key Java concepts including JDK, JRE, and JVM, detailing the Java program execution flow from writing code to execution. It explains Java program structure, variables, data types, operators, and naming conventions, along with examples of code and command-line arguments. Additionally, it covers type conversion, memory allocation, and bitwise operators, emphasizing the importance of understanding these fundamentals for effective Java programming.

Uploaded by

solomon masih
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)
4 views119 pages

java core basics

The document provides an overview of key Java concepts including JDK, JRE, and JVM, detailing the Java program execution flow from writing code to execution. It explains Java program structure, variables, data types, operators, and naming conventions, along with examples of code and command-line arguments. Additionally, it covers type conversion, memory allocation, and bitwise operators, emphasizing the importance of understanding these fundamentals for effective Java programming.

Uploaded by

solomon masih
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
You are on page 1/ 119

• Query successful

Try again without apps

Here are the notes from the lecture on JDK, JRE, JVM, and Java program execution:

Key Concepts:

• JDK (Java Development Kit)

o Includes tools and libraries for writing Java code, such as the debugger and javac
compiler.

o Contains the JRE.

• JRE (Java Runtime Environment)

o Provides an environment to run Java programs.

o Contains the JVM.

• JVM (Java Virtual Machine)

o The final component where Java programs are executed.

o Converts bytecode into machine code.

o Interprets bytecode line by line.

Java Program Execution Flow:

1. Writing Java Code:

o Java programs are written in files with a .java extension (e.g., Test.java).

2. Compilation to Bytecode:

o The javac compiler converts the .java file into bytecode, which has a .class extension
(e.g., Test.class).

o Bytecode is platform-independent, meaning it can run on different operating systems


like Windows or Mac.

3. Execution by JVM:

o The JVM takes the bytecode and converts it into machine code, which is platform-
dependent (specific to the operating system).

o The JVM interprets the bytecode line by line.

o Just-In-Time (JIT) Compiler: Within the JVM, a JIT compiler optimizes frequently
used code blocks by compiling them into machine code, avoiding repeated
interpretation. This makes the execution faster for those specific blocks.

Code Example: "Hello World" Program

Java

class Test {
public static void main(String[] args) {

System.out.println("Hello World");

Steps to Compile and Run the Program:

1. Save the file: Save the code as Test.java in a designated folder.

2. Open Command Prompt: Navigate to the folder where the Test.java file is saved.

3. Compile the Java file: Use the javac command followed by the filename.

Bash

javac Test.java

o This command creates a Test.class file (bytecode) in the same directory.

4. Run the Java program: Use the java command followed by the class name (without the .class
extension).

Bash

java Test

o This command executes the bytecode through the JVM, printing "Hello World" to the
console.

The javac and java tools are located in the bin directory of the JDK installation. When running java
Test, you do not need to specify .class because the JVM expects a class file.

• Query successful

Try again without apps

Understanding the Java Program Structure

• Class Definition

o In Java, all code resides within a class.

o A class acts as a blueprint for creating objects (e.g., a student, a car, a laptop).

o It defines the properties (like name, roll number for a student) that an object of that
class will have.

o The example uses class Test, where Test is the name of the class.

• The main Method

o public static void main(String[] args) is the entry point of any Java program.

o It has a specific "signature" that cannot be changed, otherwise the program will not
run.
o public: This is an access modifier, meaning the method can be accessed from outside
the class. The Java Virtual Machine (JVM) needs to access this method directly.

o static: This keyword indicates that the method belongs to the class itself, not to an
instance (object) of the class. This allows the JVM to call the main method directly
using Test.main() without creating an object of the Test class.

o void: This specifies that the method does not return any value.

o main: This is the name of the method.

o String[] args: This means the method accepts an array of strings as parameters.
These are used to pass command-line arguments to the program.

• Printing to the Console (System.out.println)

o System.out.println("Hello World"); is used to print output to the console.

o System is a class in Java's java.lang package that provides access to system resources,
including the console.

o out is an object of the PrintStream class within the System class.

o println() is a method that prints the given string to the console and then moves to
the next line.

• Semicolons

o In Java, a semicolon (;) is used to indicate the end of a statement. It helps the
compiler understand the structure of the code.

Code Example: Passing Command-Line Arguments

Initial Code:

Java

class Test {

public static void main(String[] args) {

System.out.println("Hello World");

Running the program without arguments:

• Compile: javac Test.java

• Run: java Test

• Output: Hello World

Modified Code to use Command-Line Arguments:

The args array can be used to access arguments passed during execution.
Java

class Test {

public static void main(String[] args) {

System.out.println("Hello World");

// Accessing the first argument

System.out.println(args[0]);

// Accessing the second argument

System.out.println(args[1]);

Running the program with arguments:

• Compile: javac Test.java

• Run: java Test apple mango

• Output:

• Hello World

• apple

• mango

The apple and mango are passed as command-line arguments and are stored in the args array, which
can then be accessed within the main method.

Variables and Data Types in Java

What are Variables?

• Variables are used to store data when coding.

• Similar to variables in mathematics (e.g., x = 1, y = 2), they hold data.

• In Java, variables can store various types of data, such as names, salaries, or ages, unlike in
math where they primarily store numbers.

Primitive Data Types

The lecture introduces four main categories of primitive data types:

1. Whole Numbers (Integral Numbers)

o Used for numbers without decimal points.

o Can store negative values.

o Data Types:

▪ byte: Smallest capacity, like a small cup.


▪ Range: -128 to 127.

▪ Example: byte age1 = 20;

▪ short: Larger than byte.

▪ Example: short age3 = 20;

▪ int: Commonly used, larger than short.

▪ Example: int age = 20;

▪ long: Largest capacity, like a bucket.

▪ Requires an L suffix if the number exceeds int's range.

▪ Example: long age4 = 20L;

o The choice of data type depends on the required capacity, similar to choosing a glass
size for a drink.

o You don't need to memorize the exact ranges; they can be easily found using
Byte.MIN_VALUE, Byte.MAX_VALUE, etc.

2. Decimal Numbers

o Used for numbers with decimal points.

o Data Types:

▪ float: Stores smaller decimal numbers and offers less precision (approx. 7
decimal digits).

▪ Requires an f suffix.

▪ Example: float mySalary = 1000.12345f;

▪ double: Stores larger decimal numbers and offers more precision (around 15
decimal digits).

▪ Default for decimal numbers in Java.

▪ Example: double yourSalary = 1000.123456789012345;

o Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE can


be used to check ranges.

3. Characters (char)

o Used to store single characters, symbols, or numbers.

o Enclosed in single quotes (' ').

o Example: char initial = 'A';

o Characters are stored as numerical values (Unicode) in memory.

o You can convert a char to an int to see its Unicode value (e.g., 'A' is 65).
o Range of char in Java is from 0 to 65535, allowing for a wide variety of characters
from different languages and symbols.

o Can also be represented using Unicode escape sequences (e.g., \u2764 for a heart
symbol).

o ASCII values (0-127) are a subset of Unicode.

4. Booleans (boolean)

o Used to store true or false values.

o true and false are reserved keywords, not strings.

o Example: boolean isEligible = true;

Type Conversion (Casting)

The lecture also explains how data types are converted in Java:

• Widening Conversion (Implicit/Automatic Conversion)

o Occurs when converting a smaller data type to a larger, compatible data type.

o No data loss occurs.

o Java performs this conversion automatically.

o Examples:

▪ int to long: long b = a; (where a is an int)

▪ int to float: float c = a;

▪ char to int: int charValue = 'A';

▪ char to float: float floatCharValue = 'A';

• Narrowing Conversion (Explicit Conversion)

o Occurs when converting a larger data type to a smaller data type.

o Potential for data loss.

o Requires explicit casting using parentheses () before the variable.

o Examples:

▪ float to int: int g = (int) f; (where f is a float)

▪ double to float: float floatValue = (float) doubleValue;

▪ long to int: int b = (int) a; (where a is a long)

Memory Allocation (Bytes)

• byte: 1 byte

• short: 2 bytes

• int: 4 bytes
• long: 8 bytes

• float: 4 bytes

• double: 8 bytes

• char: 2 bytes

• boolean: 1 bit

• Query successful

Try again without apps

Rules for Naming Variables in Java

• Case Sensitivity

o Variable names in Java are case-sensitive. For example, amount and Amount would
be treated as two different variables.

o Using a variable with a different case than its declaration will result in an error, as the
system won't recognize it.

• Allowed Characters

o Variable names can include letters, numbers, underscores (_), and dollar signs ($).

o Example: myName, my$Name, name43.

o Other characters like &, (, -, or spaces are not allowed.

• Starting Character

o A variable name cannot start with a number.

o It must start with a letter, an underscore (_), or a dollar sign ($).

o Example: _myName is valid, my$Name is valid, but 1MyName is not.

• Reserved Keywords

o You cannot use Java's reserved keywords as variable names.

o Keywords like String, int, class, public, static, and void have special meanings in Java
and cannot be used for variable naming.

o There's no need to memorize all reserved keywords; you'll become familiar with
them as you code.

Naming Conventions (Best Practices):

• Camel Case

o For variable names consisting of multiple words, use camel case.

o The first letter of the first word should be lowercase, and the first letter of
subsequent words should be uppercase.

o Example: Instead of full_name (snake case, common in Python), use fullName.


o Another Example: myFullName. This makes the variable name easier to read.

• Meaningful Names

o Always use meaningful names for your variables.

o Avoid generic names like x or xx.

o Meaningful names improve code readability and maintainability, especially when


working in a team or on collaborative projects.

• Query successful

Try again without apps

Arithmetic Operators

Arithmetic operators are used to perform mathematical operations.

• Addition (+):

o Example: salary + bonus

o When mixing data types (e.g., int and double), Java automatically converts the
smaller data type to the larger one to avoid data loss. For instance, an int will be
converted to a double if added to a double.

o Similarly, long values can be converted to float if the float can hold larger values due
to scientific notation, though this might lead to precision loss.

• Subtraction (-):

o Example: salary - deduction

o Similar data type promotion rules apply as with addition.

• Multiplication (*):

o Example: monthlyTotal * 12

o Be cautious when multiplying large numbers, as the result might exceed the range of
an int and require a long to prevent overflow.

o If one operand is a long, the other operand (even an int literal) will be automatically
promoted to long before multiplication.

• Division (/):

o Example: yearlyTotal / 3

o When dividing two integers, the result will also be an integer, truncating any decimal
part.

o If one of the operands is a double, the result will be a double.

o Dividing by zero results in an ArithmeticException.

• Modulus (%):
o Returns the remainder of a division.

o Example: int remainder = a % b;

o Dividing by zero with the modulus operator also results in an ArithmeticException.

Operator Precedence

Operator precedence determines the order in which operations are performed in an expression.

• Parentheses () have the highest precedence.

• Multiplication (*), Division (/), and Modulus (%) have higher precedence than addition and
subtraction.

• If operators have the same precedence (e.g., multiplication and division), they are evaluated
from left to right.

• Increment (++) and Decrement (--) operators have the highest precedence.

Compound Assignment Operators

These operators provide a shorthand for performing an operation and assigning the result back to
the same variable.

• Addition Assignment (+=): a += 1 is equivalent to a = a + 1.

• Subtraction Assignment (-=): a -= 1 is equivalent to a = a - 1.

• Multiplication Assignment (*=): a *= 2 is equivalent to a = a * 2.

• Division Assignment (/=): a /= 2 is equivalent to a = a / 2.

• Modulus Assignment (%=): a %= 2 is equivalent to a = a % 2.

• Implicit Casting: Compound assignment operators automatically perform implicit casting,


preventing compilation errors that might occur with explicit assignments when mixing data
types (e.g., byte and int).

Increment and Decrement Operators

These operators increase or decrease a variable's value by one.

• Increment (++):

o Post-increment (a++): The value of the variable is used first, then incremented.

Java

int a = 99;

int b = a++; // b becomes 99, then a becomes 100

System.out.println(b); // Output: 99

System.out.println(a); // Output: 100

o Pre-increment (++a): The value of the variable is incremented first, then used.

Java
int a = 99;

int b = ++a; // a becomes 100, then b becomes 100

System.out.println(b); // Output: 100

System.out.println(a); // Output: 100

• Decrement (--):

o Post-decrement (a--): The value of the variable is used first, then decremented.

o Pre-decrement (--a): The value of the variable is decremented first, then used.

Comments

• In Java, two forward slashes (//) are used to create a single-line comment. Any text after //
on that line will be ignored by the compiler.

• Query successful

Try again without apps

Bitwise Operators in Java

This lecture provides an in-depth explanation of bitwise operators in Java, covering their purpose,
how they work, and various types.

What are Bitwise Operators?

• Computers store data in binary (0s and 1s). For example, the integer 5 is stored as its binary
equivalent, 101.

• Bitwise operators are used to directly manipulate these individual bits (0s and 1s) of a
number.

• They are faster than arithmetic operators because they operate directly on the bits of a
number.

• Operands: Bitwise operations can only be applied to integral values such as byte, short, int,
and long. They cannot be used with decimal numbers (floating-point numbers) because their
bits are divided into parts (sign, exponent, significant), making direct manipulation difficult.

Types of Bitwise Operators:

1. AND Operator (&)

o Purpose: Performs a bitwise AND operation on corresponding bits of two numbers.

o Rule: The result bit is 1 only if both corresponding bits are 1; otherwise, it's 0. This
can be thought of as multiplication.

o Truth Table:

▪ 0&0=0

▪ 0&1=0

▪ 1&0=0
▪ 1&1=1

o Code Example:

Java

int c = 5 & 4; // Binary of 5 is 101, Binary of 4 is 100

System.out.println(c); // Output: 4 (because 101 & 100 = 100, which is 4 in decimal)

2. OR Operator (|)

o Purpose: Performs a bitwise OR operation on corresponding bits of two numbers.

o Rule: The result bit is 1 if at least one of the corresponding bits is 1; otherwise, it's 0.

o Truth Table:

▪ 0|0=0

▪ 0|1=1

▪ 1|0=1

▪ 1|1=1

o Code Example:

Java

int c = 5 | 7; // Binary of 5 is 101, Binary of 7 is 111

System.out.println(c); // Output: 7 (because 101 | 111 = 111, which is 7 in decimal)

3. XOR Operator (^)

o Purpose: Performs a bitwise XOR (exclusive OR) operation on corresponding bits of


two numbers.

o Rule: The result bit is 1 if the corresponding bits are different; otherwise, it's 0.

o Truth Table:

▪ 0^0=0

▪ 0^1=1

▪ 1^0=1

▪ 1^1=0

o Code Example:

Java

int c = 5 ^ 7; // Binary of 5 is 101, Binary of 7 is 111

System.out.println(c); // Output: 2 (because 101 ^ 111 = 010, which is 2 in decimal)

4. NOT Operator (~)


o Purpose: Inverts all the bits of a single number.

o Rule: 0 becomes 1, and 1 becomes 0.

o Code Example:

Java

int a = 5; // Binary of 5 is ...000101 (assuming 32 bits)

int c = ~a;

System.out.println(c); // Output: -6

System.out.println(Integer.toBinaryString(c)); // Binary of -6 is ...111010

o Explanation: For positive numbers, the NOT operator results in -(original_number +


1). This is due to how negative numbers are represented in two's complement form.

5. Left Shift Operator (<<)

o Purpose: Shifts the bits of a number to the left by a specified number of positions.

o Rule: Bits shifted off to the left are discarded, and zeros are filled in from the right.

o Effect: Shifting left by n positions is equivalent to multiplying the number by 2^n.

o Code Example:

Java

int a = 5; // Binary of 5 is 101

int c = a << 1; // Shift 5 left by 1 position

System.out.println(c); // Output: 10 (Binary of 10 is 1010)

Java

int a = 5; // Binary of 5 is 101

int c = a << 2; // Shift 5 left by 2 positions

System.out.println(c); // Output: 20 (Binary of 20 is 10100)

6. Right Shift Operator (>>)

o Purpose: Shifts the bits of a number to the right by a specified number of positions.

o Rule: Bits shifted off to the right are discarded. The leftmost bit (sign bit) is filled with
the original sign bit (0 for positive, 1 for negative).

o Effect: Shifting right by n positions is equivalent to dividing the number by 2^n.

o Code Example (Positive Number):

Java

int a = 5; // Binary of 5 is 101

int c = a >> 1; // Shift 5 right by 1 position


System.out.println(c); // Output: 2 (Binary of 2 is 10)

o Code Example (Negative Number):

Java

int a = -5; // Binary of -5 (two's complement)

int c = a >> 2; // Shift -5 right by 2 positions

System.out.println(c); // Output: -2 (The leftmost bits are filled with 1s to preserve the negative sign)

7. Unsigned Right Shift Operator (>>>)

o Purpose: Shifts the bits of a number to the right by a specified number of positions,
filling the leftmost bits with zeros, regardless of the original sign.

o Rule: Bits shifted off to the right are discarded, and zeros are always filled in from the
left.

o Difference from >>: Unlike >>, this operator does not preserve the sign of the
number. It always fills with zeros, potentially turning a negative number into a
positive one.

o Code Example:

Java

int a = -5; // Binary of -5 (two's complement)

int c = a >>> 2; // Shift -5 right by 2 positions, filling with zeros

System.out.println(c); // Output: A large positive number (because the leading 1s are replaced by 0s)

Outputting to the Console in Java

This lecture covers the different ways to print output to the console in Java, specifically focusing on
System.out.println, System.out.print, and System.out.printf.

System.out.println

• Purpose: Used to print data to the console and then move the cursor to the next line.

• System Class: A class in Java that contains utility methods for interacting with the system's
runtime environment. This environment is the infrastructure provided by the JRE (Java
Runtime Environment).

o Example of a System method: System.getenv(), which retrieves environment


variables as a map.

• out: A static member of the System class that is connected to the console. It's used to print
anything to the console.
• Overloaded Methods: println has multiple overloaded versions, meaning it can accept
various data types as arguments (e.g., integers, characters, strings, long).

• Empty println(): Calling println() without any arguments will print a blank line.

Java

System.out.println(1); // Prints 1 and moves to the next line

System.out.println('x'); // Prints x and moves to the next line

System.out.println(); // Prints a blank line

System.out.println("Hello"); // Prints Hello and moves to the next line

• Concatenation with +:

o When used with numbers, + performs addition.

Java

int a = 1;

int b = 2;

System.out.println(a + b); // Output: 3

o When used with strings, + performs concatenation.

Java

System.out.println("Hello" + " " + "World"); // Output: Hello World

o When mixing strings and numbers, the numbers are converted to strings and then
concatenated.

Java

int a = 1;

int b = 2;

String c = "Sum";

System.out.println(a + b + c); // Output: 3Sum (a+b is evaluated first)

System.out.println(c + a + b); // Output: Sum12 (c+a is evaluated first, then concatenated with b)

o Parentheses () can be used to control the order of operations due to their higher
precedence.

Java

String c = "Sum";

int a = 1;

int b = 2;

System.out.println(c + (a + b)); // Output: Sum3


System.out.println("Sum of " + a + " and " + b + " is " + (a + b)); // Output: Sum of 1 and 2 is 3

System.out.print

• Purpose: Similar to println, but it does not add a new line character at the end. The cursor
remains on the same line after printing.

Java

System.out.print(1); // Prints 1

System.out.print('x'); // Prints x on the same line

System.out.print("Hello"); // Prints Hello on the same line

// Output: 1xHello

System.out.printf

• Purpose: Provides formatted output, similar to the printf function in C. It allows for multiple
arguments and uses format specifiers as placeholders.

• Format Specifiers (Placeholders):

o %s: For strings

o %d: For integers

o %f: For floating-point numbers

o %c: For characters

o %b: For booleans

o %e: For exponential format of floating-point numbers

• No New Line by Default: Like print, printf does not add a new line character at the end. To
add a new line, use \n.

• Example:

Java

String c = "Sum";

int a = 1;

int b = 2;

System.out.printf("Sum of %d and %d is %d\n", a, b, a + b); // Output: Sum of 1 and 2 is 3

System.out.printf("Character: %c, Float: %f\n", 'd', 1.2f); // Output: Character: d, Float: 1.200000

• Controlling Decimal Places: For floating-point numbers, you can specify the number of
decimal places using %.nf (where n is the number of decimal places).

Java

System.out.printf("Float with one decimal: %.1f\n", 1.2f); // Output: Float with one decimal: 1.2
System.out.printf("Float with two decimals: %.2f\n", 1.2f); // Output: Float with two decimals: 1.20

• Locale: printf can also take a Locale object as an argument to format numbers and dates
according to specific geographical conventions.

Java

import java.util.Locale;

// ...

double number = 123456.789;

System.out.printf(Locale.US, "US Format: %,.2f\n", number); // Example: 123,456.79

System.out.printf(Locale.GERMANY, "German Format: %,.2f\n", number); // Example: 123.456,79

• Query successful

Try again without apps

String Data Type in Java

This lecture focuses on the String data type in Java, contrasting it with primitive data types and
explaining its underlying structure and memory management.

String Data Type Basics

• Definition: A String is a sequence of characters. Unlike single characters stored using char,
strings are used for multiple characters like names or city names.

• Declaration:

o Strings are declared using the String keyword, followed by a variable name, and the
value enclosed in double quotes.

o Example: String name = "Vipul";

• Contrast with Primitive Data Types:

o The video reviews primitive data types like int, char, and boolean.

o Key Difference: String is not a primitive data type; it is a class in Java. This means
String variables are reference variables, not directly storing the value like primitives.

Understanding Classes and Objects (Overview)

• Class as a Blueprint: A class is a blueprint for creating objects. It defines the properties
(variables) and behaviors (methods) that objects of that class will have.

o Example: A Student class can have properties like name (String), address (String),
standard (int), and rollNumber (int).

• Object Creation: Objects are instances of a class. They are created using the new keyword.
o Example: Student student = new Student(); creates a new Student object.

• Accessing Object Properties: You can access an object's properties using the dot operator.

o Example: student.name = "Vipul";

Memory Management for Strings

• Heap Memory: When an object is created using new, memory is allocated for it in the Heap
memory. The Heap is a portion of memory provided by the operating system for the JVM to
store objects.

• Reference Variables: When you declare a String variable (or any object), it's a reference
variable. It doesn't store the actual object but rather the memory address of where the
object is stored in the Heap.

o Contrast with Primitives: For primitive types (e.g., int a = 1;), the variable a directly
stores the value 1 in its allocated memory.

Ways to Create Strings and Their Memory Implications

There are two primary ways to create String objects in Java:

1. Using the new keyword:

o Syntax: String variableName = new String("value");

o Memory Behavior: Each time new String() is used, a new object is created in the
Heap memory, even if the string literal value is the same.

o Example:

Java

String a = new String("Ram");

String b = new String("Ram");

System.out.println(a == b); // Output: false (because 'a' and 'b' point to different memory locations)

2. Using String Literals (Directly assigning a value):

o Syntax: String variableName = "value";

o Memory Behavior: Java uses a special area in the Heap called the String Pool (or
String Constant Pool) for string literals.

▪ If a string literal already exists in the String Pool, Java reuses the existing
object and returns its reference.

▪ If the literal doesn't exist, a new object is created in the String Pool.

o Example:

Java

String c = "Ram";

String d = "Ram";
System.out.println(c == d); // Output: true (because 'c' and 'd' point to the same memory location in
the String Pool)

Comparing Strings (== vs. .equals())

• The == operator, when used with String objects, compares their memory references
(addresses), not their actual content.

• To compare the actual content (equality of characters) of two strings, you should use the
.equals() method, which will be covered in the next video.

Code Examples and Setup

• The video demonstrates setting up a new Java project in IntelliJ IDEA to organize code
examples for different lectures.

• A TestString class is created to show basic string declaration and printing.

• A Student class is created as an example of a custom class with properties.

• A TestStudent class demonstrates creating Student objects and accessing their properties.

• Query successful

Try again without apps

String Methods in Java

This lecture provides a comprehensive guide to various String methods in Java. The instructor
explains each method with examples and demonstrates their usage.

String Methods Covered:

• length():

o Returns the length of the string (number of characters).

o Example:

Java

String name = "Ram";

int length = name.length(); // length will be 3

System.out.println(length); // Output: 3

For "Akshit Sharma", the length is 13.

• charAt(int index):

o Returns the character at the specified index.

o Indexes start from 0.

o An IndexOutOfBoundsException occurs if the index is negative or greater than or


equal to the string's length.

o The valid index range is from 0 to length() - 1.


o Example:

Java

String name = "Akshit Sharma";

char charAtIndex5 = name.charAt(5); // charAtIndex5 will be 't'

System.out.println(charAtIndex5); // Output: t

char charAtIndex0 = name.charAt(0); // charAtIndex0 will be 'A'

System.out.println(charAtIndex0); // Output: A

char lastChar = name.charAt(name.length() - 1); // lastChar will be 'a'

System.out.println(lastChar); // Output: a

• equals(String anotherString):

o Compares two strings for equality, considering case.

o Returns true if the strings are identical, false otherwise.

o Unlike ==, which checks for reference equality (if two objects are the same in
memory), equals() checks for content equality.

o Example:

Java

String name = "Akshit Sharma";

String name2 = "Akshit Sharma";

System.out.println(name.equals(name2)); // Output: true

String name3 = "AkshitSharma"; // Space removed

System.out.println(name.equals(name3)); // Output: false

String name4 = "Akshit sharma"; // 's' is lowercase

System.out.println(name.equals(name4)); // Output: false

• equalsIgnoreCase(String anotherString):

o Compares two strings for equality, ignoring case differences.

o Example:

Java

String name = "Akshit Sharma";

String name4 = "Akshit sharma";


System.out.println(name.equalsIgnoreCase(name4)); // Output: true

• compareTo(String anotherString):

o Compares two strings lexicographically (based on the Unicode value of each


character).

o Returns an integer value:

▪ A negative integer if the calling string is lexicographically less than the


argument string.

▪ Zero if the strings are lexicographically equal.

▪ A positive integer if the calling string is lexicographically greater than the


argument string.

o The comparison is based on the difference in ASCII values of the first differing
characters.

o Example:

Java

String str1 = "remote";

String str2 = "car";

System.out.println(str1.compareTo(str2)); // Output: 15 (ASCII of 'r' - ASCII of 'c')

System.out.println(str2.compareTo(str1)); // Output: -15 (ASCII of 'c' - ASCII of 'r')

System.out.println(str1.compareTo(str1)); // Output: 0

String str3 = "ramote"; // 'a' instead of 'e'

System.out.println(str2.compareTo(str3)); // Output: -4 (ASCII of 'a' - ASCII of 'e')

o ASCII Values Example:

Java

System.out.println('r' + 0); // Output: 114

System.out.println('c' + 0); // Output: 99

System.out.println('a' + 0); // Output: 97

System.out.println('e' + 0); // Output: 101

• compareToIgnoreCase(String str):

o Compares two strings lexicographically, ignoring case differences.

o Example:

Java
String a = "Random";

String b = "random";

System.out.println(a.compareTo(b)); // Output: -32 (ASCII of 'R' - ASCII of 'r')

System.out.println(a.compareToIgnoreCase(b)); // Output: 0

• substring(int beginIndex):

o Returns a new string that is a substring of this string. The substring begins at the
specified beginIndex and extends to the end of the string.

o Example:

Java

String name = "Amar Panchal";

System.out.println(name.substring(5)); // Output: Panchal (starts from index 5)

• substring(int beginIndex, int endIndex):

o Returns a new string that is a substring of this string. The substring begins at the
specified beginIndex and extends to the character at endIndex - 1. The character at
endIndex is excluded.

o Example:

Java

String name = "Amar Panchal";

System.out.println(name.substring(5, 8)); // Output: Pan (from index 5 up to, but not including, index
8)

o Using name.length() as endIndex is valid because endIndex is exclusive.

• toUpperCase():

o Converts all characters in the string to uppercase.

o Example:

Java

String name = "Amar Panchal";

System.out.println(name.toUpperCase()); // Output: AMAR PANCHAL

• toLowerCase():

o Converts all characters in the string to lowercase.

o Example:

Java

String name = "Amar Panchal";


System.out.println(name.toLowerCase()); // Output: amar panchal

• trim():

o Returns a new string with leading and trailing whitespace removed.

o Example:

Java

String name = " Amar Panchal ";

System.out.println(name.trim()); // Output: Amar Panchal

o Important Note: All string methods return a new string. The original string remains
unchanged because strings are immutable in Java. This immutability is crucial for
optimization, especially with the String Pool.

• replace(CharSequence target, CharSequence replacement):

o Returns a new string resulting from replacing all occurrences of target with
replacement.

o Example:

Java

String name = "Amar Panchal";

String newName = name.replace("Panchal", "Sharma"); // 'P' must match case

System.out.println(newName); // Output: Amar Sharma

String nameWithMultiple = "Amar Panchal Amar Panchal";

System.out.println(nameWithMultiple.replace("Panchal", "Sharma")); // Output: Amar Sharma Amar


Sharma

// Replacing a character

System.out.println(name.replace('a', 'o')); // Output: Amor Ponchol

o Method chaining is possible as replace() returns a String.

Java

String name = "Amar Panchal";

System.out.println(name.replace('a', 'o').toUpperCase()); // Output: AMOR PONCHOL

• contains(CharSequence s):

o Returns true if this string contains the specified sequence of characters, false
otherwise.

o Can check for both characters and substrings.


o Example:

Java

String name = "Amar Panchal";

System.out.println(name.contains("Pan")); // Output: true

System.out.println(name.contains("p")); // Output: false (case-sensitive)

• startsWith(String prefix):

o Tests if this string starts with the specified prefix. Case-sensitive.

o Example:

Java

String name = "Amar Panchal";

System.out.println(name.startsWith("Am")); // Output: true

System.out.println(name.startsWith("am")); // Output: false

• endsWith(String suffix):

o Tests if this string ends with the specified suffix. Case-sensitive.

o Example:

Java

String name = "Amar Panchal";

System.out.println(name.endsWith("al")); // Output: true

System.out.println(name.endsWith("Al")); // Output: false

• isEmpty():

o Returns true if the string has a length of 0, false otherwise.

o Does not consider strings with only whitespace as empty.

o Example:

Java

String str = "";

System.out.println(str.isEmpty()); // Output: true

String strWithSpace = " ";

System.out.println(strWithSpace.isEmpty()); // Output: false

• isBlank():
o Returns true if the string is empty or contains only whitespace characters, false
otherwise. (Introduced in Java 11)

o Example:

Java

String strWithSpace = " ";

System.out.println(strWithSpace.isBlank()); // Output: true

• indexOf(int ch) / indexOf(String str):

o Returns the index within this string of the first occurrence of the specified character
or substring.

o Returns -1 if the character/substring is not found.

o Example:

Java

String name = "Amar Panchal";

System.out.println(name.indexOf('a')); // Output: 2 (first 'a' is at index 2)

System.out.println(name.indexOf("Pan")); // Output: 5

• lastIndexOf(int ch) / lastIndexOf(String str):

o Returns the index within this string of the last occurrence of the specified character
or substring.

o Example:

Java

String name = "Amar Panchal";

System.out.println(name.lastIndexOf('a')); // Output: 10 (last 'a' is at index 10)

• indexOf(int ch, int fromIndex) / indexOf(String str, int fromIndex):

o Returns the index of the first occurrence of the specified character or substring,
starting the search at fromIndex.

o Example:

Java

String name = "Amar Panchal";

System.out.println(name.indexOf('a', 5)); // Output: 6 (first 'a' from index 5 onwards is at index 6)

• String.valueOf(primitiveData):

o A static method that converts various primitive data types (like int, double, boolean,
char[]) to their string representation.

o Example:
Java

int a = 10;

String strA = String.valueOf(a);

System.out.println(strA); // Output: "10" (as a String)

• String.format(String format, Object... args):

o A static method used for formatting strings using placeholders, similar to printf in C.

o %s for string, %d for integer, etc.

o Example:

Java

String formattedString = String.format("My name is %s and I am %d years old.", "John", 30);

System.out.println(formattedString); // Output: My name is John and I am 30 years old.

• subSequence(int beginIndex, int endIndex):

o Returns a CharSequence that is a subsequence of this string.

o In Java, for String objects, subSequence() behaves identically to substring() and


returns a continuous part of the string.

o Difference between Substring and Subsequence:

▪ Substring: A continuous part of a string (e.g., "mar" is a substring of "Amar").

▪ Subsequence: A sequence of characters that appear in the same order as in


the original string, but not necessarily continuously (e.g., "Amr" is a
subsequence of "Amar").

o Example:

Java

String name = "Amar Panchal";

System.out.println(name.subSequence(2, 8)); // Output: ar Pan

Key Takeaways:

• Methods vs. Code: Methods are blocks of code that perform specific tasks.

• Accessing Methods: String methods are accessed using the dot operator (.) on a String
object (e.g., name.length()).

• No Memorization Needed: Integrated Development Environments (IDEs) like IntelliJ provide


auto-completion and documentation for methods, so memorizing them is not necessary.

• String Immutability: Strings in Java are immutable. All methods that modify a string (like
toUpperCase(), replace(), substring()) return a new string, leaving the original string
unchanged. This is a fundamental concept and a common interview question.
• Static Methods: Methods accessed directly on the class name (e.g., String.valueOf(),
String.format()) are static methods.

Comments in Java:

• Single-line comment: //

• Multi-line comment: /* ... */

o Shortcut (IntelliJ): Ctrl + Shift + / for multi-line, Ctrl + / for single-line.

Conditional Statements in Java

This lecture covers conditional statements in Java, including relational operators, logical operators, if-
else statements, and switch-case statements.

Relational Operators

Relational operators compare two values and return a boolean result (true or false).

• Less Than (<): Checks if the left operand is less than the right operand.

o Example: a < b

• Greater Than (>): Checks if the left operand is greater than the right operand.

o Example: a > b

• Equality (==): Checks if two operands are equal.

o Example: a == b

o For strings, == checks for reference equality (if they point to the same object in
memory), not value equality.

• Not Equal To (!=): Checks if two operands are not equal.

o Example: a != b

• Greater Than or Equal To (>=): Checks if the left operand is greater than or equal to the right
operand.

o Example: a >= b

• Less Than or Equal To (<=): Checks if the left operand is less than or equal to the right
operand.

o Example: a <= b

Relational operators can be used with various data types like integers, doubles, and characters. When
used with characters, their ASCII values are compared.

Logical Operators

Logical operators combine boolean expressions.

• Logical AND (&&): Returns true if both conditions are true. If the first condition is false, the
second condition is not evaluated (short-circuiting).
o Example: (ramMarks >= 33) && (ramAge <= 18)

• Logical OR (||): Returns true if at least one condition is true. If the first condition is true, the
second condition is not evaluated (short-circuiting).

o Example: (experience >= 5) || (isTierOne)

• Logical NOT (!): Reverses the boolean value of an operand.

o Example: !(2 < 3)

Conditional Statements

If-Else Statements

If-else statements allow you to execute different blocks of code based on a condition.

• if statement: Executes a block of code if a specified boolean expression is true.

Java

int age = 20;

if (age >= 18) { // Condition (boolean expression)

System.out.println("You are an adult");

• if-else statement: Executes one block of code if the condition is true and another block if it's
false.

Java

int age = 2;

if (age >= 18) {

System.out.println("You are an adult");

} else {

System.out.println("You are a child");

• if-else if-else ladder: Used for multiple conditions. It checks conditions sequentially, and
once a condition is true, its block is executed, and the rest of the ladder is skipped.

Java

int marks = 75;

if (marks >= 90) {

System.out.println("Grade A");

} else if (marks >= 75) {

System.out.println("Grade B");
} else if (marks >= 60) {

System.out.println("Grade C");

} else {

System.out.println("Grade D");

Switch-Case Statements

Switch-case statements provide an alternative to long if-else if ladders when you have a single
expression to test against multiple possible values.

• Syntax:

Java

int day = 3;

switch (day) { // Expression to evaluate

case 1:

System.out.println("Monday");

break; // Important to prevent fall-through

case 2:

System.out.println("Tuesday");

break;

case 3:

System.out.println("Wednesday");

break;

// ... other cases

default: // Executed if no case matches

System.out.println("Invalid Day");

• How it works: The switch statement evaluates the expression and jumps directly to the
matching case label.

• break statement: Essential to terminate a case block. Without break, the code will "fall
through" and execute subsequent case blocks until a break is encountered or the switch
block ends.

• default: Similar to the else block in if-else statements, the default block is executed if none of
the case values match the expression.

• Advantages:
o Cleaner and more maintainable code compared to long if-else if ladders.

o Improved performance as it directly jumps to the matching case instead of checking


each condition sequentially.

• Supported Data Types: switch statements can be used with byte, short, char, int, String
(from Java 7), and enum.

• Unsupported Data Types: switch statements cannot be used with double or other floating-
point types due to precision issues. For these, if-else statements must be used.

This lecture provides a comprehensive overview of loops in Java, covering while, do-while, and for
loops, along with practical examples and concepts like nested loops, break, and continue statements.

Types of Loops in Java

Java primarily has three types of loops:

• While Loop

• Do-While Loop

• For Loop

The core purpose of loops is to repeatedly execute a block of code.

While Loop

• Syntax: while (condition) { // code to be executed }

• The code inside the while loop's block continues to execute as long as the specified condition
remains true.

• Example: Printing "Hello World" 10 times

Java

int i = 0;

while (i < 10) {

System.out.println("Hello World");

i = i + 1; // or i++

o The variable i is initialized outside the loop.

o The condition i < 10 is checked before each iteration.

o i is incremented inside the loop to eventually make the condition false and prevent
an infinite loop.

• Example: Printing numbers from 1 to 50

Java

int i = 1;
while (i <= 50) {

System.out.println(i);

i++;

Do-While Loop

• Syntax: do { // code to be executed } while (condition);

• The do-while loop guarantees that the code block will execute at least once, even if the
condition is initially false. The condition is checked after the first execution.

• Example: Printing numbers from 1 to 50

Java

int i = 1;

do {

System.out.println(i);

i++;

} while (i <= 50);

• do-while loops are used less frequently in practice.

For Loop

• Syntax: for (initialization; condition; update) { // code to be executed }

• The for loop is generally preferred for its structured approach, as initialization, condition, and
update are all defined within the loop's header.

• Example: Printing numbers from 1 to 10

Java

for (int j = 1; j <= 10; j++) {

System.out.println(j);

• Advantages:

o Readability: All loop control elements are in one place.

o Scope: Variables declared in the for loop's initialization are scoped to the loop,
preventing naming conflicts outside.

• Execution Flow:

1. Initialization: Executed once at the beginning.

2. Condition Check: Evaluated before each iteration.


3. Code Execution: If the condition is true, the loop body executes.

4. Update: Executed after each iteration.

Practical Examples with For Loop

1. Printing a sequence (1, 10, 100, 1000, 10000, 100000)

Java

for (int i = 1, j = 1; j <= 6; i *= 10, j++) {

System.out.println(i);

o This example demonstrates declaring and updating multiple variables within the for
loop's header.

2. Printing the 7 Times Table

Java

for (int i = 1; i <= 10; i++) {

System.out.println(i + " * 7 = " + (i * 7));

3. Sum of First 10 Natural Numbers

Java

int sum = 0;

int i = 1;

while (i <= 10) {

sum = sum + i;

i++;

System.out.println("Answer: " + sum); // Output: 55

4. Counting Digits of a Number

Java

int n = 12345678; // Example number

int result = 0;

while (n > 0) {

n = n / 10; // Divides the number by 10, effectively removing the last digit

result++; // Increments the count for each digit removed


}

System.out.println(result); // Output: 8

5. Calculating Factorial of a Number

Java

int n = 6; // Example number

int r = 1; // Initialize result to 1 for multiplication

while (n > 0) {

r = r * n;

n--; // Decrement n

System.out.println(r); // Output: 720

Nested Loops

• Loops can be placed inside other loops, known as nested loops.

• Example: Printing "Hello World" 100 times using two nested for loops

Java

int rs = 0;

for (int i = 0; i < 10; i++) {

for (int j = 0; j < 10; j++) {

// System.out.println("Hello World");

rs++; // Counts how many times the inner code runs

System.out.println(rs); // Output: 100

o The inner loop completes all its iterations for each single iteration of the outer loop.

• Pattern Printing Example: Printing a right-angled triangle of stars

Java

for (int i = 0; i < 6; i++) { // Controls the number of rows

for (int j = 0; j <= i; j++) { // Controls the number of stars in each row

System.out.print("*"); // Prints star without new line

System.out.println(); // Moves to the next line after each row


}

o The inner loop's condition (j <= i) depends on the outer loop's variable i, causing the
number of stars to increase with each row.

Break and Continue Statements

1. break Statement

o Used to terminate the loop immediately.

o When break is encountered, the loop is exited, and execution continues with the
statement immediately following the loop.

o Example: Exiting a while loop when i reaches 500

Java

int i = 0;

while (i < 1000) {

System.out.println(i);

if (i == 500) {

break; // Exits the while loop

i++;

System.out.println("Hello"); // This will print after 500

o In nested loops, break only exits the innermost loop it is contained within.

2. continue Statement

o Used to skip the current iteration of a loop and proceed to the next iteration.

o When continue is encountered, the remaining code in the current loop iteration is
skipped, and the loop proceeds to the next iteration (checking the condition and
performing the update).

o Example: Printing numbers from 1 to 10, skipping 5

Java

// Using while loop (requires manual increment before continue)

int i = 1;

while (i <= 10) {

if (i == 5) {

i++; // Important: Increment i before continuing to avoid infinite loop


continue;

System.out.println(i);

i++;

// Using for loop (update happens automatically)

for (int k = 1; k <= 10; k++) {

if (k == 5) {

continue; // Skips printing 5, moves to next iteration

System.out.println(k);

o The importance of manually updating the loop variable before continue in while
loops to prevent infinite loops. In for loops, the update part handles this
automatically.

Arrays in Java

This lecture provides a comprehensive overview of arrays in Java, covering 1D, 2D, and jagged arrays,
along with practical examples and explanations of their declaration, initialization, and traversal.

1. Introduction to Arrays

• Problem with individual variables: Storing a large number of similar data types (e.g., 1000
integers) using individual variables (e.g., int x = 1; int y = 2;) is inefficient and impractical.

• Solution: Arrays: Arrays allow storing a collection of similar kind of data together. For
example, int[] array = {1, 2, 3};.

• Purpose of Arrays: Arrays are used when you need a collection of similar data types.

2. Declaring and Initializing 1D Arrays

• Declaration Syntax:

Java

type[] variableName;

Example: int[] integerArray;

o The [] indicates that it's an array.

o The type specifies the data type of elements in the array (e.g., int, char, String).

• Initialization Syntax:
Java

variableName = new type[size];

Example: int[] arr = new int[5];

o new keyword allocates memory for the array in the heap.

o size specifies the number of elements the array can hold.

• Combined Declaration and Initialization:

Java

type[] variableName = new type[size];

Example: int[] arr = new int[5];

• Memory Allocation (Heap vs. Stack):

o When an array is created using new, it is stored in the heap memory.

o The array variable (e.g., arr) is a reference variable that stores the starting address of
the array in the heap. This reference variable itself is stored in the stack memory.

o Default values: When an array is initialized, its elements are automatically assigned
default values (e.g., 0 for int, null for String, false for boolean).

• Direct Initialization with Values:

Java

int[] arr = {1, 2, 3, 4};

This directly assigns values to the array elements.

3. Accessing Array Elements

• Array elements are accessed using their index, which starts from 0. Example: arr[0], arr[1],
arr[2].

• Assigning values: You can assign values to specific indices. Example: arr[0] = 89;

4. Traversing Arrays

• Using a for loop: This is the most common way to iterate through array elements.

Java

for (int i = 0; i < arr.length; i++) {

System.out.println(arr[i]);

o arr.length: This is a property (not a method) that returns the size of the array.

o This approach allows flexible iteration and access to elements by index.


• Using a for-each loop (Enhanced for loop): Introduced for iterating over collections like
arrays.

Java

for (int element : arr) {

System.out.println(element);

o This loop directly provides the element's value, not its index.

o It simplifies iteration when you don't need the index.

• Printing an entire array directly: Printing an array directly using System.out.println(arr); will
print its hash code, not its elements. Example output: [I@6e08ea8a

o [ indicates an array.

o I indicates integer type (other types like B for byte, C for char, D for double, F for
float).

o @ followed by a hash code (a unique identifier).

5. Array Operations and Examples

• Searching an Element:

Java

int[] arr = {1, 4, 2, 55, 7, -2};

int target = 55;

for (int element : arr) {

if (element == target) {

System.out.println("Found");

break; // Exit loop once found

This example uses a for-each loop to check for the presence of an element.

• Finding Maximum Element:

Java

int[] arr = new int[5];

arr[0] = 2;

arr[1] = 12;

arr[2] = 4322;
arr[3] = -32;

arr[4] = 22;

int max = Integer.MIN_VALUE; // Initialize with negative infinity

for (int i = 0; i < arr.length; i++) {

if (arr[i] > max) {

max = arr[i];

System.out.println("Maximum element: " + max);

o Integer.MIN_VALUE is used to ensure any array element will be greater than the
initial max value, even if all elements are negative.

• Reversing an Array (Printing in Reverse):

Java

int[] arr = {1, 3, 43, 5, 5}; // Example array

for (int i = arr.length - 1; i >= 0; i--) {

System.out.println(arr[i]);

This loop iterates backward from the last index to the first.

• Sum of Array Elements:

Java

int[] arr = {-2, 4, 55, -4, 11, -55, -11, 2, 11}; // Example array

int sum = 0;

for (int element : arr) { // Using for-each loop

sum += element;

System.out.println("Sum: " + sum);

This calculates the sum of all elements in the array.

6. Two-Dimensional (2D) Arrays

• Concept: 2D arrays are "arrays of arrays," representing a matrix or a grid.

• Declaration and Initialization:


Java

type[][] variableName = new type[rows][columns];

Example: int[][] matrix = new int[3][3];

o This creates a 3x3 matrix initialized with default values (zeros for int).

• Direct Initialization with Values:

Java

int[][] nums = {

{1, 2, 3},

{4, 5, 6},

{7, 8, 9}

};

This directly assigns values to the 2D array.

• Accessing Elements: Elements are accessed using two indices: [row_index][column_index].


Example: nums[1][2] would access the element 6 (second row, third column).

• Traversing 2D Arrays (Nested Loops): To traverse a 2D array, you need nested for loops.

Java

for (int i = 0; i < nums.length; i++) { // Outer loop for rows

for (int j = 0; j < nums[i].length; j++) { // Inner loop for columns

System.out.print(nums[i][j] + " ");

System.out.println(); // New line after each row

o nums.length gives the number of rows.

o nums[i].length gives the number of columns in the current row i.

7. Jagged Arrays

• Concept: Jagged arrays are 2D arrays where each row can have a different number of
columns (different lengths).

• Declaration and Initialization:

Java

char[][] charArray = new char[3][]; // Declare rows, but not columns

charArray[0] = new char[2]; // First row has 2 columns

charArray[1] = new char[3]; // Second row has 3 columns


charArray[2] = new char[2]; // Third row has 2 columns

o You first specify the number of rows, then initialize each row with its own length.

• Accessing and Traversing Jagged Arrays: The same nested loop structure used for regular 2D
arrays works for jagged arrays because arr[i].length dynamically gets the length of each inner
array.

Java

// Example of assigning values to a jagged array

charArray[0][0] = 'A';

charArray[0][1] = 'B';

charArray[1][0] = 'C';

charArray[1][1] = 'D';

charArray[1][2] = 'E';

charArray[2][0] = 'F';

charArray[2][1] = 'G';

// Traversing a jagged array

for (int i = 0; i < charArray.length; i++) {

for (int j = 0; j < charArray[i].length; j++) {

System.out.print(charArray[i][j] + " ");

System.out.println();

This lecture provides an overview of Object-Oriented Programming (OOP) in Java, covering its core
concepts and four main principles.

What is OOP?

• OOP stands for Object-Oriented Programming.

• It's a programming paradigm, which means it's a way of structuring programs.

• In OOP, we primarily deal with classes and objects.

Classes and Objects

• Class: A blueprint for creating objects. In Java, everything is written inside a class.

• Object: An instance of a class. Anything you see around you (e.g., laptop, phone, bottle) can
be considered an object.
• Objects have two main characteristics:

o Properties (or Fields/Data): Attributes that describe the object (e.g., for a car: brand,
model, color, max speed). These are defined in the blueprint (class).

o Behavior (or Methods): Actions that the object can perform (e.g., for a car:
accelerate, brake). In Java, behaviors are implemented as methods.

Code Example: Car Class (Blueprint) The instructor demonstrates creating a Car class with properties
and methods:

Java

// Properties (Fields)

String color;

int speed;

String brand;

int year;

String model;

// Behaviors (Methods)

public void accelerate() {

speed++; // Increases speed

public void brake() {

speed--; // Decreases speed

• Properties like color, speed, brand, year, and model are defined.

• Methods like accelerate() and brake() define the car's behavior.

Code Example: Creating a Car Object In a Test class with a main method (the entry point of a Java
application):

Java

public class Test {

public static void main(String[] args) {

Car car = new Car(); // Creating a new Car object from the blueprint

car.color = "Blue"; // Setting properties


car.speed = 40;

car.brand = "Tata";

car.year = 2024;

car.model = "Safari";

car.accelerate(); // Calling a method to change behavior

System.out.println(car.speed); // Output: 41

• An object car is created from the Car class.

• Properties of the car object are set.

• The accelerate() method is called, increasing the car's speed.

Four Principles of OOP

The four main principles of OOP are:

1. Encapsulation

2. Abstraction

3. Inheritance

4. Polymorphism

1. Encapsulation

• Definition: Bundling data (fields) and methods that operate on the data into a single unit (a
class).

• It also involves data hiding, meaning restricting direct access to some of an object's
components.

• This is achieved using access modifiers like private.

• If a field is private, it cannot be directly accessed or modified from outside the class.

• To access or modify private fields, getters (to retrieve data) and setters (to modify data)
methods are used.

Code Example: Encapsulation in Car Class

Java

public class Car {

private String color; // Private field

private int speed;


private String brand;

private int year;

private String model;

// Getters and Setters (generated)

public String getColor() { return color; }

public void setColor(String color) { this.color = color; }

// ... similar getters/setters for other fields

// Example of removing setters to prevent modification

// public void setModel(String model) { this.model = model; } // Removed to prevent model change

// public void setYear(int year) { this.year = year; } // Removed to prevent year change

public void accelerate() {

speed++;

public void brake() {

speed--;

• By making fields private, direct modification (e.g., car.year = 2030;) is prevented, leading to
compilation errors.

• Getters and setters provide controlled access to these private fields.

• The instructor demonstrates how specific setters (e.g., setModel, setYear) can be removed to
prevent certain properties from being changed after object creation.

2. Inheritance

• Definition: Allows one class (child/subclass) to inherit properties and behaviors from another
class (parent/superclass).

• Achieved using the extends keyword in Java.

• Promotes code reusability.

Code Example: Inheritance (Animal and Cat)


Java

// Parent Class

public class Animal {

String name;

int age;

// Child Class

public class Cat extends Animal { // Cat inherits from Animal

String breed;

• The Cat class extends the Animal class.

• This means a Cat object will automatically have name and age properties in addition to its
own breed property.

Code Example: Using Inherited Properties

Java

public class Test {

public static void main(String[] args) {

Cat cat = new Cat();

cat.breed = "Persian";

cat.name = "Bob"; // Inherited from Animal

cat.age = 3; // Inherited from Animal

• Even though name and age are not explicitly defined in Cat, they are accessible because Cat
inherits from Animal.

3. Polymorphism

• Definition: "Many forms." It allows objects of different classes to be treated as objects of a


common superclass.

• This means a subclass object can be assigned to a reference variable of its superclass type.

• It often involves method overriding, where a subclass provides a specific implementation for
a method that is already defined in its superclass.
Code Example: Polymorphism (Animal, Cat, Dog)

Java

// Superclass

public class Animal {

public void makeSound() {

System.out.println("Some sound");

// Subclass 1

public class Cat extends Animal {

@Override // Indicates method overriding

public void makeSound() {

System.out.println("Meow");

// Subclass 2

public class Dog extends Animal {

@Override

public void makeSound() {

System.out.println("Woof");

• Animal has a makeSound() method.

• Cat and Dog override makeSound() to provide their specific sounds.

Code Example: Demonstrating Polymorphism

Java

public class Test {

public static void main(String[] args) {

Animal dog = new Dog(); // Object of Dog, but reference of Animal


dog.makeSound(); // Output: Woof (the Dog's overridden method is called)

Animal cat = new Cat(); // Object of Cat, but reference of Animal

cat.makeSound(); // Output: Meow (the Cat's overridden method is called)

• Even though dog is an Animal type reference, when makeSound() is called, the Dog class's
makeSound() method is executed because the actual object created is a Dog.

4. Abstraction

• Definition: Hiding internal implementation details and showing only the necessary
information to the user.

• Focuses on "what" an object does rather than "how" it does it.

• Real-life example: Using a TV remote. You press a button to change the channel without
needing to know the complex internal workings of the TV.

• Another example: Driving a car. You change gears without needing to understand the
internal mechanics of the engine and transmission.

Other Programming Paradigms

The instructor briefly mentions other programming paradigms besides OOP:

• Imperative: Line-by-line execution, explicitly stating "how" to do something (e.g., C


language).

• Declarative: Focuses on "what" to do, not "how."

• Functional: Treats functions as first-class citizens, allowing them to be stored in variables,


passed as arguments, etc.

This lecture serves as an introductory overview, with deeper dives into each concept planned for
future lessons. This lecture provides an overview of Object-Oriented Programming (OOP) in Java,
covering its core concepts and four main principles.

What is OOP?

• OOP stands for Object-Oriented Programming.

• It's a programming paradigm, which means it's a way of structuring programs.

• In OOP, we primarily deal with classes and objects.

Classes and Objects

• Class: A blueprint for creating objects. In Java, everything is written inside a class.

• Object: An instance of a class. Anything you see around you (e.g., laptop, phone, bottle) can
be considered an object.
• Objects have two main characteristics:

o Properties (or Fields/Data): Attributes that describe the object (e.g., for a car: brand,
model, color, max speed). These are defined in the blueprint (class).

o Behavior (or Methods): Actions that the object can perform (e.g., for a car:
accelerate, brake). In Java, behaviors are implemented as methods.

Code Example: Car Class (Blueprint) The instructor demonstrates creating a Car class with properties
and methods:

Java

// Properties (Fields)

String color;

int speed;

String brand;

int year;

String model;

// Behaviors (Methods)

public void accelerate() {

speed++; // Increases speed

public void brake() {

speed--; // Decreases speed

• Properties like color, speed, brand, year, and model are defined.

• Methods like accelerate() and brake() define the car's behavior.

Code Example: Creating a Car Object In a Test class with a main method (the entry point of a Java
application):

Java

public class Test {

public static void main(String[] args) {

Car car = new Car(); // Creating a new Car object from the blueprint

car.color = "Blue"; // Setting properties


car.speed = 40;

car.brand = "Tata";

car.year = 2024;

car.model = "Safari";

car.accelerate(); // Calling a method to change behavior

System.out.println(car.speed); // Output: 41

• An object car is created from the Car class.

• Properties of the car object are set.

• The accelerate() method is called, increasing the car's speed.

Four Principles of OOP

The four main principles of OOP are:

1. Encapsulation

2. Abstraction

3. Inheritance

4. Polymorphism

1. Encapsulation

• Definition: Bundling data (fields) and methods that operate on the data into a single unit (a
class).

• It also involves data hiding, meaning restricting direct access to some of an object's
components.

• This is achieved using access modifiers like private.

• If a field is private, it cannot be directly accessed or modified from outside the class.

• To access or modify private fields, getters (to retrieve data) and setters (to modify data)
methods are used.

Code Example: Encapsulation in Car Class

Java

public class Car {

private String color; // Private field

private int speed;


private String brand;

private int year;

private String model;

// Getters and Setters (generated)

public String getColor() { return color; }

public void setColor(String color) { this.color = color; }

// ... similar getters/setters for other fields

// Example of removing setters to prevent modification

// public void setModel(String model) { this.model = model; } // Removed to prevent model change

// public void setYear(int year) { this.year = year; } // Removed to prevent year change

public void accelerate() {

speed++;

public void brake() {

speed--;

• By making fields private, direct modification (e.g., car.year = 2030;) is prevented, leading to
compilation errors.

• Getters and setters provide controlled access to these private fields.

• The instructor demonstrates how specific setters (e.g., setModel, setYear) can be removed to
prevent certain properties from being changed after object creation.

2. Inheritance

• Definition: Allows one class (child/subclass) to inherit properties and behaviors from another
class (parent/superclass).

• Achieved using the extends keyword in Java.

• Promotes code reusability.

Code Example: Inheritance (Animal and Cat)


Java

// Parent Class

public class Animal {

String name;

int age;

// Child Class

public class Cat extends Animal { // Cat inherits from Animal

String breed;

• The Cat class extends the Animal class.

• This means a Cat object will automatically have name and age properties in addition to its
own breed property.

Code Example: Using Inherited Properties

Java

public class Test {

public static void main(String[] args) {

Cat cat = new Cat();

cat.breed = "Persian";

cat.name = "Bob"; // Inherited from Animal

cat.age = 3; // Inherited from Animal

• Even though name and age are not explicitly defined in Cat, they are accessible because Cat
inherits from Animal.

3. Polymorphism

• Definition: "Many forms." It allows objects of different classes to be treated as objects of a


common superclass.

• This means a subclass object can be assigned to a reference variable of its superclass type.

• It often involves method overriding, where a subclass provides a specific implementation for
a method that is already defined in its superclass.
Code Example: Polymorphism (Animal, Cat, Dog)

Java

// Superclass

public class Animal {

public void makeSound() {

System.out.println("Some sound");

// Subclass 1

public class Cat extends Animal {

@Override // Indicates method overriding

public void makeSound() {

System.out.println("Meow");

// Subclass 2

public class Dog extends Animal {

@Override

public void makeSound() {

System.out.println("Woof");

• Animal has a makeSound() method.

• Cat and Dog override makeSound() to provide their specific sounds.

Code Example: Demonstrating Polymorphism

Java

public class Test {

public static void main(String[] args) {

Animal dog = new Dog(); // Object of Dog, but reference of Animal


dog.makeSound(); // Output: Woof (the Dog's overridden method is called)

Animal cat = new Cat(); // Object of Cat, but reference of Animal

cat.makeSound(); // Output: Meow (the Cat's overridden method is called)

• Even though dog is an Animal type reference, when makeSound() is called, the Dog class's
makeSound() method is executed because the actual object created is a Dog.

4. Abstraction

• Definition: Hiding internal implementation details and showing only the necessary
information to the user.

• Focuses on "what" an object does rather than "how" it does it.

• Real-life example: Using a TV remote. You press a button to change the channel without
needing to know the complex internal workings of the TV.

• Another example: Driving a car. You change gears without needing to understand the
internal mechanics of the engine and transmission.

Other Programming Paradigms

The instructor briefly mentions other programming paradigms besides OOP:

• Imperative: Line-by-line execution, explicitly stating "how" to do something (e.g., C


language).

• Declarative: Focuses on "what" to do, not "how."

• Functional: Treats functions as first-class citizens, allowing them to be stored in variables,


passed as arguments, etc.

This lecture serves as an introductory overview, with deeper dives into each concept planned for
future lessons.

This lecture provides a comprehensive overview of methods in Java, covering their definition, syntax,
parameters, return types, method overloading, and variable arguments, along with practical
examples.

What are Methods?

• Methods are blocks of code that perform a specific task.

• They help in organizing code, reducing repetition, and making it easier to maintain and
modify.

• Instead of writing the same code multiple times, you can define it once in a method and call
it whenever needed.
• Example: Calculating the sum of two numbers or the sum of elements in an array. If you
need to perform these operations multiple times, writing the code repeatedly leads to
redundancy and makes changes difficult.

Method Syntax

The general syntax for defining a method in Java is as follows:

Java

AccessModifier StaticKeyword ReturnType MethodName(Parameters) {

// Method Body

• Access Modifier: Specifies the visibility of the method (e.g., public, private). public means
the method can be accessed from any class, while private restricts access to the same class.

• Static Keyword: (To be covered later in the course). For now, if the main method is static,
other methods called within it must also be static.

• Return Type: The data type of the value the method returns. If the method does not return
any value, void is used.

• Method Name: A unique name that identifies the method.

• Parameters: A comma-separated list of input variables that the method accepts. These are
optional.

• Method Body: Contains the actual code that performs the method's task.

Examples of Methods

1. Sum of Array Elements (Void Return Type)

o Initially, the method prints the sum directly and does not return any value, hence
void is used as the return type.

Java

public static void sumOfArray(int[] arr) {

int sum = 0;

for (int i : arr) {

sum += i;

System.out.println("Sum: " + sum);

// Calling the method


public static void main(String[] args) {

int[] a = {1, 2, 3, 4, 5};

sumOfArray(a); // Output: Sum: 15

o This method can be called multiple times with different arrays without rewriting the
summation logic.

2. Sum of Array Elements (Integer Return Type)

o To make the method more flexible, it can return the calculated sum as an int.

Java

public static int sumOfArray(int[] arr) {

int sum = 0;

for (int i : arr) {

sum += i;

return sum; // Returns the sum

// Calling the method

public static void main(String[] args) {

int[] a = {1, 2, 3, 4, 5};

int result = sumOfArray(a);

System.out.println("Sum: " + result); // Output: Sum: 15

// Or directly print:

System.out.println("Sum: " + sumOfArray(new int[]{10, 20, 30})); // Output: Sum: 60

3. String Manipulation Method

o This method takes a string, removes leading/trailing spaces, and converts it to


uppercase.

Java

private static String upperFunction(String str) {

return str.trim().toUpperCase();

}
// Calling the method

public static void main(String[] args) {

String text = " apple ";

String result = upperFunction(text);

System.out.println(result); // Output: APPLE

4. Sum of Two Numbers

o A method to calculate the sum of two integers.

Java

private static int sum(int a, int b) {

return a + b;

// Calling the method

public static void main(String[] args) {

System.out.println(sum(3, 7)); // Output: 10

Method Overloading

• Method overloading allows multiple methods in the same class to have the same name but
different parameters.

• The parameters can differ in:

o Number of parameters: e.g., sum(int a, int b) and sum(int a, int b, int c).

o Type of parameters: e.g., sum(int a, int b) and sum(float a, float b).

o Order of parameters: e.g., doSomething(int a, String b) and doSomething(String b,


int a).

• Method Signature: Consists of the method name and its parameter list (types and order).
The return type and access modifiers are NOT part of the method signature.

• For method overloading to work, the method signatures must be unique.

Variable Arguments (Varargs)

• Varargs allow a method to accept a variable number of arguments of a specified type.

• Syntax: type... variableName (e.g., int... a).


• Inside the method, the varargs parameter is treated as an array.

• Example: Summing any number of integers.

Java

public static int sum(int... a) {

int sum = 0;

for (int i : a) {

sum += i;

return sum;

// Calling the method

public static void main(String[] args) {

System.out.println(sum(1, 2)); // Output: 3

System.out.println(sum(1, 2, 3)); // Output: 6

System.out.println(sum(1, 2, 3, 4, 5)); // Output: 15

• Varargs eliminate the need to create separate overloaded methods for different numbers of
arguments.

Pass by Value vs. Pass by Reference (with Mutability)

1. Primitive Data Types (Pass by Value)

o When a primitive data type (like int, double, boolean) is passed to a method, a copy
of its value is passed.

o Changes made to the parameter inside the method do not affect the original variable
outside the method.

Java

public static int multiplyBy10(int x) {

x = x * 10;

return x;

public static void main(String[] args) {


int x = 10;

System.out.println(multiplyBy10(x)); // Output: 100 (returns the modified copy)

System.out.println(x); // Output: 10 (original x remains unchanged)

2. String Objects (Pass by Value, but Strings are Immutable)

o When a String object is passed, a copy of the reference is passed.

o However, String objects are immutable in Java. This means that any operation that
appears to modify a string (like toUpperCase()) actually creates a new string object.

o The original string object remains unchanged.

Java

public static String toUpperCase(String s) {

return s.toUpperCase(); // Creates a new string

public static void main(String[] args) {

String a = "apple";

System.out.println(toUpperCase(a)); // Output: APPLE

System.out.println(a); // Output: apple (original 'a' is unchanged)

3. Custom Objects (Pass by Value, but Objects are Mutable)

o When a custom object (like an instance of a Cat class) is passed, a copy of the
reference to that object is passed.

o Since objects are mutable, changes made to the object's properties (e.g.,
cat.setName()) through this copied reference will affect the original object in
memory.

Java

// Assuming a Cat class with getName() and setName() methods

class Cat {

String name;

public String getName() { return name; }

public void setName(String name) { this.name = name; }

}
public static void makeCatNameUpperCase(Cat cat) {

cat.setName(cat.getName().toUpperCase()); // Modifies the original object's name

public static void main(String[] args) {

Cat a = new Cat();

a.setName("bob");

System.out.println(a.getName()); // Output: bob

makeCatNameUpperCase(a);

System.out.println(a.getName()); // Output: BOB (original 'a' is changed)

o This is a crucial concept: while the reference itself is passed by value (a copy of the
memory address), the object at that memory address can be modified.

Command Line Arguments

• The main method in Java has a parameter String[] args.

• This args array is used to receive command-line arguments passed to the Java application
when it is executed.

• Arguments are typically space-separated strings.

• Example:

Java

public class Test {

public static void main(String[] args) {

if (args.length > 0) {

System.out.println("First argument: " + args[0]);

o To compile: javac Test.java

o To run with arguments: java Test Hello World

o Output: First argument: Hello


• The Java Virtual Machine (JVM) automatically converts the space-separated command-line
inputs into an array of strings.

Prime Number Check Example

This example demonstrates how to write a method to check if a given integer is a prime number.

public static boolean isPrime(int x) {

if (x <= 1) { // Numbers less than or equal to 1 are not prime

return false;

// A number is prime if it's only divisible by 1 and itself.

// We only need to check divisibility up to x/2.

// If a number has a divisor greater than x/2, it must also have a divisor less than x/2.

for (int i = 2; i <= x / 2; i++) {

if (x % i == 0) { // If x is divisible by i, it's not prime

return false;

return true; // If no divisors found, it's prime

public static void main(String[] args) {

System.out.println(isPrime(13)); // Output: true

System.out.println(isPrime(91)); // Output: false (91 = 7 * 13)

System.out.println(isPrime(7)); // Output: true

System.out.println(isPrime(100)); // Output: false

• Query successful

Try again without apps

Recursion in Java

This lecture covers recursion, a programming concept where a method calls itself. The video explains
recursion by first demonstrating how to calculate the factorial of a number using a loop and then re-
implementing it using recursion.
Factorial Calculation

1. Iterative Approach (using a loop) The traditional way to calculate the factorial of a number n
involves a loop.

Java

public static int factorial(int n) {

int res = 1; // Initialize result to 1

for (int i = 1; i <= n; i++) { // Loop from 1 to n

res = res * i; // Multiply res by current number

return res; // Return the final result

For example, factorial(5) would result in 120 (5 * 4 * 3 * 2 * 1).

2. Recursive Approach Recursion leverages the mathematical property of factorials, where n! = n *


(n-1)!.

• Base Case: The crucial part of a recursive function is the base case, which stops the
recursion. For factorials, 1! = 1.

• Recursive Step: The function calls itself with a smaller input.

Java

public static int factorial(int n) {

if (n == 1) { // Base case: if n is 1, return 1

return 1;

return n * factorial(n - 1); // Recursive step: n * factorial of (n-1)

This recursive implementation also yields 120 for factorial(5). The video demonstrates the execution
flow of this recursive call using a visual representation of function calls waiting for each other to
finish.

Call Stack and Recursion

The video explains how recursion works with the call stack.

• The call stack is a part of memory that tracks method calls.

• When a method is called, it's pushed onto the stack.

• When a method finishes execution, it's popped off the stack.

• This follows a Last-In, First-Out (LIFO) principle, similar to a stack of books or bricks.
For factorial(5):

1. main calls factorial(5).

2. factorial(5) calls factorial(4).

3. factorial(4) calls factorial(3).

4. factorial(3) calls factorial(2).

5. factorial(2) calls factorial(1).

6. factorial(1) hits the base case and returns 1.

7. factorial(2) receives 1, calculates 2 * 1 = 2, and returns 2.

8. factorial(3) receives 2, calculates 3 * 2 = 6, and returns 6.

9. factorial(4) receives 6, calculates 4 * 6 = 24, and returns 24.

10. factorial(5) receives 24, calculates 5 * 24 = 120, and returns 120 to main. This process shows
how calls are added to the stack and then resolved from top to bottom.

Sum of First N Natural Numbers (Recursive Example)

The video further illustrates recursion with another example: calculating the sum of the first n
natural numbers.

• Problem: Sum of n natural numbers (e.g., for n=5, sum = 5 + 4 + 3 + 2 + 1 = 15).

• Recursive Idea: Sum(n) = n + Sum(n-1).

• Base Case: If n = 1, the sum is 1.

Java

public static int sumOfNNaturalNumbers(int n) {

if (n == 1) { // Base case: if n is 1, return 1

return 1;

return n + sumOfNNaturalNumbers(n - 1); // Recursive step: n + sum of (n-1) natural numbers

Calling sumOfNNaturalNumbers(5) returns 15.

The video concludes by emphasizing that recursion is a fundamental concept for Data Structures and
Algorithms (DSA).

This lecture focuses on understanding packages and class paths in Java.

What are Packages?

• Packages are essentially folders used to organize classes, similar to how you organize files
and folders on your computer.
• They help in differentiating classes with the same name. For example, you can have two Cat
classes in different packages (e.g., Test and Test2) without conflict.

• Every class in a package will have a package declaration at the top, indicating its location.

• Java has many pre-built packages like java.lang (which contains String and Math classes).

• The java.lang package is automatically imported, so you don't need to explicitly write import
java.lang.*. Other packages, like java.util.List, need to be explicitly imported.

Accessing Classes Across Packages

• When creating an object of a class that exists in multiple packages, you'll be prompted to
choose which one.

• You can access a class by its fully qualified name (e.g., Test2.Cat).

• Alternatively, you can import the class using the import statement (e.g., import Test2.Cat;).

• If you import a class, and there's another class with the same name in a different package,
you'll need to use the fully qualified name to distinguish them (e.g., Test.Cat vs. Test2.Cat).

Package Naming Conventions

• The convention for naming root packages is com.companyname.projectname (e.g.,


com.engineeringdigest.corejava).

• Sub-packages are then created within this root package (e.g.,


com.engineeringdigest.corejava.animals, com.engineeringdigest.corejava.vehicles).

• All package names should be in lowercase.

Class Path

• The class path is where the Java Virtual Machine (JVM) looks for compiled .class files.

• When running a Java program with packages from the command line, you need to specify
the correct class path.

• Example of running a Java class with a package from the command line:

o Compile: javac Test.java (This creates Test.class inside the Test package directory).

o If you are inside the Test directory and try to run java Test, it will fail because the
JVM looks for Test/Test within the current directory.

o To run it correctly, navigate one directory up (e.g., to src if Test is inside src).

o Then, run using the fully qualified name: java Test.Test. This tells the JVM to look for
the Test package and then the Test class within it.

o Alternatively, you can use the -classpath or -cp flag to specify where to find the
classes: java -cp . Test.Test (where . means the current directory).

Multiple Classes in a Single File

• You can write multiple classes within a single .java file.


• However, only one class can be public in a .java file, and its name must match the file name.

• Classes that are not declared public within the same file are considered package-private.
This means they can only be accessed within the same package.

• Example: If MiniCycle is a non-public class in Cycle.java, it can be accessed within the


vehicles package (e.g., from Car.java in the same package), but not from outside the vehicles
package (e.g., from Test.java in a different package).

• Inner classes (nested classes) can be used to encapsulate classes within another class. To
create an instance of an inner class, you first need an instance of the outer class.

o Code Example for Inner Class:

Java

// Inside Cycle.java

class Cycle {

// ...

class MiniCycle {

// ...

// To access MiniCycle from another class in the same package (e.g., Car.java)

Cycle cycle = new Cycle();

Cycle.MiniCycle miniCycle = cycle.new MiniCycle();

The next lecture will cover access modifiers, which are closely related to packages.

• Query successful

Try again without apps

This lecture focuses on Encapsulation in Java, a fundamental concept in Object-Oriented


Programming (OOP).

What is Encapsulation?

Encapsulation is about bundling data (properties/fields) and methods (behaviors) that operate on the
data within a single unit (a class) and restricting direct access to some of the component's parts. This
means you control how data is accessed and modified, typically through methods.

Key Concepts:

• Class as a Blueprint: A class is a blueprint that defines the properties (data) and behaviors
(methods) of objects.
o Properties (Fields/Instance Variables): These describe the characteristics of an
object. For example, a Student class might have name, address, and roll number as
properties.

o Behaviors (Methods): These define what an object can do or how it interacts with its
data.

• Local vs. Instance Variables:

o Local Variable: Declared inside a method (e.g., String name inside main method).

o Instance Variable: Declared within a class but outside any method, attached to an
object of that class (e.g., String name inside Student class).

• Access Modifiers - private and public:

o private: Members (fields or methods) declared as private can only be accessed


within the class they are defined in. This is crucial for encapsulation as it prevents
direct external modification of data.

o public: Members declared as public can be accessed from anywhere. Methods used
to interact with private fields are typically public.

• Getters and Setters:

o Setters: Public methods used to set the value of a private instance variable. They
often include validation logic to ensure data integrity.

o Getters: Public methods used to retrieve the value of a private instance variable.

o Why use them? They provide a controlled way to access and modify data, allowing
you to implement validation and business logic centrally within the class.

Code Examples:

1. Student Class Example:

Initial (without encapsulation):

Java

class Student {

String name;

int age;

int rollNumber;

// In Test class (main method)

Student student = new Student();

student.name = "Ram"; // Direct access


student.age = 15; // Direct access

student.rollNumber = 21; // Direct access

Problem: Direct access allows setting invalid values (e.g., negative age or roll number).

With Encapsulation (using private fields and public methods):

Java

class Student {

private String name;

private int age;

private int rollNumber;

// Setter for age with validation

public void setAge(int x) {

if (x < 0) {

System.out.println("Invalid Age"); // Example validation

this.age = 0; // Set to a default valid value

} else {

this.age = x;

// Getter for age

public int getAge() {

return this.age;

// Getters and Setters for name and rollNumber can be generated by IDE

// Example for name:

public String getName() {

return name;

}
public void setName(String name) {

this.name = name;

// Example for rollNumber:

public int getRollNumber() {

return rollNumber;

public void setRollNumber(int rollNumber) {

this.rollNumber = rollNumber;

// In Test class (main method)

Student student = new Student();

student.setAge(15); // Use setter

student.setAge(-15); // Will print "Invalid Age" and set age to 0

System.out.println(student.getAge()); // Use getter

Benefit: Centralized control over data modification, allowing for validation and preventing invalid
states.

2. Bank Account Class Example:

This example demonstrates how encapsulation is used to manage bank account operations like
deposit and withdrawal with proper validation.

Java

class BankAccount {

private long accountNumber;

private double balance; // Changed to double for decimal amounts

// Getters and Setters for accountNumber (generated by IDE)

public long getAccountNumber() {

return accountNumber;
}

public void setAccountNumber(long accountNumber) {

this.accountNumber = accountNumber;

// Getter for balance (no setter for balance to prevent direct modification)

public double getBalance() {

return balance;

// Deposit method with validation

public void deposit(double amount) {

if (amount > 0) {

this.balance += amount;

System.out.println("Deposited Amount: " + amount);

} else {

System.out.println("Invalid Deposit Amount");

// Withdraw method with validation

public void withdraw(double amount) {

if (amount > 0 && amount <= this.balance) {

this.balance -= amount;

System.out.println("Withdrew: " + amount);

} else {

System.out.println("Invalid Amount or Insufficient Balance");

}
// In Test class (main method)

BankAccount bankAccount = new BankAccount();

bankAccount.deposit(-10); // Invalid deposit

bankAccount.withdraw(10); // Insufficient balance

bankAccount.deposit(100); // Valid deposit

bankAccount.withdraw(10); // Valid withdrawal

System.out.println(bankAccount.getBalance()); // Get current balance

Result: The output shows the validation messages and the correct balance after operations. This
demonstrates how encapsulation ensures that bank account operations adhere to business rules.

Summary of Encapsulation:

• Data Hiding: Fields are made private to prevent direct external access.

• Controlled Access: Data is accessed and modified only through public methods (getters and
setters, or other behavior-specific methods like deposit and withdraw).

• Centralized Logic: Business rules and validation logic are contained within the methods of
the class, ensuring consistency and preventing errors.

• Maintainability: Changes to data representation or validation logic only affect the class itself,
not external code that uses the class.

• Query successful

Try again without apps

This lecture focuses on constructors in Java, explaining their purpose, types, and how they are used
to initialize objects.

What are Constructors?

• Constructors are special methods used to initialize objects.

• They are automatically called when an object is created.

• Constructors help in setting initial values for an object's fields.

• A key characteristic of a constructor is that its name is the same as the class name, and it
has no return type.

Types of Constructors

1. Default Constructor

o This constructor takes no parameters.

o It is automatically generated by the compiler if no other constructor is explicitly


defined in the class.
o The default constructor sets the default values for the object's fields (e.g., null for
strings, 0 for integers).

o Example:

Java

Student student = new Student(); // Calls the default constructor

// student.getAge() would return 0 (default for int)

// student.getName() would return null (default for String)

// student.getRollNumber() would return 0 (default for int)

o Important Note: If you define any custom constructor (parameterized or


overloaded), the default constructor is no longer automatically provided by Java,
leading to errors if you try to call it without explicitly defining it.

2. Parameterized Constructor

o These constructors take one or more parameters.

o They are explicitly written by the programmer.

o Parameterized constructors allow you to initialize object fields with specific values
at the time of object creation.

o Example:

Java

public class Student {

String name;

int rollNumber;

int age;

// Parameterized Constructor

public Student(String name, int rollNumber, int age) {

this.age = age;

this.name = name;

this.rollNumber = rollNumber;

// Object creation using parameterized constructor


Student student = new Student("John", 101, 11); // Initializes name, rollNumber, and age

o The this keyword is used to refer to the instance variables of the class, distinguishing
them from local parameters with the same name.

Constructor Overloading

• Similar to method overloading, constructors can be overloaded.

• Constructor overloading means having multiple constructors in a class with the same name
(which is the class name) but with different parameter lists (different number of parameters
or different types of parameters).

• This allows for flexible object creation, where you can initialize an object with different sets
of initial values.

• Examples of Overloaded Constructors:

o Overloading the Default Constructor: You can define a default constructor that sets
specific initial values instead of the system defaults.

Java

public class Student {

String name;

int rollNumber;

int age;

// Overloaded Default Constructor

public Student() {

this.age = 10; // Sets default age to 10

// When Student student = new Student(); is called, age will be 10

o Constructors with different parameter sets:

Java

public class Student {

String name;

int rollNumber;

int age;

// Constructor with all parameters


public Student(String name, int rollNumber, int age) {

this.age = age;

this.name = name;

this.rollNumber = rollNumber;

// Constructor with only name

public Student(String name) {

this.name = name;

// Constructor with only roll number

public Student(int rollNumber) {

this.rollNumber = rollNumber;

// Object creation using different overloaded constructors:

Student student1 = new Student("Shyam"); // Calls constructor with String parameter

Student student2 = new Student(123); // Calls constructor with int parameter

Benefits of Constructors

• Initializes objects: Ensures that objects are created in a valid state.

• Reduces code: Allows for setting initial values in a single line during object creation, avoiding
multiple set method calls.

• Enforces conditions: Can include logic to validate initial values (e.g., ensuring age is not
negative).

• Query successful

Try again without apps

This lecture on Inheritance in Java covers several key concepts, including different types of
inheritance, method overriding, constructor chaining, and the super keyword.

1. Introduction to Inheritance
• Inheritance is one of the four core principles of Object-Oriented Programming (OOP),
alongside encapsulation, polymorphism, and abstraction.

• It allows a class (child class) to inherit properties and behaviors from another class (parent
class), promoting code reusability and reducing redundancy.

2. Types of Inheritance

The video discusses three types of inheritance:

• Single Inheritance

o A class inherits from only one parent class.

o Example: A Dog class extending an Animal class.

Java

// Animal.java

public class Animal {

private String name;

private int age;

// Getters and Setters

public String getName() { /* ... */ }

public void setName(String name) { /* ... */ }

public int getAge() { /* ... */ }

public void setAge(int age) { /* ... */ }

public void eat() {

System.out.println("This animal eats food");

public void sayHello() {

// General animal doesn't say anything specific

// Dog.java

public class Dog extends Animal {


// Dog inherits name, age, eat(), and sayHello() from Animal

// Dog can have its own specific methods or override parent methods

o Testing Single Inheritance

Java

// Test.java

public class Test {

public static void main(String[] args) {

Dog dog = new Dog();

dog.setAge(2); // Inherited from Animal

dog.setName("Bob"); // Inherited from Animal

dog.eat(); // Inherited from Animal

dog.sayHello(); // Inherited from Animal (can be overridden)

• Multi-Level Inheritance

o A class inherits from a parent class, which in turn inherits from another class,
forming a chain.

o Example: Child extends Parent, and Parent extends GrandParent.

Java

// GrandParent.java

public class GrandParent {

private String name;

private int age;

private boolean hasSuperPowers = false; // Initial setup

public GrandParent(int age, String name) { // Parameterized constructor

this.age = age;

this.name = name;

}
// Getters and Setters for name, age, and hasSuperPowers

public String getName() { /* ... */ }

public void setName(String name) { /* ... */ }

public int getAge() { /* ... */ }

public void setAge(int age) { /* ... */ }

public boolean isHasSuperPowers() { /* ... */ }

// Parent.java

public class Parent extends GrandParent {

public Parent(int age, String name) { // Parameterized constructor

super(age, name); // Calls GrandParent's constructor

public void parentMethod() {

System.out.println("Parent Method Called");

// Child.java

public class Child extends Parent {

public Child(int age, String name) { // Parameterized constructor

super(age, name); // Calls Parent's constructor

public void childMethod() {

System.out.println("Child Method Called");

super.parentMethod(); // Calling parent's method

o Testing Multi-Level Inheritance


Java

// Test.java

public class Test {

public static void main(String[] args) {

Child child = new Child(8, "Ram"); // Child's own age and name

System.out.println(child.isHasSuperPowers()); // Inherited from GrandParent

child.childMethod();

• Hierarchical Inheritance

o Multiple classes inherit from a single parent class.

o Example: Dog and Cat classes both extending the Animal class.

Java

// Cat.java

public class Cat extends Animal {

@Override // Annotation for method overriding

public void sayHello() {

System.out.println("Meow");

o Testing Hierarchical Inheritance

Java

// Test.java

public class Test {

public static void main(String[] args) {

Dog dog = new Dog();

// Dog can access Animal's properties and methods

Cat cat = new Cat();

// Cat can access Animal's properties and methods

}
3. Method Overriding

• Method overriding occurs when a child class provides a specific implementation for a
method that is already defined in its parent class.

• The method in the child class must have the same name, return type, and parameters as the
method in the parent class.

• Example: The Dog class overrides the sayHello() method from the Animal class.

Java

// Animal.java

public class Animal {

public void sayHello() {

// General animal doesn't say anything specific

// Dog.java

public class Dog extends Animal {

@Override // Good practice to use this annotation

public void sayHello() {

System.out.println("Woof");

• The @Override annotation is optional but highly recommended. It tells the compiler that the
method is intended to override a method in a superclass. If it doesn't, the compiler will
throw an error.

4. Constructor Chaining

• When an object of a child class is created, the constructors of its parent classes are implicitly
called in a chain, starting from the topmost parent.

• This ensures that the initial setup and properties of all superclasses are properly initialized
before the child class's constructor executes.

• Order of Constructor Calls: GrandParent -> Parent -> Child.

Java

// GrandParent.java

public class GrandParent {


public GrandParent() { // Default constructor

System.out.println("GrandParent Constructor Called");

// Parent.java

public class Parent extends GrandParent {

public Parent() { // Default constructor

System.out.println("Parent Constructor Called");

// Child.java

public class Child extends Parent {

public Child() { // Default constructor

System.out.println("Child Constructor Called");

// Test.java

public class Test {

public static void main(String[] args) {

Child child = new Child();

// Output:

// GrandParent Constructor Called

// Parent Constructor Called

// Child Constructor Called

5. The super Keyword

• The super keyword refers to the immediate parent class.


• It can be used to:

o Invoke the superclass constructor: super().

▪ If a child class constructor does not explicitly call a superclass constructor


using super(), Java implicitly adds a call to the no-argument constructor of
the superclass.

▪ The super() call must be the first statement in the constructor body. This
ensures that the parent class is fully initialized before the child class.

▪ If the parent class only has parameterized constructors, the child class must
explicitly call one of them using super() with appropriate arguments.

o Invoke superclass methods: super.methodName().

▪ This is useful when a child class has overridden a method, but you still want
to call the parent's implementation of that method.

o Access superclass fields: super.fieldName (though this is less common due to


encapsulation and private fields).

6. this vs. super

• this refers to the current instance of the class.

• super refers to the immediate parent class.

7. Multiple Inheritance (Not Supported in Java)

• Java does not support multiple inheritance (a class extending more than one class).

• This is primarily to avoid the "Diamond Problem" or ambiguity.

o Example: If Smartphone could extend Camera and MusicPlayer, and both Camera
and MusicPlayer had a method with the same signature (e.g., powerOn()), the
Smartphone object wouldn't know which powerOn() method to call.

• Java solves this problem using Interfaces, which will be discussed in future lectures.

Java

// Phone.java

public class Phone {

public void call() {

System.out.println("Calling...");

// MusicPlayer.java

public class MusicPlayer {


public void playMusic() {

System.out.println("Playing Music...");

public void powerOn() {

System.out.println("Music Player Power On");

// Camera.java

public class Camera {

public void clickPhoto() {

System.out.println("Clicked Photo");

public void powerOn() {

System.out.println("Camera Power On");

// Smartphone.java (Illustrates why multiple inheritance is not allowed)

// public class Smartphone extends Camera, MusicPlayer, Phone { // Not allowed in Java

// // If allowed, calling smartphone.powerOn() would be ambiguous

// }

This lecture covers the concept of Polymorphism in Object-Oriented Programming (OOP), one of its
four core principles, along with encapsulation, inheritance, and abstraction.

What is Polymorphism?

Polymorphism allows methods to perform different actions based on the object they are acting
upon. The key characteristic is that the method name and signature remain the same, yet they
produce different results. The term "Polymorphism" itself means "many forms" (Poly = many, Morph
= forms).

Types of Polymorphism

There are two main types of polymorphism:

1. Compile-Time Polymorphism (Method Overloading)


o Definition: This type of polymorphism is achieved through method overloading. It
means having multiple methods with the same name but different parameters
(number or type) within the same class.

o Decision Time: The decision of which method to call is made at compile time. The
compiler determines the correct method based on the arguments provided during
the method call.

o Example:

▪ Class: Calculator

▪ Methods:

▪ add(int a, int b): Adds two integers.

▪ add(int a, int b, int c): Adds three integers.

▪ add(double a, double b): Adds two doubles.

▪ Code Snippet (Conceptual):

Java

class Calculator {

// Method to add two integers

public int add(int a, int b) {

return a + b;

// Method to add three integers (overloaded)

public int add(int a, int b, int c) {

return a + b + c;

// Method to add two doubles (overloaded)

public double add(double a, double b) {

return a + b;

class Main {
public static void main(String[] args) {

Calculator calc = new Calculator();

System.out.println(calc.add(5, 10)); // Calls add(int, int)

System.out.println(calc.add(5, 10, 15)); // Calls add(int, int, int)

System.out.println(calc.add(5.5, 10.5)); // Calls add(double, double)

▪ In this example, the add method has "many forms" depending on the
parameters passed.

2. Run-Time Polymorphism (Method Overriding / Dynamic Method Dispatch)

o Definition: This type of polymorphism is achieved through method overriding and


inheritance. It occurs when a subclass provides a specific implementation for a
method that is already defined in its superclass.

o Decision Time: The decision of which method to call is made at run time by the Java
Virtual Machine (JVM). This is also known as Dynamic Method Dispatch.

o Key Concept: Upcasting: You can create a reference of the parent class and assign it
an object of the child class.

▪ Example: Animal myDog = new Dog(); Here, myDog is an Animal reference,


but it holds a Dog object.

o Example:

▪ Classes:

▪ Animal (Parent class)

▪ Method: sayHello() (empty or default implementation)

▪ Cat (Child class, extends Animal)

▪ Overrides sayHello() to print "Meow"

▪ Dog (Child class, extends Animal)

▪ Overrides sayHello() to print "Woof"

▪ Has its own unique method: sayBye()

▪ Code Snippet (Conceptual):

Java

class Animal {

public void sayHello() {

System.out.println("..."); // Default implementation


}

class Cat extends Animal {

@Override

public void sayHello() {

System.out.println("Meow");

class Dog extends Animal {

@Override

public void sayHello() {

System.out.println("Woof");

public void sayBye() {

System.out.println("Bye Bye");

class Test {

public static void main(String[] args) {

Animal myAnimal = new Animal();

myAnimal.sayHello(); // Prints "..."

Animal myDog = new Dog(); // Upcasting: Animal reference, Dog object

myDog.sayHello(); // Prints "Woof" (Dog's overridden method is called at runtime)

Animal myCat = new Cat(); // Upcasting: Animal reference, Cat object

myCat.sayHello(); // Prints "Meow" (Cat's overridden method is called at runtime)


// Cannot call child-specific methods using parent reference

// myDog.sayBye(); // This would cause a compile-time error

▪ Even though myDog and myCat are Animal references, the JVM determines
at runtime to call the sayHello() method of the actual object type (Dog or
Cat).

▪ Important Note: When using a parent class reference for a child class object
(upcasting), you can only access methods that are defined in the parent
class. You cannot call methods unique to the child class using the parent
reference.

Downcasting

• Definition: Downcasting is the process of converting a parent class reference to a child class
reference. This is typically done when you have an object that was originally a child class but
was upcasted to a parent class reference.

• Example:

Java

Animal myDog = new Dog(); // Upcasting

Dog actualDog = (Dog) myDog; // Downcasting

actualDog.sayBye(); // Now you can call child-specific methods

o This is similar to casting primitive data types, e.g., int e = (int) d; where d is a double.

Summary

• Polymorphism: Many forms.

• Compile-Time Polymorphism: Achieved by Method Overloading.

• Run-Time Polymorphism: Achieved by Method Overriding with Inheritance. Also known as


Dynamic Method Dispatch.

• Upcasting: Assigning a child object to a parent reference.

• Downcasting: Converting a parent reference back to a child reference.

This lecture focuses on Abstraction in Java, a core pillar of Object-Oriented Programming.

What is Abstraction?

Abstraction is about hiding internal details and showing only the necessary functionalities. The video
uses the example of an AC remote: you can operate the AC (change temperature, mode, etc.)
without needing to know how the AC works internally.
Achieving Abstraction in Java

Abstraction in Java can be achieved using abstract classes and abstract methods.

Abstract Methods

• An abstract method is a method that has a declaration but no definition (body).

• To declare a method as abstract, use the abstract keyword before the return type.

Java

public abstract void sayHello(); // No method body

• If a method is abstract, it means its implementation will be provided by its subclasses.

Abstract Classes

• If a class contains one or more abstract methods, the class itself must be declared as
abstract.

Java

public abstract class Animal {

// Abstract method

public abstract void sayHello();

// Concrete method

public void sleep() {

System.out.println("Animal is sleeping");

• Abstract classes can have both abstract and concrete (regular) methods. Concrete methods
have a definition/body.

• It is not mandatory for an abstract class to have abstract methods. You can have an abstract
class with only concrete methods, though this is less common.

• However, if you have an abstract method, its class must be abstract.

Key Rules and Concepts

• Cannot create objects (instantiate) of an abstract class. This is because abstract classes may
have methods without definitions, making it impossible to execute them if an object were
created.

• Can create references of an abstract class. These references can point to objects of their
concrete subclasses.

Java
Animal dog = new Dog(); // Animal is an abstract class, Dog is a concrete subclass

dog.sayHello(); // Calls the sayHello() method implemented in Dog

• Subclasses of an abstract class must either:

1. Implement all inherited abstract methods. If they don't, they must also be declared
as abstract.

2. Be declared as abstract themselves.

Example: Animal Class

The video demonstrates abstraction with an Animal class:

• Problem without Abstraction: Initially, the Animal class had a sayHello() method with a
generic "..." implementation, which wasn't specific to any animal.

• Solution with Abstraction:

o The Animal class is made abstract.

o The sayHello() method in Animal is made abstract (no body).

o Concrete subclasses like Dog and Cat extend Animal and provide their specific
implementations for sayHello().

Java

// Dog.java

public class Dog extends Animal {

@Override

public void sayHello() {

System.out.println("Woof");

// Cat.java

public class Cat extends Animal {

@Override

public void sayHello() {

System.out.println("Meow");

}
• Benefits: This approach forces subclasses to provide implementations for the abstract
methods, ensuring consistency and avoiding generic or meaningless implementations in the
parent class.

Example: Vehicle Class

Another example is given with a Vehicle abstract class:

• A Vehicle class is abstract because a "vehicle" is a general term.

• It defines abstract methods like accelerate() and decelerate().

• Subclasses like Cycle and Car extend Vehicle and provide their specific implementations for
these methods.

Constructors in Abstract Classes

• Abstract classes can have constructors.

• These constructors are primarily used for initial setup of common fields or logic that all
subclasses might need.

• A common practice (and a warning from SonarLint) is to make constructors of abstract


classes protected instead of public. This is because the constructor of an abstract class can
only be called from the constructors of its subclasses, so there's no point in making it public.

Access Modifiers and Abstraction

• private abstract methods are not allowed. If a method is private, it cannot be overridden by
subclasses, which defeats the purpose of an abstract method.

• package-private (default) abstract methods: If no access modifier is specified, the method is


package-private. This means it can only be accessed within the same package. Subclasses in
different packages would not be able to override it.

• protected abstract methods: A protected abstract method can be accessed within the same
package and by subclasses (even in different packages). This is useful when you want to
restrict access but still allow subclasses to implement the method.

When to Use Abstraction

Abstraction is useful when you have a generic parent class with many child classes. It allows you to
declare common functionalities in the parent class without providing a concrete implementation,
forcing the child classes to define their specific behaviors. This ensures that all subclasses adhere to a
defined structure and implement necessary methods.

This lecture covers Java access modifiers: Public, Private, Default, and Protected.

Access Modifiers Overview

• Public: Accessible from anywhere.

• Private: Accessible only within the same class.

• Protected: Accessible within the same package and by subclasses (even in different
packages).
• Default: No keyword is used. Accessible only within the same package.

Detailed Explanation and Code Examples

1. Public Access Modifier

• Concept: Members (fields, methods, classes) declared as public can be accessed from any
other class, regardless of the package.

• Example:

o A Student class in the accessmodifier.school package.

o Student.java:

Java

package accessmodifier.school;

public class Student {

public String name;

public int age;

public void sayHello() {

System.out.println("Hello");

o A Test class in the accessmodifier.test package.

o Test.java:

Java

package accessmodifier.test;

import accessmodifier.school.Student;

public class Test {

public static void main(String[] args) {

Student student = new Student();

student.age = 12; // Accessible because 'age' is public

student.name = "Ram"; // Accessible because 'name' is public


student.sayHello(); // Accessible because 'sayHello' is public

o Output: Hello

2. Private Access Modifier

• Concept: Members declared as private are only accessible within the class they are declared
in.

• Example (modifying Student class):

o Student.java:

Java

package accessmodifier.school;

public class Student {

private String name; // Changed to private

public int age;

public void sayHello() {

System.out.println("Hello");

o In Test.java, student.name = "Ram"; will cause a compilation error because name has
private access.

• Private Constructors:

o Concept: A constructor can be made private to prevent direct instantiation of a class


from outside.

o Use Case 1: Utility Classes: When a class only contains static methods and no object
creation is needed.

▪ Utils.java:

Java

package accessmodifier.school;

public class Utils {


private Utils() { // Private constructor

// Prevents instantiation

public static void sayBye() { // Static method

System.out.println("Bye");

▪ Test.java:

Java

package accessmodifier.test;

import accessmodifier.school.Utils;

public class Test {

public static void main(String[] args) {

// Utils utils = new Utils(); // This would cause an error

Utils.sayBye(); // Accessible directly via class name

o Use Case 2: Singleton Pattern: Ensures only one instance of a class is created
throughout the application.

▪ School.java:

Java

package accessmodifier.school;

public class School {

private static School instance; // Private static instance

private School() { // Private constructor

// Prevents direct instantiation


}

public static School getInstance() { // Public static method to get instance

if (instance == null) { // Check if instance already exists

instance = new School(); // Create instance if null

return instance;

▪ Test.java:

Java

package accessmodifier.test;

import accessmodifier.school.School;

public class Test {

public static void main(String[] args) {

School school1 = School.getInstance(); // First call creates instance

School school2 = School.getInstance(); // Subsequent calls return the same instance

▪ Debugging shows that the constructor new School() is only called once.

3. Default Access Modifier

• Concept: If no access modifier is specified, it's considered default (also known as package-
private). Members are accessible only within the same package.

• Example (modifying School class):

o School.java:

Java

package accessmodifier.school;

class School { // No public keyword, so it's default


// ... (rest of the School class content)

o In Test.java (which is in a different package accessmodifier.test), School school1 =


School.getInstance(); will cause an error because School is not accessible outside its
package.

o If School is made public again, it becomes accessible.

• Note: Top-level classes can only be public or default.

4. Protected Access Modifier

• Concept: Members declared as protected are accessible within the same package and by
subclasses (even if the subclass is in a different package).

• Example:

o Animal.java in accessmodifier.zoo package:

Java

package accessmodifier.zoo;

public class Animal {

private String name;

protected String sound; // Protected field

public Animal(String name) {

this.name = name;

public void makeSound() {

System.out.println(name + " makes a sound " + sound);

protected void changeSound(String newSound) { // Protected method

this.sound = newSound;

private String getClassName() { // Private helper method


return this.getClass().getSimpleName();

o Dog.java in accessmodifier.zoo package, extending Animal:

Java

package accessmodifier.zoo;

public class Dog extends Animal { // Dog extends Animal

public Dog(String name) {

super(name); // Calls parent constructor

this.sound = "Bark"; // Directly accessing protected 'sound' field

public void wagTail() {

System.out.println(getClassName() + " is wagging its tail"); // Using private helper

public void setDogSound(String newSound) {

changeSound(newSound); // Calling protected 'changeSound' method

o Test.java in accessmodifier.test package:

Java

package accessmodifier.test;

import accessmodifier.zoo.Dog;

public class Test {

public static void main(String[] args) {

Dog bob = new Dog("Bob"); // Create Dog object

bob.makeSound(); // Output: Bob makes a sound Bark


// bob.changeSound("Woof"); // This would cause an error: 'changeSound' has protected access

bob.setDogSound("Woof"); // Accessible via public wrapper method in Dog

bob.makeSound(); // Output: Bob makes a sound Woof

bob.wagTail(); // Output: Dog is wagging its tail

• Key Point: A protected member can be accessed directly by a subclass (like Dog accessing
changeSound and sound), but not directly by an unrelated class in a different package (like
Test trying to access changeSound directly). However, it can be accessed by any class within
the same package, even if it's not a subclass.

Access Modifier Summary Chart

Same Same Subclass (Same Subclass (Different Different Package (Non-


Modifier
Class Package Package) Package) Subclass)

Public Yes Yes Yes Yes Yes

Private Yes No No No No

Default Yes Yes Yes No No

Protected Yes Yes Yes Yes No

Export to Sheets

• Clarification on Protected: The chart highlights that protected members are accessible
within the same package, even by non-subclasses. This is demonstrated by accessing
changeSound from a class in the same package as Animal, even if it doesn't extend Animal.

• Query successful

Try again without apps

This lecture covers the static keyword in Java, explaining its use for memory management and how it
applies to variables, methods, and blocks.

Key Concepts of static

• Class Part, Not Instance Part: When static is applied to a member (variable or method), it
becomes a part of the class itself, rather than an instance of the class. This means you can
access static members directly using the class name, without needing to create an object of
that class.
• Memory Management: static helps in memory management by ensuring that only one copy
of a static member exists, which is shared by all objects of that class. This prevents
redundant copies and saves memory.

Applying static

1. Static Variables (Fields):

o A static variable is shared among all instances of a class.

o Example: To count the number of Student objects created, a static int count variable
can be used. Each time a Student object is created (via its constructor), count is
incremented.

o Code Example:

Java

public class Student {

public static int count = 0; // Initialized to 0

public Student() {

count++; // Increments count every time a Student object is created

// Other fields and methods

// Accessing the static variable

System.out.println(Student.count); // Access directly via class name

o If count were not static, each Student object would have its own count variable, and
it would always be 1 for each instance.

2. Static Methods:

o A static method can be called directly using the class name, without creating an
object.

o Example: A getCount() method can be made static to return the static count variable.

o Code Example:

Java

public class Student {

public static int count = 0;


public Student() {

count++;

public static void getCount() {

System.out.println("Total Students: " + count);

// Other fields and methods

// Calling the static method

Student.getCount(); // Call directly via class name

o Restrictions:

▪ Static methods cannot directly use non-static data members or call non-
static methods. This is because non-static members belong to an object, and
a static method is called on the class itself, without an object context.

▪ this and super keywords cannot be used within a static context because they
refer to the current object and parent object, respectively.

3. Static Blocks:

o A static block is executed when the class is loaded into memory.

o It is primarily used for static initialization, especially when complex logic is required
to initialize static variables.

o Code Example:

Java

public class Student {

public static int count;

static {

// This block executes when the Student class is loaded

System.out.println("Hello from static block");

count = 10; // Initializing static variable with some logic

}
// Other fields and methods

// When Student class is used (e.g., Student.getCount()), the static block runs

o Static blocks are useful for one-time setup tasks, such as establishing a database
connection in a DatabaseManager class.

Common Use Cases for static

• Utility Classes: Classes that contain only static methods are often called utility classes (e.g.,
Math class in Java). These methods perform common, reusable operations that don't require
an object instance.

o Example: A Utils class with max() and min() methods to find the maximum or
minimum of two numbers.

o Code Example:

Java

public class Utils {

public static int max(int a, int b) {

if (a > b) {

return a;

} else {

return b;

public static String trimAndUpperCase(String str) {

if (str != null) {

return str.trim().toUpperCase();

} else {

return "";

}
// Usage

int result = Utils.max(10, 20);

String processedString = Utils.trimAndUpperCase(" hello world ");

• Singleton Design Pattern: static is crucial for implementing the Singleton design pattern,
which ensures that a class has only one instance and provides a global point of access to it.

o This is achieved by making the constructor private and providing a public static
method to return the single instance of the class.

o Code Example:

Java

public class School {

private static School instance = new School(); // Single instance created when class loads

private School() {

// Private constructor to prevent external instantiation

public static School getInstance() {

return instance; // Returns the single instance

// Usage

School school1 = School.getInstance();

School school2 = School.getInstance();

// school1 and school2 will refer to the same object

This lecture explains the final keyword in Java, which can be applied to variables, methods, and
classes, with different implications for each.

Final Variables

• Purpose: The final keyword makes a variable a constant, meaning its value cannot be
changed once initialized.

• Example:

Java
public class Car {

public final int SPEED_LIMIT = 200; // Initialized directly

o If you try to change a final variable after initialization, it will result in a compile-time
error.

o Attempting to generate a setter for a final variable will show that it's not possible.

• Initialization:

o A final variable can be initialized at the time of declaration.

o It can also be initialized in a static block if it's a static final variable.

Java

public class Utils {

public static final double PI; // Declared

static {

PI = 3.14159; // Initialized in static block

o For instance final variables, they can be initialized in the constructor.

Java

public class Car {

public final int speedLimit;

public Car() {

this.speedLimit = 200; // Initialized in constructor

• Restriction: Once a final variable is assigned a value, it cannot be reassigned.

Final Methods

• Purpose: When a method is declared final, it cannot be overridden by any subclass. This is
useful for enforcing specific behavior that should not be altered by subclasses, such as safety
features.

• Example:

Java

public class Car {


public final void airbags() {

System.out.println("Four airbags");

public class EVCar extends Car {

// This will cause a compile-time error because airbags() is final in Car

// @Override

// public void airbags() {

// System.out.println("Two airbags (cost cutting)");

// }

o Attempting to override a final method will result in a compile-time error indicating


that the method cannot be overridden.

Final Classes

• Purpose: When a class is declared final, it cannot be extended by any other class. This
prevents inheritance and ensures that the class's implementation remains unchanged.

• Example:

Java

public final class PremiumCar {

// Class implementation

// This will cause a compile-time error because PremiumCar is final

// public class EVPremiumCar extends PremiumCar {

// // Class implementation

// }

o Trying to extend a final class will result in a compile-time error, stating that it cannot
inherit from a final class.

Final Constructors

• Can a constructor be final?: No, constructors cannot be declared final.

• Reasoning:
o Constructors are used to initialize the state of an object.

o The final keyword for methods is used to prevent overriding in inheritance.

o Constructors are not inherited or overridden in the same way as regular methods; a
subclass has its own constructor, which may call the parent's constructor using
super().

o Applying final to a constructor would not serve any meaningful purpose and is not
allowed by the Java compiler.

This set of lectures covers fundamental concepts in Java Object-Oriented Programming (OOP),
including Encapsulation, Constructors, Inheritance, Polymorphism, Abstraction, Access Modifiers, the
static keyword, the final keyword, and Interfaces.

Here are the summarized notes and code examples from each lecture:

1. Encapsulation in Java

https://youtu.be/ifJ0eCrEC44?list=PLA3GkZPtsafY62QhQ030p85HAer0pFDdr

What is Encapsulation? Encapsulation bundles data (properties/fields) and methods (behaviors)


within a single unit (a class) and restricts direct access to some parts. This controls how data is
accessed and modified, typically through public methods.

Key Concepts:

• Class as a Blueprint: Defines properties and behaviors of objects.

• Properties (Fields/Instance Variables): Characteristics of an object.

• Behaviors (Methods): What an object can do.

• Local vs. Instance Variables: Local variables are inside methods; instance variables are inside
a class but outside methods.

• Access Modifiers (private, public):

o private: Accessible only within the class.

o public: Accessible from anywhere.

• Getters and Setters: Public methods to control access and modification of private instance
variables, often including validation.

Code Example (Student Class with Encapsulation):

Java

class Student {

private String name;

private int age;

private int rollNumber;


// Setter for age with validation

public void setAge(int x) {

if (x < 0) {

System.out.println("Invalid Age");

this.age = 0;

} else {

this.age = x;

// Getter for age

public int getAge() {

return this.age;

// Getters and Setters for name and rollNumber

public String getName() { return name; }

public void setName(String name) { this.name = name; }

public int getRollNumber() { return rollNumber; }

public void setRollNumber(int rollNumber) { this.rollNumber = rollNumber; }

// In Test class (main method)

Student student = new Student();

student.setAge(15);

student.setAge(-15); // Will print "Invalid Age"

System.out.println(student.getAge());

2. Constructors in Java

https://youtu.be/uCAaTvO7dn0?list=PLA3GkZPtsafY62QhQ030p85HAer0pFDdr

What are Constructors? Special methods used to initialize objects. They are automatically called
when an object is created, helping set initial values for fields. A constructor's name is the same as the
class name, and it has no return type.
Types of Constructors:

1. Default Constructor: Takes no parameters, automatically generated by the compiler if no


other constructor is defined. Sets default values (e.g., null, 0).

2. Parameterized Constructor: Takes one or more parameters, explicitly written by the


programmer, allows initializing fields with specific values.

Constructor Overloading: Having multiple constructors in a class with the same name but different
parameter lists.

Code Example (Student Class with Constructors):

Java

public class Student {

String name;

int rollNumber;

int age;

// Overloaded Default Constructor

public Student() {

this.age = 10; // Sets default age

// Parameterized Constructor

public Student(String name, int rollNumber, int age) {

this.age = age;

this.name = name;

this.rollNumber = rollNumber;

// Constructor with only name

public Student(String name) {

this.name = name;

// Constructor with only roll number


public Student(int rollNumber) {

this.rollNumber = rollNumber;

// Object creation using different constructors:

Student student1 = new Student(); // Calls default constructor (age=10)

Student student2 = new Student("John", 101, 11); // Calls parameterized constructor

Student student3 = new Student("Shyam"); // Calls constructor with String

Student student4 = new Student(123); // Calls constructor with int

3. Inheritance in Java

https://youtu.be/CGHL1zuD5fY?list=PLA3GkZPtsafY62QhQ030p85HAer0pFDdr

What is Inheritance? Allows a class (child/subclass) to inherit properties and behaviors from another
class (parent/superclass), promoting code reusability.

Types of Inheritance:

• Single Inheritance: One child class inherits from one parent class.

• Multi-Level Inheritance: A chain of inheritance (Child extends Parent, Parent extends


GrandParent).

• Hierarchical Inheritance: Multiple classes inherit from a single parent class.

Method Overriding: A child class provides a specific implementation for a method already defined in
its parent class.

Constructor Chaining: When a child object is created, parent constructors are implicitly called in a
chain from the topmost parent.

The super Keyword: Refers to the immediate parent class. Used to:

• Invoke superclass constructor (super()).

• Invoke superclass methods (super.methodName()).

• Access superclass fields (super.fieldName).

Multiple Inheritance (Not Supported in Java): Java does not support a class extending more than
one class to avoid the "Diamond Problem." This is solved using Interfaces.

Code Example (Animal and Dog Classes):

Java

// Animal.java

public class Animal {


public void sayHello() {

System.out.println("...");

// Dog.java

public class Dog extends Animal {

@Override

public void sayHello() {

System.out.println("Woof");

// Test.java

public class Test {

public static void main(String[] args) {

Dog dog = new Dog();

dog.sayHello(); // Output: Woof

4. Polymorphism in Java

https://youtu.be/TRlz0X5hD7E?list=PLA3GkZPtsafY62QhQ030p85HAer0pFDdr

What is Polymorphism? Allows methods to perform different actions based on the object they are
acting upon, while the method name and signature remain the same. Means "many forms."

Types of Polymorphism:

1. Compile-Time Polymorphism (Method Overloading): Multiple methods with the same name
but different parameters within the same class. The decision of which method to call is made
at compile time.

2. Run-Time Polymorphism (Method Overriding / Dynamic Method Dispatch): A subclass


provides a specific implementation for a method defined in its superclass. The decision of
which method to call is made at run time by the JVM.

Upcasting and Downcasting:


• Upcasting: Assigning a child object to a parent class reference (e.g., Animal myDog = new
Dog();).

• Downcasting: Converting a parent class reference back to a child class reference (e.g., Dog
actualDog = (Dog) myDog;).

Code Example (Animal, Cat, Dog with Polymorphism):

Java

class Animal {

public void sayHello() {

System.out.println("...");

class Cat extends Animal {

@Override

public void sayHello() {

System.out.println("Meow");

class Dog extends Animal {

@Override

public void sayHello() {

System.out.println("Woof");

public void sayBye() {

System.out.println("Bye Bye");

class Test {

public static void main(String[] args) {

Animal myDog = new Dog(); // Upcasting


myDog.sayHello(); // Output: Woof (Runtime Polymorphism)

Animal myCat = new Cat(); // Upcasting

myCat.sayHello(); // Output: Meow (Runtime Polymorphism)

Dog actualDog = (Dog) myDog; // Downcasting

actualDog.sayBye(); // Output: Bye Bye (Can call child-specific methods)

5. Abstraction in Java

https://youtu.be/W0Qv4UkCo6k?list=PLA3GkZPtsafY62QhQ030p85HAer0pFDdr

What is Abstraction? Hiding internal details and showing only necessary functionalities.

Achieving Abstraction:

• Abstract Methods: Methods with a declaration but no body, using the abstract keyword.
Implementation is provided by subclasses.

• Abstract Classes: A class containing one or more abstract methods must be declared
abstract. Can have both abstract and concrete methods.

Key Rules:

• Cannot create objects of an abstract class.

• Can create references of an abstract class, pointing to concrete subclasses.

• Subclasses must implement all inherited abstract methods or be declared abstract


themselves.

• Abstract classes can have constructors.

• private abstract methods are not allowed.

Code Example (Animal Abstract Class):

Java

public abstract class Animal {

// Abstract method (no body)

public abstract void sayHello();

// Concrete method

public void sleep() {


System.out.println("Animal is sleeping");

// Dog.java

public class Dog extends Animal {

@Override

public void sayHello() {

System.out.println("Woof");

// Cat.java

public class Cat extends Animal {

@Override

public void sayHello() {

System.out.println("Meow");

// Test.java

public class Test {

public static void main(String[] args) {

Animal dog = new Dog(); // Reference to abstract class, object of concrete subclass

dog.sayHello(); // Output: Woof

dog.sleep(); // Output: Animal is sleeping

6. Access Modifiers in Java

https://youtu.be/ZlUuQIw-a9U?list=PLA3GkZPtsafY62QhQ030p85HAer0pFDdr

Overview: Control the visibility and accessibility of classes, fields, and methods.
• Public: Accessible from anywhere.

• Private: Accessible only within the same class.

• Protected: Accessible within the same package and by subclasses (even in different
packages).

• Default (no keyword): Accessible only within the same package.

Code Example (Public and Private):

Java

// Student.java (in accessmodifier.school package)

package accessmodifier.school;

public class Student {

private String name; // Private field

public int age; // Public field

public void sayHello() { // Public method

System.out.println("Hello");

// Getter/Setter for name if needed

// Test.java (in accessmodifier.test package)

package accessmodifier.test;

import accessmodifier.school.Student;

public class Test {

public static void main(String[] args) {

Student student = new Student();

student.age = 12; // Accessible (public)

// student.name = "Ram"; // Compile-time error (private)

student.sayHello(); // Accessible (public)


}

7. The static Keyword in Java

https://youtu.be/qfMOfbhVpB0?list=PLA3GkZPtsafY62QhQ030p85HAer0pFDdr

Key Concepts:

• Class Part, Not Instance Part: Static members belong to the class, not to individual objects.

• Memory Management: Only one copy of a static member exists, shared by all objects.

Applying static to:

1. Static Variables (Fields): Shared among all instances of a class.

2. Static Methods: Called directly using the class name. Cannot directly use non-static members
or this/super.

3. Static Blocks: Executed when the class is loaded, used for static initialization.

Common Use Cases:

• Utility Classes: Contain only static methods (e.g., Math class).

• Singleton Design Pattern: Ensures only one instance of a class.

Code Example (Student with static count):

Java

public class Student {

public static int count = 0; // Static variable

public Student() {

count++; // Incremented every time a Student object is created

public static void getCount() { // Static method

System.out.println("Total Students: " + count);

// Usage

Student s1 = new Student();


Student s2 = new Student();

Student.getCount(); // Output: Total Students: 2

8. The final Keyword in Java

https://youtu.be/CYBDq23Uzt0?list=PLA3GkZPtsafY62QhQ030p85HAer0pFDdr

Purpose: Makes something constant or unchangeable.

Applying final to:

• Variables: Value cannot be changed once initialized.

Java

public final int SPEED_LIMIT = 200; // Constant

• Methods: Cannot be overridden by any subclass.

Java

public final void airbags() { // Cannot be overridden

System.out.println("Four airbags");

• Classes: Cannot be extended by any other class, preventing inheritance.

Java

public final class PremiumCar { // Cannot be extended

// ...

Final Constructors:

• Constructors cannot be declared final. They are not inherited or overridden in the same way
as methods.

9. Interfaces in Java

https://youtu.be/PpxzFint1IA?list=PLA3GkZPtsafY62QhQ030p85HAer0pFDdr

What is an Interface? A blueprint for a class, used to achieve multiple inheritance and pure
abstraction.

Key Characteristics:

• Cannot create objects of an interface.

• No constructors.

• Classes implement interfaces using the implements keyword.

• Implementing classes must provide an implementation for all abstract methods.

• Can only contain abstract methods and static constants (implicitly public, static, final).
Interface Features (Java 8+):

• Static Methods: Belong to the interface, called directly using the interface name.

• Default Methods: Have a default implementation within the interface, can be overridden by
implementing classes.

Achieving Multiple Inheritance: A class can implement multiple interfaces, allowing it to inherit
functionalities from multiple sources.

Code Example (Smartphone implementing multiple interfaces):

// Interface for Music Player functionality

public interface MusicPlayer {

void playMusic();

void stopMusic();

// Interface for Phone functionality

public interface Phone {

void makeCall(String number);

void endCall();

// Smartphone class implementing multiple interfaces

public class Smartphone implements MusicPlayer, Phone {

@Override

public void playMusic() {

System.out.println("Playing music on Smartphone");

@Override

public void stopMusic() {

System.out.println("Stopping music on Smartphone");

}
@Override

public void makeCall(String number) {

System.out.println("Making call to " + number + " from Smartphone");

@Override

public void endCall() {

System.out.println("Ending call on Smartphone");

This video provides an in-depth explanation of four types of inner classes in Java: Member Inner
Class, Static Nested Class, Local Inner Class, and Anonymous Inner Class.

1. Member Inner Class

• Concept: A class defined inside another class, where the inner class is a member of the outer
class. It is associated with an instance of the outer class.

• Example (Car and Engine):

o An Engine class is defined inside a Car class.

o The Car class has model (String) and isEngineOn (boolean) fields.

o The Engine class has start() and stop() methods that interact with the isEngineOn
field of the outer Car class.

o Code Snippet (Car.java):

Java

class Car {

private String model;

private boolean isEngineOn;

public Car(String model) {

this.model = model;

this.isEngineOn = false;

}
class Engine { // Member Inner Class

public void start() {

if (!isEngineOn) {

isEngineOn = true;

System.out.println(model + " engine started.");

} else {

System.out.println(model + " engine is already on.");

public void stop() {

if (isEngineOn) {

isEngineOn = false;

System.out.println(model + " engine stopped.");

} else {

System.out.println(model + " engine is already off.");

o Code Snippet (Test.java - Usage):

Java

public class Test {

public static void main(String[] args) {

Car car = new Car("Tata Safari");

Car.Engine engine = car.new Engine(); // Creating instance of inner class

engine.start();

engine.stop();

}
• Benefit: Allows the inner class to directly access members (fields and methods) of the outer
class instance. It establishes a strong association between the inner and outer class
instances.

• Alternative (without Inner Class): If not using an inner class, the Engine class would need to
explicitly take a Car instance in its constructor to access Car's properties, leading to more
verbose and less encapsulated code.

2. Static Nested Class

• Concept: A static class defined inside another class. Unlike member inner classes, it belongs
to the outer class itself, not to an instance of the outer class.

• Example (Computer and USB):

o A USB class is defined as static inside a Computer class.

o The Computer class has brand and model fields.

o The USB class has a type field and a displayInfo() method.

o Code Snippet (Computer.java):

Java

class Computer {

private String brand;

private String model;

public Computer(String brand, String model) {

this.brand = brand;

this.model = model;

// Member Inner Class (for comparison)

class OperatingSystem {

private String osName;

public OperatingSystem(String osName) {

this.osName = osName;

public void displayInfo() {


System.out.println("OS: " + osName + " on " + brand + " " + model);

static class USB { // Static Nested Class

private String type;

public USB(String type) {

this.type = type;

public void displayInfo() {

System.out.println("USB Type: " + type);

o Code Snippet (Test.java - Usage):

Java

public class Test {

public static void main(String[] args) {

Computer computer = new Computer("HP", "ABC");

// For OperatingSystem (Member Inner Class)

Computer.OperatingSystem os = computer.new OperatingSystem("XYZ");

os.displayInfo();

// For USB (Static Nested Class)

Computer.USB usb = new Computer.USB("USB-C"); // No outer class instance needed

usb.displayInfo();

• Benefit:
o No Instance Dependency: Does not require an instance of the outer class to be
created.

o Memory Management: Prevents unnecessary memory allocation for the inner class
if the outer class instance is created but the inner class is not used.

o Grouping: Useful for logically grouping classes that are related but don't depend on
an outer class instance.

3. Local Inner Class

• Concept: A class defined inside a method or a block of code. Its scope is limited to the
method or block where it is defined.

• Example (Hotel Reservation):

o A ReservationValidator class is defined inside the reserveRoom() method of the Hotel


class.

o The Hotel class has name, totalRooms, and reservedRooms fields.

o The ReservationValidator class has a validate() method that checks reservation


conditions.

o Code Snippet (Hotel.java):

Java

class Hotel {

private String name;

private int totalRooms;

private int reservedRooms;

public Hotel(String name, int totalRooms, int reservedRooms) {

this.name = name;

this.totalRooms = totalRooms;

this.reservedRooms = reservedRooms;

public void reserveRoom(String guestName, int numberOfRooms) {

class ReservationValidator { // Local Inner Class

public boolean validate() {

if (guestName == null || guestName.isBlank()) {

System.out.println("Guest name cannot be empty.");


return false;

if (numberOfRooms <= 0) {

System.out.println("Number of rooms should be positive.");

return false;

if (reservedRooms + numberOfRooms > totalRooms) { // Accessing outer class fields

System.out.println("Not enough rooms available.");

return false;

return true;

ReservationValidator validator = new ReservationValidator();

if (validator.validate()) {

reservedRooms += numberOfRooms;

System.out.println("Reservation confirmed for " + guestName + " for " + numberOfRooms + "
rooms.");

} else {

System.out.println("Reservation failed.");

o Code Snippet (Test.java - Usage):

Java

public class Test {

public static void main(String[] args) {

Hotel hotel = new Hotel("Sunshine Hotel", 10, 5);

hotel.reserveRoom("Akshit", 1); // Confirmed

hotel.reserveRoom("Shubham", 10); // Not enough rooms


}

• Benefit:

o Encapsulation: Encapsulates logic that is specific to a particular method.

o Contextual: The class is only relevant within the method it's defined in.

o Access to Method Parameters: Can access final or effectively final local variables and
parameters of the enclosing method.

4. Anonymous Inner Class

• Concept: A class without a name, used for one-time implementations of interfaces or


extensions of classes.

• Example (Payment Interface):

o A Payment interface with a pay() method.

o A ShoppingCart class with a processPayment() method that accepts a Payment


object.

o Instead of creating a separate CreditCard class that implements Payment, an


anonymous inner class is used to implement Payment directly when calling
processPayment().

o Code Snippet (Payment.java):

Java

interface Payment {

void pay(double amount);

o Code Snippet (ShoppingCart.java):

Java

class ShoppingCart {

private double totalAmount;

public ShoppingCart(double totalAmount) {

this.totalAmount = totalAmount;

public void processPayment(Payment paymentMethod) {

paymentMethod.pay(totalAmount);
}

o Code Snippet (Test.java - Usage):

Java

public class Test {

public static void main(String[] args) {

ShoppingCart cart = new ShoppingCart(150.0);

// Using Anonymous Inner Class

cart.processPayment(new Payment() {

@Override

public void pay(double amount) {

System.out.println("Paid " + amount + " using Credit Card.");

});

• Benefit:

o Conciseness: Reduces boilerplate code when a class is needed for a single,


immediate use.

o On-the-Fly Implementation: Allows implementing an interface or extending a class


directly at the point of use.

o No Naming Overhead: Avoids the need to create a separate named class file for a
simple, one-off implementation.

The video concludes by summarizing when to use each type of inner class:

• Member Inner Class: When the inner class is strongly associated with and depends on an
instance of the outer class.

• Static Nested Class: When grouping related classes together, but the inner class does not
depend on an instance of the outer class.

• Anonymous Inner Class: For one-time implementations of interfaces or extensions of classes


without creating a separate named class.

• Local Inner Class: When a class's functionality is specific to a single method and its scope
should be limited to that method.

You might also like