0% found this document useful (0 votes)
6 views

JAVA OOP

Object-Oriented Programming (OOP) is a paradigm that organizes software design around objects, which have properties and methods. The four pillars of OOP are encapsulation, abstraction, inheritance, and polymorphism, which enhance code modularity, reusability, scalability, and maintainability. Key concepts include classes as blueprints for objects, constructors for initializing objects, and the 'new' keyword for object creation.
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)
6 views

JAVA OOP

Object-Oriented Programming (OOP) is a paradigm that organizes software design around objects, which have properties and methods. The four pillars of OOP are encapsulation, abstraction, inheritance, and polymorphism, which enhance code modularity, reusability, scalability, and maintainability. Key concepts include classes as blueprints for objects, constructors for initializing objects, and the 'new' keyword for object creation.
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/ 109

Intro to OOP

Object-Oriented Programming (OOP) is a programming paradigm that organizes


software design around objects, rather than functions and logic. An object
represents a real-world entity with properties (data) and methods (functions or
actions).

4 pillars of OOP:
1. Encapsulation

2. Abstraction

3. Inheritance

4. Polymorphism

Key Concepts of OOP:

1. Class:

A class is a blueprint or template for creating objects. It defines the


properties and behaviors that the objects created from it will have.

2. Object:

An object is an instance of a class. It represents a real-world entity with


specific data and can perform actions (methods).

3. Encapsulation:

This principle involves bundling data (properties) and the methods that
operate on the data into a single unit (class). It also involves hiding the
internal details of how data is stored and accessed, exposing only
necessary functionality.

4. Abstraction:

Abstraction involves hiding the complexity of the system by providing a


simple interface. This allows programmers to focus on high-level
functionality rather than the complex inner workings.

Intro to OOP 1
Example: Using interfaces or abstract classes to hide implementation
details.

5. Inheritance:

Inheritance allows a class to inherit properties and methods from another


class, promoting code reuse.

6. Polymorphism:

Polymorphism allows objects of different classes to be treated as objects


of a common superclass. The exact method that is called is determined at
runtime.

Benefits of OOP:

Modularity: The code is organized into classes and objects, making it easier
to maintain and extend.

Reusability: Code in the form of classes can be reused in multiple


applications.

Scalability: It's easier to scale applications by adding new classes and objects
without affecting the existing ones.

Maintainability: Encapsulation and abstraction make the code easier to


understand, modify, and debug.

Intro to OOP 2
Classes and Objects
1. Object:

An object is a real-world entity that represents a specific instance of a


class. It has properties (attributes) and behaviors (methods or actions).

Example: A Human object has properties like name , age , gender , and
behaviors like canRun() , canEat() .

2. Class:

A class is a blueprint or template for creating objects. It defines properties


and behaviors that the objects created from the class will have.

In Java, everything must be done within a class.

Example:

class Pen {
// Properties (variables)
String color = "blue";
float tip = 0.7f;

// Behavior (method)
void displayColor() {
System.out.println("The color of the pen is " + color);
}
}

3. Creating an Object from a Class:

You can create an object (instance) of a class using the new keyword.

Example:

public class Main {


public static void main(String[] args) {

Classes and Objects 1


// Create an object of Pen class
Pen p = new Pen();
// Call the method of the object
p.displayColor();
}
}

Key Points:
Properties are defined by variables inside a class.

Behaviors are defined by methods inside the class.

The class serves as a blueprint, while objects are the actual instances.

Important Questions
1. Can you explain what happens when an object is created from a class, step
by step?

Answer:

1. Class Definition: The class is defined with properties and methods.

2. Object Creation: Using the new keyword, a new instance of the class
is created.

3. Memory Allocation: Memory is allocated for the object.

4. Constructor Call: If a constructor is defined, it is called to initialize the


object’s properties.

5. Object Initialization: The object is now ready to use, with initialized


properties and behaviors.

2. What error occurs when you have a public class defined within another
class file in Java, and how can you fix it?

Error:

Classes and Objects 2


If you define a public class inside a file that doesn't match the class name,
you'll get an error like:

class Pen is public, should be declared in a file named Pen.java

Reason:

In Java, each public class must be in a file with the same name as the class. A
class named Pen must be in a file called Pen.java . You can only have one public
class per file.

Conclusion:
Java requires the file name to match the public class name. If you don't match
it, you'll get a compilation error. You can either rename the file or remove public
to avoid the error.

Can you use other access modifiers (like protected , private , or default ) for top-
level classes?

No, you can only use public or no modifier (package-private) for top-level
classes. Using protected or private will cause an error.

Classes and Objects 3


Constructors
A constructor is a special method used to initialize an object when it is created. It
is automatically called at the time of object creation and has the following
characteristics:

1. No return type: Constructors don't have a return type, not even void .

2. Same name as the class: The constructor's name must be the same as the
class name.

3. Called automatically: A constructor is automatically invoked when an object is


created.

4. Cannot be abstract, static, final, or synchronized: Constructors cannot have


certain modifiers like abstract , static , final , or synchronized .

Types of Constructors:

1. Default Constructor (Non-parameterized constructor):

If no constructor is explicitly defined in a class, Java provides a default


constructor with no parameters. This constructor assigns default values to
the object's properties.

public class MyClass {


MyClass() {
// Default constructor
System.out.println("Object created with default constructor.");
}
}

2. Parameterized Constructor:

This type of constructor accepts parameters and allows you to initialize an


object with specific values when it is created.

Constructors 1
public class MyClass {
private int value;

// Parameterized constructor
MyClass(int value) {
this.value = value;
System.out.println("Object created with value: " + value);
}
}

Constructor Overloading:

Java allows having more than one constructor in a class, each with a different
number or type of parameters. This is known as constructor overloading and
lets you create objects in different ways.

public class MyClass {


private int value;

// Default constructor
MyClass() {
this.value = 0;
}

// Parameterized constructor
MyClass(int value) {
this.value = value;
}
}

Important Questions
1. Can a class have no constructor? If yes, what happens in that case?

Constructors 2
Yes, a class can have no constructor. In that case, Java provides a default
constructor that initializes the object with default values (e.g., 0 for
integers, null for objects, false for boolean).

class MyClass {
int num;
String name;
}

// Default constructor is provided automatically


MyClass obj = new MyClass(); // num = 0, name = null

2. What happens if you do not initialize an object's properties in the


constructor?

If you don't initialize an object's properties explicitly, Java will assign them
default values (e.g., 0 for int , null for reference types, false for boolean ).

3. Can a constructor return a value in Java?

No, a constructor cannot return a value, not even void . A constructor’s


purpose is to initialize an object, not to return a value. If a method is
intended to return a value, it should be defined as a method, not a
constructor.

4. Can a constructor be private in Java?

Answer: Yes, a constructor can be private in Java. A private constructor is


typically used in singleton design patterns, where you want to restrict
object creation to only one instance.

class Singleton {
private static Singleton instance;

private Singleton() {} // Private constructor

public static Singleton getInstance() {

Constructors 3
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

5. What is constructor chaining in Java?

Constructor chaining refers to the process of calling one constructor from


another within the same class or from a superclass constructor. In Java,
the this() keyword is used to invoke another constructor in the same class,
and super() is used to call the constructor of the superclass.

class Parent {
Parent() {
System.out.println("Parent constructor called");
}
}

class Child extends Parent {


Child() {
super(); // Calls Parent's constructor
System.out.println("Child constructor called");
}
}

6. Can you invoke a constructor directly?

No, constructors cannot be invoked like normal methods. They are invoked
implicitly when an object is created using the new keyword. You cannot
explicitly call a constructor from another part of the code.

7. Can a constructor be static in Java? If not, why?

No, a constructor cannot be static in Java.

Constructors 4
Constructors are instance-specific, while static methods are class-
specific.

Therefore, constructors cannot be static in Java.

Constructors 5
new Keyword
The new keyword in Java is used to create new objects and allocate memory for
them. It is crucial for object-oriented programming in Java because it allows you
to instantiate classes and allocate memory for new instances of objects.

Key Points About the new Keyword:

1. Object Creation:

The primary use of the new keyword is to create an instance (or object) of
a class. When you create an object using new , memory is allocated in the
heap for that object.

Syntax:

ClassName objectName = new ClassName();

2. Memory Allocation:

When you use new , Java allocates memory for the object in the heap and
initializes its instance variables (fields) to default values (if not initialized).

3. Constructor Invocation:

The new keyword also calls the constructor of the class to initialize the
object. If no constructor is explicitly defined, Java calls the default
constructor (if available).

4. Garbage Collection:

When an object created with the new keyword is no longer in use, it


becomes eligible for garbage collection. The garbage collector
automatically frees up memory by destroying objects that are no longer
referenced.

Example:

new Keyword 1
class Pen {
String color;
float tip;

// Constructor
Pen(String color, float tip) {
this.color = color;
this.tip = tip;
}

// Method to display information


void display() {
System.out.println("Pen color: " + color + ", Tip: " + tip);
}
}

public class Main {


public static void main(String[] args) {
// Creating an object of class Pen using the new keyword
Pen p1 = new Pen("blue", 0.7f);
p1.display(); // Calls the display method
}
}

Here, Pen p1 = new Pen("blue", 0.7f); creates an object of the Pen class, calling the
constructor with the arguments "blue" and 0.7f .

Conclusion:
The new keyword in Java is used to create objects and allocate memory for
them.

It also calls the constructor of the class to initialize the object.

The new keyword is also used for creating arrays dynamically.

new Keyword 2
Important Questions
1. What happens if you create an object inside a method without using the new

keyword?

If you try to create an object without using the new keyword, you will get a
compile-time error because Java requires the new keyword to allocate
memory for the object and initialize it.

2. What happens when the new keyword is used to create an object in Java?

When you use the new keyword to create an object:

1. Memory Allocation: Memory is allocated for the new object on the


heap.

2. Constructor Invocation: The constructor of the class is called to


initialize the object.

3. Reference: A reference to the newly created object is returned and


assigned to a variable.

new Keyword 3
this Keyword
The this keyword is used to refer to the current object. It helps to distinguish
between instance variables (class attributes) and parameters or local variables
that may have the same name.

Example Without this :

public class Employee {


private int id;

public void setId(int id) { //'id' is both a parameter and a class attribute
id = id;
// Java doesn't know which 'id' to assign (class attribute or parameter)
}
}

Problem:

The statement id = id; assigns the parameter id to itself.

The instance variable id of the Employee object remains unchanged.

Referring to the Current Object:

this refers to the current instance (object) of the class.

It's helpful when you need to differentiate between a class's instance variable
and a parameter with the same name.

Example:

public class Employee {


private int id; // Instance variable

// Setter method with a parameter 'id'

this Keyword 1
public void setId(int id) {
// Here, 'id' refers to the parameter, and 'this.id' refers to the instance var
iable
this.id = id; // 'this.id' refers to the instance variable
}
}

In this example, this.id refers to the instance variable id , while the method
parameter id is used to initialize it. Without this , Java would assume you're
referring to the method parameter.

What Happens Internally:

1. Object Creation:

Employee obj = new Employee(); creates an instance of the Employee class. Let's say
this instance is stored in memory with a reference like obj .

2. Calling setId Method:

When obj.setId(10); is called:

Java internally translates this to something similar to setId(10, obj); , where


obj is implicitly passed as the current object reference.

This means the setId method is now aware of the specific object ( obj )
it is supposed to modify.

3. Method Execution:

Inside the setId method, Java does the following:

public void setId(int id, Employee obj) {


Employee obj1 = obj; //obj1 is a reference to the current object(obj)
obj1.id = id;
//Assign the parameter value to the object's instance variable
}

Here, obj1 points to the same memory location as obj . The line obj1.id = id; is
equivalent to this.id = id; .

this Keyword 2
4. Why this is Used:

The this keyword acts as a shorthand, allowing the developer to write this.id

= id instead of managing references ( obj , obj1 ) explicitly.

Important Questions
1. Can this be used in a static context?

No, this cannot be used in a static context (e.g., static methods or static
blocks). The this keyword refers to the current instance, but static
members belong to the class, not to any specific instance.

2. Can this be passed as an argument to a method?

Yes, this can be passed as an argument to a method. For example:

class Example {
void display() {
print(this); // Passes the current object
}
void print(Example obj) {
System.out.println("Printing object");
}
}

3. What is the output of the following code?

class Test {
int x = 10;
void display() {
int x = 20;
System.out.println(x); // Local variable x
System.out.println(this.x); // Instance variable x
}
public static void main(String[] args) {

this Keyword 3
Test obj = new Test();
obj.display();
}
}

Answer:

20
10

Explanation: x refers to the local variable, while this.x refers to the


instance variable.

4. Can this be used to return the current object from a method?

Yes, this can be used to return the current object from a method. This is
often used in method chaining. For example:

class Example {
int x;
Example setX(int x) {
this.x = x;
return this; // Returns the current object
}
}

5. What is the output of the following code?

class Test {
Test() {
this(10);
System.out.println("Default constructor");
}
Test(int x) {
System.out.println("Parameterized constructor: " + x);
}

this Keyword 4
public static void main(String[] args) {
Test obj = new Test();
}
}

Answer:

Parameterized constructor: 10
Default constructor

Explanation: The this(10) call invokes the parameterized constructor first,


and then the default constructor continues execution.

this Keyword 5
Encapsulation
Encapsulation is a fundamental concept in Object-Oriented Programming (OOP). It
is about hiding the internal details of a class and only exposing what is
necessary. It combines data (variables) and behavior (methods) into a single unit
(class).

Key Features:

1. Data Hiding: The class variables (data) are declared as private , restricting
direct access from outside the class.

2. Access Through Methods: The variables are accessed and modified using
public getter and setter methods.

3. Control Access: Encapsulation allows us to control how data is accessed or


modified, ensuring better security and flexibility.

class Employee {
// Private variables (data hiding)
private String name;
private int id;

// Getter method for id


public int getId() {
return id;
}

// Setter method for id


public void setId(int id) {
this.id = id; // Using 'this' to refer to the current object's id
}

// Getter method for name


public String getName() {

Encapsulation 1
return name;
}

// Setter method for name


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

public class Main {


public static void main(String[] args) {
Employee emp = new Employee();

// Set values using setter methods


emp.setId(101);
emp.setName("John Doe");

// Access values using getter methods


System.out.println("ID: " + emp.getId());
System.out.println("Name: " + emp.getName());
}
}

What Happens:

1. The variables id and name are private and cannot be accessed directly from
outside the Employee class.

2. The setId and setName methods allow controlled modification of these


variables.

3. The getId and getName methods allow controlled access to these variables.

Why Use Encapsulation?

Security: Prevents unauthorized access to sensitive data.

Encapsulation 2
Control: Provides control over data modification.

Flexibility: You can change the implementation without affecting the external
code.

Readability: Makes code more structured and easier to understand.

Key Takeaways:

Private: Restricts direct access to variables.

Public Getter/Setter: Provides controlled access to those variables.

Encapsulation ensures data integrity and security, which is crucial for large
and complex systems.

Access Modifiers
Access modifiers are a key part of implementing encapsulation in Java. They
help control the visibility and accessibility of class members (variables and
methods) and play a crucial role in bundling data and methods while hiding
implementation details.

Subclass
Within Outside
Access Modifier Within Class (outside
Package Package
package)

Public ✅ Yes ✅ Yes ✅ Yes ✅ Yes


Protected ✅ Yes ✅ Yes ✅ Yes ❌ No
Default (no
modifier)
✅ Yes ✅ Yes ❌ No ❌ No
Private ✅ Yes ❌ No ❌ No ❌ No

Encapsulation 3
Polymorphism
Polymorphism is a core concept in Object-Oriented Programming (OOP) that
allows methods or objects to behave differently based on the context. In simple
terms, polymorphism means "many forms."

Polymorphism lets us perform a single action in different ways, depending on the


object or method being used. For example:

A person can act as a teacher in school and a parent at home, but they are still
the same person.

Types of Polymorphism in Java

1. Compile-Time Polymorphism (Static Polymorphism):

Decided at compile time.

Achieved through method overloading (same method name, different


parameters).

2. Run-Time Polymorphism (Dynamic Polymorphism):

Decided at runtime.

Achieved through method overriding (same method name and


parameters, but different implementation in child class).

1. Compile-Time Polymorphism: Method Overloading

When multiple methods have the same name but differ in:

Number of parameters,

Type of parameters, or

Order of parameters.

This is called method overloading.


Example: Method Overloading

Polymorphism 1
class MathUtils {
// Method with two integer parameters
int add(int a, int b) {
return a + b;
}

// Method with two double parameters


double add(double a, double b) {
return a + b;
}

// Method with three integer parameters


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

public class Main {


public static void main(String[] args) {
MathUtils mathUtils = new MathUtils();

System.out.println(mathUtils.add(1, 2)); // Calls add(int, int)


System.out.println(mathUtils.add(1.5, 2.5)); // Calls add(double, double)
System.out.println(mathUtils.add(1, 2, 3)); // Calls add(int, int, int)
}
}

Explanation

At Compile Time: The Java compiler decides which add method to call based
on the number and type of arguments passed.

add(1, 2) calls the method with two integers.

add(1.5, 2.5) calls the method with two doubles.

add(1, 2, 3) calls the method with three integers.

Polymorphism 2
Why It’s Useful: Overloading allows flexibility by using the same method name
for similar operations.

2. Run-Time Polymorphism: Method Overriding

When a child class provides a specific implementation for a method that is already
defined in its parent class, it is called method overriding.
Rules for Method Overriding

1. The method in the child class must have the same name, return type, and
parameters as the method in the parent class.

2. The method in the parent class must be accessible (public or protected).

3. The @Override annotation is optional but recommended for clarity.

4. Only instance methods (non-static) can be overridden.

Example: Method Overriding

class Animal {
void makeSound() {
System.out.println("Animals make sounds");
}
}

class Dog extends Animal {


@Override
void makeSound() {
System.out.println("Dog barks");
}
}

class Cat extends Animal {


@Override
void makeSound() {
System.out.println("Cat meows");
}

Polymorphism 3
}

public class Main {


public static void main(String[] args) {
Animal myAnimal;

myAnimal = new Dog();


myAnimal.makeSound(); // Output: Dog barks

myAnimal = new Cat();


myAnimal.makeSound(); // Output: Cat meows
}
}

Explanation

1. Parent Class Reference: The reference variable myAnimal is of type Animal .

2. Dynamic Binding: At runtime, the JVM decides to call the method based on
the actual object (e.g., Dog or Cat ) that myAnimal refers to.

For myAnimal = new Dog(); the overridden makeSound() in Dog is called.

For myAnimal = new Cat(); the overridden makeSound() in Cat is called.

3. Why It’s Useful: Method overriding allows a subclass to provide a specific


behavior while still being part of the parent class.

Aspect Method Overloading Method Overriding

Binding Type Compile-Time (Static) Run-Time (Dynamic)

Methods with the same name but Subclass redefines a method


Definition
different parameters. from the parent class.

Inheritance Not required Requires inheritance

Return Type Can vary Must be the same

Access Must have equal or broader


Not restricted
Modifiers access

Polymorphism 4
Important Questions
1. Can we overload methods by changing only the return type?

Answer:

No, method overloading is not possible by only changing the return type.
The method signature must differ in parameters (number, type, or order).

2. Can we override a private or final method in Java?

Answer:

Private methods: Cannot be overridden since they are not accessible


outside the class.

Final methods: Cannot be overridden because they are designed to be


constant.

3. What happens if we remove the @Override annotation in method overriding?

Answer:

The code will still compile and run, but if the method signature in the
subclass is incorrect (e.g., wrong parameter or return type), it will not
override the method from the parent class, leading to unexpected
behavior.

Using @Override helps the compiler enforce correctness.

4. Can constructors be overloaded and overridden?

Answer:

Overloading: Yes, constructors can be overloaded (multiple constructors


with different parameters in the same class).

Overriding: No, constructors cannot be overridden because they are not


inherited.

5. What is covariance in method overriding?

Answer:

Polymorphism 5
Covariant return types allow a subclass to override a method and return a
more specific type (subtype) than the method in the parent class.

Example:

class Parent {
Parent display() {
System.out.println("Parent display");
return this;
}
}
class Child extends Parent {
@Override
Child display() {
System.out.println("Child display");
return this;
}
}
public class Test {
public static void main(String[] args) {
Parent obj = new Child();
obj.display(); // Child display
}
}

6. Can polymorphism be achieved without inheritance?

Answer:

Compile-time polymorphism (method overloading): Yes, it can be


achieved without inheritance.

Runtime polymorphism (method overriding): No, it requires inheritance to


work.

8. Trick Question: What will this code print?

Polymorphism 6
class Parent {
void display() {
System.out.println("Parent display");
}
}

class Child extends Parent {


@Override
void display() {
System.out.println("Child display");
}
}

public class Test {


public static void main(String[] args) {
Parent obj = new Child();
obj.display();
}
}

Answer:

It will print Child display . At runtime, the Child 's display() method is called
because the actual object is of type Child .

Polymorphism 7
Inheritance
Inheritance allows one class (child class) to acquire properties and methods from
another class (parent class). It promotes code reusability, scalability, and
improves readability by preventing redundancy.

1. Super Class (Parent Class/Base Class):

The class whose properties and methods are inherited.

Example: class Animal

2. Sub Class (Child Class/Derived Class):

The class that inherits properties and methods from the superclass.

Example: class Dog extends Animal

Syntax of Inheritance

class SuperClass {
// properties and methods of the superclass
}

class SubClass extends SuperClass {


// additional properties and methods of the subclass
}

Types of Inheritance in Java

1. Single-Level Inheritance
A subclass inherits from one parent class.

Example:

Inheritance 1
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}

class Dog extends Animal {


void bark() {
System.out.println("The dog barks.");
}
}

public class Main {


public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Inherited method
dog.bark(); // Subclass method
}
}

Output:

This animal eats food.


The dog barks.

2. Multi-Level Inheritance
A class inherits from another class, which itself is a subclass of another.

Example:

Inheritance 2
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}

class Dog extends Animal {


void bark() {
System.out.println("The dog barks.");
}
}

class GermanShepherd extends Dog {


void dangerous() {
System.out.println("German Shepherds are guard
dogs.");
}
}

public class Main {


public static void main(String[] args) {
GermanShepherd gs = new GermanShepherd();
gs.eat(); // Method from Animal
gs.bark(); // Method from Dog
gs.dangerous(); // Method from GermanShepherd
}
}

Output:

This animal eats food.


The dog barks.
German Shepherds are guard dogs.

Inheritance 3
3. Hierarchical Inheritance
Multiple subclasses inherit from a single parent class.

Example:

class Animal {
void eat() {
System.out.println("Eats food.");
}
}

class Dog extends Animal {


void bark() {
System.out.println("The dog barks.");
}
}

class Cat extends Animal {


void meow() {
System.out.println("The cat meows.");
}
}

public class Main {


public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Inherited from Animal
dog.bark(); // Subclass method

Cat cat = new Cat();


cat.eat(); // Inherited from Animal
cat.meow(); // Subclass method
}
}

Inheritance 4
Output:

Eats food.
The dog barks.
This animal eats food.
The cat meows.

4. Hybrid Inheritance
In languages like Java, hybrid inheritance can also be achieved by combining
different types of inheritance like single-level, multi-level, and hierarchical
inheritance.

Example (Using Multi-level and Hierarchical Inheritance):

Here, we combine multi-level inheritance and hierarchical inheritance without


using interfaces.

class Animal {
void eat() {
System.out.println("Eats food.");
}
}

class Dog extends Animal {


void bark() {
System.out.println("The dog barks.");
}
}

class Cat extends Animal {


void meow() {
System.out.println("The cat meows.");
}
}

Inheritance 5
class PetDog extends Dog {
void play() {
System.out.println("The dog plays.");
}
}

public class Main {


public static void main(String[] args) {
PetDog petDog = new PetDog();
petDog.eat(); // Inherited from Animal
petDog.bark(); // Inherited from Dog
petDog.play(); // Subclass method in PetDog

Cat cat = new Cat();


cat.eat(); // Inherited from Animal
cat.meow(); // Subclass method in Cat
}
}

Output:

Eats food.
The dog barks.
The dog plays.
This animal eats food.
The cat meows.

Explanation:
In this example, we're combining multi-level inheritance (Dog → PetDog) and
hierarchical inheritance (Dog and Cat both inherit from Animal). Even without
interfaces, this demonstrates a "hybrid" inheritance approach by utilizing multiple
inheritance mechanisms in one program.

5. Multiple Inheritance

Inheritance 6
Java does not support multiple inheritance with classes.

Multiple inheritance occurs when a class tries to inherit from two or more
classes, leading to ambiguity.

Example of Ambiguity:

class A {
void show() {
System.out.println("Method from Class A");
}
}

class B {
void show() {
System.out.println("Method from Class B");
}
}

// This leads to ambiguity


// class C extends A, B {
// void display() {
// show(); // Which show() to call?
// }
// }

Why doesn't Java allow this?

If both parent classes ( A and B ) have a method with the same name,
Java cannot determine which method to inherit.

A has show() and B also has show() now which show() needs to be
called by the inherited class ?

This leads to ambiguity.

But, by using Interfaces we can achieve multiple Inheritance.

Advantages of Inheritance

Inheritance 7
1. Code Reusability:

Methods and properties of the parent class can be reused in the child
class without rewriting them.

2. Extensibility:

New functionality can be added to an existing class by creating


subclasses.

3. Improved Maintainability:

Changes in the parent class automatically reflect in subclasses.

Key Notes and Rules

1. Access Modifiers:

Public and protected members are inherited. Private members are not
directly inherited but can be accessed via public or protected methods.

Example:

class Animal {
private void secret() {
System.out.println("This is a secret!");
}

protected void accessSecret() {


secret();
}
}

class Dog extends Animal {


void reveal() {
accessSecret();
}
}

Inheritance 8
2. Constructors are not inherited.

Child classes can call parent constructors using super() .

Example:

Output:

class Animal {
Animal() {
System.out.println("Animal constructor called");
}
}

class Dog extends Animal {


Dog() {
super(); // Explicitly calls the parent class constructor
System.out.println("Dog constructor called");
}
}

public class Main {


public static void main(String[] args) {
Dog dog = new Dog();
}
}

Animal constructor called


Dog constructor called

3. Overriding Methods:

A child class can override parent class methods to provide its specific
implementation.

Example:

Inheritance 9
class Animal {
void sound() {
System.out.println("Animals make sounds");
}
}

class Dog extends Animal {


@Override
void sound() {
System.out.println("Dogs bark");
}
}

public class Main {


public static void main(String[] args) {
Animal animal = new Dog();
animal.sound(); // Dogs bark
}
}

Disadvantages of Inheritance

1. Tight Coupling:

The child class depends on the parent class; changes in the parent class
can affect subclasses.

2. Increase in Complexity:

Deep inheritance hierarchies can make debugging and understanding the


code harder.

Important Questions
1. Can we inherit private members of a class?

Inheritance 10
Answer:

No, private members of a class cannot be directly inherited. They are not
accessible outside the class, including in subclasses. However, you can
access them indirectly through public or protected methods in the parent
class.

2. Can we override a private or static method?

Answer:

No, you cannot override private or static methods in Java:

Private methods are not inherited by subclasses, so they cannot be


overridden.

Static methods belong to the class, not instances, so they are not
overridden. Instead, they can be hidden.

3. Can a constructor be inherited?

Answer:

No, constructors are not inherited. However, a subclass can call a


constructor of the superclass using the super keyword.

4. What is the diamond problem in Java, and how does Java solve it?

Answer:

The diamond problem occurs in multiple inheritance, where a class inherits


from two classes that have the same method, leading to ambiguity.

Java solves this by not allowing multiple inheritance of classes. Java


provides multiple inheritance through interfaces (which do not have this
problem) instead of classes.

5. What happens if two parent classes have methods with the same signature,
and a subclass inherits both?

Answer:

Inheritance 11
Java does not allow multiple inheritance with classes, so if you attempt
to create such a scenario, it will lead to a compilation error. Java resolves
this issue by supporting multiple inheritance only through interfaces.

If both interfaces have the same method signature, the subclass must override
the method and provide an implementation.
Example with interfaces:

interface A {
void display();
}

interface B {
void display();
}

class C implements A, B {
@Override
public void display() {
System.out.println("Method from class C");
}
}

6. What is the role of instanceof in inheritance?

Answer:

is used to check if an object is an instance of a particular class or


instanceof

interface.

It can be used to check the type of an object in the inheritance hierarchy


before performing operations on it.

Example:

class Animal {}
class Dog extends Animal {}

Inheritance 12
Animal a = new Dog();

if (a instanceof Dog) {
System.out.println("a is an instance of Dog");
}

7. Explain the concept of "is-a" and "has-a" relationships in Java inheritance.

Answer:

"is-a" relationship: This refers to inheritance, where a subclass is a type


of the parent class. For example, Dog is an Animal .

"has-a" relationship: This refers to composition or aggregation, where


one class has a reference to another class. For example, a Car has an Engine .

Inheritance 13
static Keyword
The static keyword in Java is used to share variables or methods among all
instances (objects) of a class. This means, instead of each object having its own
copy of the variable or method, the class itself holds one shared version of it. This
is especially useful for memory management because static variables and
methods are loaded into memory only once, regardless of how many objects are
created.

Types of Static Components

The static keyword can be used with:

1. Static Variables (also known as Class Variables)

2. Static Methods (also known as Class Methods)

3. Static Blocks

4. Static Nested Classes

1. Static Variable (Class Variable)


A static variable is shared among all objects of the class. It is initialized once
when the class is loaded, and any change made to it through one object is
reflected in all other objects of that class.
Example:

class Mobile {
static String brand; // Static variable
static int price; // Static variable
}

public class Main {


public static void main(String[] args) {
Mobile obj1 = new Mobile(); // First object of Mobile

static Keyword 1
Mobile obj2 = new Mobile(); // Second object of Mobile

obj1.brand = "Apple"; // Assigning to static variable via obj1


obj1.price = 1500; // Assigning to static variable via obj1

System.out.println(obj2.brand); // Output: Apple


System.out.println(obj2.price); // Output: 1500
}
}

Explanation:

Both obj1 and obj2 share the same static variables brand and price because
static variables belong to the class itself, not the individual objects.

When obj1 assigns "Apple" to brand , the same brand is reflected in obj2 (since
they share it).

Static Variables and Memory:

Stack Memory: Each object’s address( obj1 , obj2 ) is stored here.

Heap Memory: Objects are stored here.

static Keyword 2
Key points about static method:

You can access static variables directly using the class name, without
creating an instance.

Shared among all objects of the class, and only one copy exists in memory.

2. Static Method (Class Method)


A static method belongs to the class and not to an object. It can be called without
creating an object of the class. Static methods can only access static variables
directly (they can't access instance variables).

Example:

class Mobile {
static String brand = "Samsung"; // Static variable

// Static method
public static void showBrand() {
System.out.println("Brand: " + brand); // Accessing static variable

static Keyword 3
}
}

public class Main {


public static void main(String[] args) {
// Calling static method directly without an object
Mobile.showBrand(); // Output: Brand: Samsung
}
}

Explanation:

The showBrand() method is static, so it can be called directly using the class
name Mobile.showBrand() without creating an object.

Key points about static method:

Static methods cannot use this or super because these keywords refer to the
current object or parent class, and static methods are not tied to any instance.

Static methods cannot be overridden because they belong to the class, not
instances. If a subclass defines a static method with the same signature, it is
method hiding, not overriding.

Overloading of static methods is allowed

Static methods are often used for utility or helper functionality, such as Math

methods:

Math.max(10, 20);
Math.sqrt(25);

3. Static Block
A static block is used to initialize static variables when the class is first loaded. It
is executed only once, when the class is loaded into memory.

Example:

static Keyword 4
class Example {
static int number; // Static variable

// Static block to initialize static variable


static {
number = 10;
System.out.println("Static block executed");
}

public static void main(String[] args) {


System.out.println("Number: " + number); // Output: 10
}
}

Explanation:

The static block runs once when the class is loaded, even before any objects
are created.

It initializes the static variable number to 10 .

4. Static Nested Class


A static nested class is a class defined inside another class with the static
keyword. A static nested class can be instantiated without creating an instance of
the outer class. It can only access the static members of the outer class.

Example:

class OuterClass {
static String outerVariable = "Outer Class";// Static variable in outer class

// Static nested class


static class StaticNestedClass {
void display() {
System.out.println("Inside static nested class");
System.out.println("Outer class variable: " + outerVariable);

static Keyword 5
// Accessing static variable of outer class
}
}
}

public class Main {


public static void main(String[] args) {
// Creating an instance of the static nested class without creating an obje
ct of the outer class
OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNested
Class();
nestedObj.display(); // Output: Inside static nested class
// Outer class variable: Outer Class
}
}

Explanation:

The StaticNestedClass can be instantiated independently, without the need for an


object of the OuterClass .

It can access the static variable outerVariable of the outer class.

Important Questions
1. Can we use static variables in non-static methods ?

Yes, static variables can be used in both static and non-static methods. This is
because static variables belong to the class itself, not any specific instance. So,
they are accessible from both static and non-static methods.

2. Can we use super or this in Static Methods ?

You cannot use super (to refer to the superclass) or this (to refer to the current
object) inside a static method because static methods are not associated with any
specific object.

3. Can we use non-static variables in static methods?

static Keyword 6
No, non-static variables cannot be accessed directly in a static method. This is
because non-static variables belong to individual objects, whereas static methods
are associated with the class itself. Since a static method doesn't know which
object (or instance) it's working with, it can't directly access instance variables
(non-static variables).

To understand why, let's take an example:

class Mobile {
String brand; // Non-static variable
int price; // Non-static variable

public Mobile(String brand, int price) {


this.brand = brand;
this.price = price;
}

public static void show() {


System.out.println(brand + ": " + price);
// Error! Cannot access non-static variables
}

public static void main(String[] args) {


Mobile obj1 = new Mobile("Apple", 1500);
Mobile obj2 = new Mobile("Samsung", 2500);
Mobile.show(); // This will throw a compilation error
}
}

Why does this fail?

brand and price are instance variables. Each object of Mobile has its own value
for these variables.

The static method show() doesn't know which object's brand or price to print
because it is not associated with any object. It belongs to the class, and thus
can't access instance variables directly.

static Keyword 7
4. How to Access Non-Static Variables in a Static Method ?

Although you can't directly access non-static variables in a static method, you can
pass an object as a parameter to the static method. Then, you can access the
non-static variables through that object.
Example:

class Mobile {
String brand; // Non-static variable
int price; // Non-static variable

public Mobile(String brand, int price) {


this.brand = brand;
this.price = price;
}

// Static method that accepts an object as parameter


public static void show(Mobile obj) {
System.out.println(obj.brand + ": " + obj.price);
// Access non-static variables via object
}

public static void main(String[] args) {


Mobile obj1 = new Mobile("Apple", 1500);
Mobile obj2 = new Mobile("Samsung", 2500);

Mobile.show(obj1); // Output: Apple: 1500


Mobile.show(obj2); // Output: Samsung: 2500
}
}

Explanation:

In the show() method, we pass the object ( obj1 or obj2 ) as a parameter.

We can access the non-static variables ( brand and price ) of that object inside
the static method.

static Keyword 8
Output:

Apple: 1500
Samsung: 2500

5. Why do we need to initialize main with static ?

Lets say we do not use static :

public class Hello {


public void main(String[] args) {
// Non-static main
}
}

1. The main method becomes a non-static method.

2. To call a non-static method, we need to create an object of the class first.

3. However, the program's execution begins with main() , and if execution hasn’t
started yet, there is no way to create an object of the Hello class.

By making the main method static :

public class Hello {


public static void main(String[] args) {
// Static main
}
}

1. The JVM can call main directly without creating an object of the class.

2. This ensures that the program can start execution properly.

So, the main method must be static to allow the JVM to execute it as the entry
point without requiring an object.

6. When there is a constructor to initialize static variables why do we need a


static block?

static Keyword 9
Constructor → Runs Every Time:
A constructor runs whenever a new object is created. If you initialize a static
variable in a constructor, it will reset the variable each time an object is
created, overwriting the previous value.

Static Block → Static is Class-Level:

Static variables belong to the class, not objects. Using a constructor for static
variables leads to redundant initialization.

Why Use a Static Block?

1. Executes Once:
A static block runs only once, when the class is loaded, making it efficient
for static variable initialization.

2. Avoids Overwriting:
Ensures static variables are initialized just once, regardless of the number
of objects created.

Example

With Constructor

class Example {
static int num;
Example() { num = 10; } // Runs every object creation
}

With Static Block

class Example {
static int num;
static { num = 10; } // Runs only once
}

static Keyword 10
super Keyword
The super keyword is used to refer to the parent class in Java.

Key Points to Remember

1. super() must be the first statement in a constructor.

2. If no constructor is explicitly written in a class, the compiler automatically


inserts a call to the parent class's default constructor.

3. super cannot be used in a static context.

4. The default superclass of all Java classes is Object .

What is the Parent Class of Every Class?

Every class in Java extends the Object class by default.

If no explicit parent is provided, the parent is Object .

1. Access Parent Class Constructor


Every constructor implicitly calls the parent class’s default constructor using
super() .

If the parent class has a parameterized constructor, you must explicitly call it
using super(parameters) .

super() must be the first line of a constructor.

class A {
A() { System.out.println("In A"); }
A(int n) { System.out.println("In A-parameterized"); }
}

class B extends A {
B() {

super Keyword 1
//super(); // Calls parent’s default constructor(no need to use super())
System.out.println("In B");
}
B(int n) {
super(n); // Calls parent’s parameterized constructor
System.out.println("In B-parameterized");
}
}

public class Main {


public static void main(String[] args) {
B b1 = new B();
B b2 = new B(5);
}
}

Output:

In A
In B
In A-parameterized
In B-parameterized

2. Access Parent Class Methods and Variables


Use super.methodName() to call a parent class method.

Use super.variableName to access a parent class variable if there is a name


conflict.

Example: Accessing Parent Members

class A {
int a = 10;
void display() { System.out.println("Display in A"); }
}

super Keyword 2
class B extends A {
int a = 20;
void display() {
super.display(); // Calls parent’s display method
System.out.println("Super a: " + super.a); // Access parent’s variable
System.out.println("Child a: " + this.a); // Access child’s variable
}
}

public class Main {


public static void main(String[] args) {
B b = new B();
b.display();
}
}

Output:

Display in A
Super a: 10
Child a: 20

Using this() and super() Together

You can call a default constructor within a parameterized constructor using


this() .

Example:

class A {
A() { System.out.println("In A"); }
}

class B extends A {

super Keyword 3
B() { System.out.println("In B"); }
B(int n) {
this(); // Calls the default constructor in the same class
System.out.println("In B-int");
}
}

public class Main {


public static void main(String[] args) {
B b = new B(5); // Output: In A -> In B -> In B-int
}
}

Important Questions
1. Can super be used inside a static method?

No, super cannot be used inside a static method because super is linked to an
instance, and static methods belong to the class, not an instance.

2. Can you call both super() and this() in the same constructor?

No, because both must be the first statement, and Java does not allow two first
statements in a constructor.

3. Can a subclass call a private method of the parent class using super ?

No, super cannot access private methods of the parent class because private
methods are not inherited.

4. If a parent class and a child class have the same method name, how do you
call the parent’s method from the child class?

Use super.methodName(); to call the parent class's method inside the child class.

5. Can we use super inside a constructor?

Yes, but only as the first statement to call the parent class constructor.

super Keyword 4
6. If a parent class has multiple constructors, how does the child class choose
which one to call?

The child class must explicitly call the required constructor using super(arguments); .

7. In Java, why do we need the super keyword if we can access parent class
properties through inheritance?

While inheritance allows a subclass to access the properties and methods of its
parent class, the super keyword is necessary for specific scenarios where explicit
interaction with the parent class is required. Here's why the super keyword is
essential:

Calling Parent Class Constructors:

When creating an instance of a subclass, the parent class's constructor must


be invoked to initialize inherited properties. The super keyword is used to
explicitly call the parent class's constructor, especially when it has
parameters.

class Parent {
Parent(int x) {
System.out.println("Parent constructor: " + x);
}
}

class Child extends Parent {


Child(int x) {
super(x); // Calls the Parent class constructor
System.out.println("Child constructor");
}
}

Without super , you wouldn't be able to invoke the parent class's constructor
explicitly.

Accessing Shadowed or Overridden Members:

super Keyword 5
If a subclass defines a field or method with the same name as one in the
parent class, the subclass's member shadows or overrides the parent's
member. The super keyword is used to access the parent class's version of the
member.

class Parent {
int x = 10;
}

class Child extends Parent {


int x = 20;

void print() {
System.out.println("Child x: " + x); // Accesses Child's x
System.out.println("Parent x: " + super.x); // Accesses Parent's x
}
}

Without super , you wouldn't be able to access the parent class's x if it's
shadowed by the subclass's x .

Calling Overridden Methods:

If a subclass overrides a method from the parent class, super can be used to
call the parent class's overridden method.

class Parent {
void display() {
System.out.println("Parent display");
}
}

class Child extends Parent {


@Override
void display() {
super.display(); // Calls Parent's display method
System.out.println("Child display");

super Keyword 6
}
}

Without super , you wouldn't be able to invoke the parent class's overridden
method.

8. Why must super() be the first line of a constructor in Java?

In Java, super() must be the first line of a constructor because the parent class's
constructor needs to be called before the subclass's constructor can execute.
This ensures that the parent class is properly initialized before the subclass
begins its own initialization.

9. What happens if we try to initialize super() in any other line besides the first
line of a constructor?

If you try to call super() in any line other than the first line of a constructor, the Java
compiler will throw a compile-time error. This is because Java enforces strict
rules about constructor chaining to ensure proper initialization of objects.

super Keyword 7
final Keyword
The final keyword is used to define entities (variables, methods, or classes) that
cannot be changed, overridden, or extended. Here's how it works:

1. Final Variable
A variable declared as final can be assigned only once.

Attempting to reassign a value results in a compile-time error.

Example:

final int value = 10;


value = 12; // Error: Cannot assign a value to a final variable

2. Final Method
A final method cannot be overridden by subclasses.

Ensures that the method's implementation remains unchanged.

Example:

class Parent {
final void display() {
System.out.println("Display in Parent");
}
}

class Child extends Parent {


// void display() { } // Error: Cannot override the final method
}

3. Final Class

final Keyword 1
A final class cannot be inherited.

Useful for classes whose implementation should not be altered.

Example:

final class Parent { }

class Child extends Parent { } // Error: Cannot inherit from final class

final vs finalize vs finally

Feature Description
final Used to declare constants, prevent method overriding, or inheritance.

A protected method of the Object class, called by the garbage collector


finalize
before an object is destroyed. Deprecated in Java 9.

A block of code that is always executed, regardless of whether an


finally
exception occurs or not.

final Keyword 2
abstract Keyword
The abstract keyword is used to define abstract classes and abstract methods.

1. Abstract Class
An abstract class cannot be instantiated directly, meaning you cannot create
objects of an abstract class.

It may contain both abstract methods (methods without a body) and non-
abstract methods (methods with a body).

Example:

abstract class Car {


abstract void drive(); // Abstract method

void playMusic() { // Non-abstract method


System.out.println("Playing music");
}
}

Subclasses of the abstract class must implement the abstract methods.

2. Abstract Method
An abstract method is a method without a body. It must be implemented by
subclasses of the abstract class.

Example:

abstract class Car {


abstract void drive(); // Abstract method, no body
}

In a subclass, you must provide an implementation for the abstract method.

abstract Keyword 1
Example:

class Wagon extends Car {


@Override
void drive() {
System.out.println("Wagon is driving");
}
}

abstract class Vehicle {


abstract void start(); // Abstract method

void stop() { // Non-abstract method


System.out.println("Vehicle stopped");
}
}

class Bike extends Vehicle {


@Override
void start() { // Abstract mwthod must be defined in subclass
System.out.println("Bike started");
}
}

public class Main {


public static void main(String[] args) {
// Vehicle v = new Vehicle(); //Error: Can't instantiate abstract class

Bike bike = new Bike();


bike.start(); // Output: Bike started
bike.stop(); // Output: Vehicle stopped
}
}

abstract Keyword 2
Interfaces
An interface in Java is a reference type, similar to a class, but it can only contain
abstract methods (until Java 8, after which it can contain default and static
methods as well). Interfaces are used to define a contract that classes must
adhere to.

An interface cannot be instantiated (you cannot create an object of an


interface directly).

A class implements an interface and must provide implementations for all the
abstract methods declared in the interface.

Key Features of an Interface


1. Abstract Methods

By default, all methods in an interface are abstract (without


implementation).

2. No Constructor

Interfaces do not have constructors, because they cannot be instantiated.

3. Public, Static, and Final Variables

All variables declared inside an interface are implicitly public, static, and
final.

The value must be initialized at the time of declaration.

4. Multiple Inheritance

A class can implement multiple interfaces, which allows Java to support


multiple inheritance of behavior.

5. Default Methods (Java 8+)

Interfaces can contain default methods, which provide a default


implementation.

6. Static Methods (Java 8+)

Interfaces 1
Interfaces can also contain static methods. These are similar to static
methods in classes, and they are invoked by the interface name.

Interface Implementation
A class that implements an interface must provide concrete implementations for
all abstract methods declared by the interface.

interface Animal {
void sound();
}

class Dog implements Animal {


@Override
public void sound() {
System.out.println("Bark");
}
}

public class Main {


public static void main(String[] args) {
Animal animal = new Dog();
animal.sound(); // Output: Bark
}
}

Note: A class must implement all abstract methods from an interface unless
the class is abstract itself.

Functional Interface

A functional interface is an interface that contains only one abstract method.


These interfaces are used extensively in Java for lambda expressions.

You can annotate a functional interface with @FunctionalInterface (optional, but it


helps in ensuring that the interface meets the criteria).

Interfaces 2
Functional interfaces can have multiple default or static methods, but they
must have exactly one abstract method.

@FunctionalInterface
interface Calculator {
int add(int a, int b); // Single abstract method

default void printMessage() {


System.out.println("Performing calculation...");
}
}

Inheritance of Interfaces

An interface can extend another interface, just like classes inherit from other
classes.

When an interface extends another interface, it inherits all the abstract


methods of the parent interface, and a class that implements the child
interface must provide implementations for all inherited methods.

interface Animal {
void sound();
}

interface Mammal extends Animal {


void walk();
}

class Dog implements Mammal {


@Override
public void sound() {
System.out.println("Bark");
}

Interfaces 3
@Override
public void walk() {
System.out.println("Walks on 4 legs");
}
}

Can an Interface Inherit Multiple Interfaces?

Yes, an interface can extend multiple interfaces, allowing multiple inheritance for
interfaces.

interface Animal {
void sound();
}

interface Mammal {
void walk();
}

interface Dog extends Animal, Mammal {


void breed();
}

Anonymous Classes and Interfaces

An interface can be implemented via anonymous classes, where the


implementation is provided at the point of use, without the need for a named
class.

interface Animal {
void sound();
}

public class Main {

Interfaces 4
public static void main(String[] args) {
Animal dog = new Animal() {
public void sound() {
System.out.println("Bark");
}
};
dog.sound(); // Output: Bark
}
}

Interface vs Abstract Class

Abstract Class:

Can have both abstract and concrete methods.

Can have member variables (fields).

Can have constructors.

A class can inherit only one abstract class (single inheritance).

Interface:

Can only have abstract methods (before Java 8).

Cannot have constructors or instance variables.

A class can implement multiple interfaces (multiple inheritance).

Important Questions
1. What happens if two interfaces have the same default method signature?

Answer: If two interfaces that a class implements have the same default
method signature, the class must override the method to resolve the conflict.
Java does not know which default method to inherit, so it forces the class to
provide its own implementation.

Interfaces 5
interface A {
default void display() {
System.out.println("Display from A");
}
}

interface B {
default void display() {
System.out.println("Display from B");
}
}

class C implements A, B {
@Override
public void display() {
System.out.println("Display from C");
}
}

2. Can an interface have private methods?

Answer: Since Java 9, interfaces can have private methods. These private
methods cannot be accessed outside the interface, but they can be used to
share code between default methods in the interface.

interface A {
private void privateMethod() {
System.out.println("Private method");
}

default void defaultMethod() {


privateMethod(); // Valid usage within the interface
}
}

Interfaces 6
3. What happens if a class implements an interface but does not provide
implementations for all abstract methods?

Answer: If a class implements an interface, it must provide implementations


for all the abstract methods defined in the interface. If the class does not
provide implementations, it must be declared as abstract .

4. Can an interface extend a class?

Answer: No, an interface cannot extend a class. An interface can only extend
other interfaces. However, a class can implement multiple interfaces and
extend one class.

5. Can an interface have multiple methods with the same name?

Answer: Yes, an interface can have multiple methods with the same name, but
they must have different parameter lists (overloading). Methods in an interface
can also have the same name as long as they are not conflicting.

interface A {
void display(int x);
void display(String x);
}

6. Can an interface have a main method?

Answer: Yes, an interface can have a main method, and it can be executed just
like a class. However, it is not common to define a main method in an interface,
as the interface is typically used to define behavior that will be implemented
by other classes.

interface A {
public static void main(String[] args) {
System.out.println("Main method in interface");
}
}

Interfaces 7
7. What happens in the following code?

interface Main {

class A {
int a = 10;
}

public static void main(String[] args) {


System.out.println("Main method in interface");
A obj = new A();
System.out.println(obj.a);
}
}

This code demonstrates the use of a main method inside an interface along
with a nested class. Here's what happens:

1. Interface with a main Method:

The Main interface contains a public static void main(String[] args) method,
which serves as the entry point for the program.

Since the main method is static , it can be executed without requiring an


instance of the interface.

2. Nested Class A :

The class A is defined inside the Main interface. This is a nested class
and is implicitly static because it is defined inside an interface.

The class A has an instance variable a initialized to 10 .

3. Creating an Instance of A :

Inside the main method, an instance of the nested class A is created


using A obj = new A(); .

The value of obj.a (which is 10 ) is printed to the console.

When you run this program, the output will be:

Interfaces 8
Main method in interface
10

This is allowed because of the following reasons:

1. Static Methods in Interfaces (Java 8+):

Java 8 introduced the ability to define static methods in interfaces. The


main method is a static method, so it can be included in an interface.

2. Nested Classes in Interfaces:

Classes defined inside an interface are implicitly static and public . They
can be instantiated and used like any other class.

3. No Need for an Implementing Class:

Since the main method is static , you don’t need to create an instance of
the Main interface or provide an implementing class to run the
program.

To run this program:

1. Save the code in a file named Main.java .

2. Compile and execute it using the following commands:

javac Main.java
java Main

8. Can you explain polymorphism with an interface?

Answer:

Polymorphism allows different classes to implement the same interface


and provide their own specific behavior.

Example:

interface Animal {
void makeSound();
}

Interfaces 9
class Dog implements Animal {
public void makeSound() {
System.out.println("Dog barks");
}
}
class Cat implements Animal {
public void makeSound() {
System.out.println("Cat meows");
}
}
public class Test {
public static void main(String[] args) {
Animal animal;
animal = new Dog();
animal.makeSound(); // Dog barks
animal = new Cat();
animal.makeSound(); // Cat meows
}
}

Interfaces 10
Lambda Expressions
Lambda expressions in Java provide a way to express instances of functional
interfaces (interfaces with a single abstract method) in a more concise and
readable way. They enable you to write code that treats functionality as a method
argument or passes behavior as an argument.

What is a Lambda Expression?

A lambda expression is a short block of code that takes in parameters, processes


them, and returns a result. It is often used to provide the implementation of a
functional interface.
The syntax for a lambda expression is:

(parameters) -> expression

Syntax Breakdown

Parameters: A list of parameters that the lambda takes. It can be empty if no


arguments are required.

Arrow ( > ): Separates parameters from the body.

Body: The expression or block of code that defines what the lambda does.

Lambda Expression Variations

No Parameters: () -> System.out.println("Hello, World!")

Single Parameter: (x) -> x * 2

Multiple Parameters: (a, b) -> a + b

Block Body (Multiple Statements):


If you need more than one statement in the body, wrap the statements in curly
braces
{} .

Lambda Expressions 1
(a, b) -> {
int result = a + b;
return result;
}

Examples of Lambda Expressions


Example 1: No Parameters

Runnable r = () -> System.out.println("Hello, World!");


r.run(); // Output: Hello, World!

Here:

No parameters are passed (empty parentheses () ).

The body contains a single line of code, which prints "Hello, World!".

Example 2: Single Parameter

// A lambda expression that takes one parameter and prints it


Consumer<String> greet = name -> System.out.println("Hello, " + name);
greet.accept("Alice"); // Output: Hello, Alice

Here:

The lambda expression takes a single parameter ( name ).

The body of the lambda prints the name with a greeting.

Example 3: Multiple Parameters

// A lambda expression that takes two parameters and returns their sum
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
System.out.println(add.apply(5, 3)); // Output: 8

Here:

Lambda Expressions 2
The lambda expression takes two parameters ( a and b ).

It returns their sum ( a + b ).

Basic Example of Lambda Expression with Functional Interface

Functional Interface

@FunctionalInterface
interface Greet {
void sayHello(String name); // Single abstract method
}

Lambda Expression Implementing the Functional Interface

public class LambdaExample {


public static void main(String[] args) {
// Using a lambda expression to implement the Greet interface
Greet greet = (name) -> System.out.println("Hello, " + name);

// Calling the method


greet.sayHello("Alice");
}
}

Output:

Hello, Alice

In this example:

The Greet interface is a functional interface because it has only one abstract
method: sayHello .

The lambda expression (name) -> System.out.println("Hello, " + name) is used to provide
the implementation of sayHello .

Lambda Expressions 3
Object class
In Java, all classes implicitly extend the Object class. This means every class you
create automatically inherits methods from Object , which is the root class of the
Java class hierarchy.

Important Methods in Object Class


There are several important methods in the Object class that are commonly
overridden in custom classes:

1. equals(Object obj)

2. toString()

What Happens if equals and toString are Not Overridden?

If you do not override the equals() and toString() methods in your custom class, the
default behavior provided by the Object class will be used.

1. Default Behavior of equals()

By default, the equals() method in the Object class checks for reference equality,
meaning it compares if the two object references point to the same memory
location (i.e., the same object in memory). This is not typically useful when
comparing objects based on their contents (like field values).

Example without overriding equals() :

class Person {
String name;
int age;

Person(String name, int age) {


this.name = name;
this.age = age;
}

Object class 1
}

public class Main {


public static void main(String[] args) {
Person person1 = new Person("Alice", 25);
Person person2 = new Person("Alice", 25);

System.out.println(person1.equals(person2)); // false
}
}

Output:

false

Even though person1 and person2 have the same values ( "Alice" and 25 ), the equals()
method in Object checks for reference equality (whether they point to the same
memory location), not content equality. Therefore, it will return false .

2. Default Behavior of toString()

By default, the toString() method in the Object class returns a string representation
of the object, which includes:

The class name.

The "@" symbol.

The hash code of the object (a unique identifier based on memory address).

Example without overriding toString() :

class Person {
String name;
int age;

Person(String name, int age) {


this.name = name;
this.age = age;

Object class 2
}
}

public class Main {


public static void main(String[] args) {
Person person = new Person("Alice", 25);
System.out.println(person.toString()); // Object's default toString() outpu
t
}
}

Output:

Person@15db9742

Here:

Person is the class name.

@15db9742 is the hash code of the object (in hexadecimal).

This is not a human-readable or useful string representation of the object, which


is why it's common to override toString() to provide more meaningful information
about the object (like its field values).

Overriding Methods in Object Class

1. equals(Object obj)

The equals method is used to compare two objects for equality.

By default, the equals method checks for reference equality (whether two
references point to the same object in memory). However, this is often
overridden in custom classes to compare object content (the values of
fields).

Example of equals method:

Object class 3
class Person {
String name;
int age;

Person(String name, int age) {


this.name = name;
this.age = age;
}

// Overriding equals() to compare content (name and age)


@Override
public boolean equals(Object obj) {
if (this == obj) return true; // Check if both are the same object
if (obj == null || getClass() != obj.getClass()) return false; // Check if
obj is not null and same class
Person person = (Person) obj;
return name.equals(person.name) && age == person.age; // Compar
e name and age
}
}

public class Main {


public static void main(String[] args) {
Person person1 = new Person("Alice", 25);
Person person2 = new Person("Alice", 25);
Person person3 = new Person("Bob", 30);

System.out.println(person1.equals(person2)); // true
System.out.println(person1.equals(person3)); // false
}
}

Output:

Object class 4
true
false

2. toString()

The toString method returns a string representation of an object. By


default, it returns the class name and the memory address of the object,
but it is commonly overridden to provide a more meaningful description of
the object’s state.

Example of toString method:

class Person {
String name;
int age;

Person(String name, int age) {


this.name = name;
this.age = age;
}

// Overriding toString() to return a custom string representation


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

public class Main {


public static void main(String[] args) {
Person person = new Person("Alice", 25);
System.out.println(person.toString()); // Person[name=Alice, age=2
5]
}
}

Object class 5
Output:

Person[name=Alice, age=25]

Object class 6
Inner Class
An inner class in Java is a class defined within another class. Inner classes are
associated with the instance of the outer class, meaning they can access all
members (including private ones) of the outer class.

Types of Inner Classes


There are four types of inner classes in Java:

1. Nested (Static) Class: A static inner class that belongs to the outer class and
can be accessed without an instance of the outer class.

2. Non-Static Inner Class (Regular Inner Class): A non-static class that is


associated with an instance of the outer class.

3. Local Inner Class: A class defined within a method or a block.

4. Anonymous Inner Class: A class that is declared and instantiated


simultaneously.

1. Nested (Static) Class


A static inner class is defined with the static keyword. It can be accessed without
creating an instance of the outer class.

public class Outer {


static class Nested {
void display() {
System.out.println("This is a static nested class.");
}
}

public static void main(String[] args) {


Outer.Nested nested = new Outer.Nested();
nested.display();

Inner Class 1
}
}

Output:

This is a static nested class.

2. Non-Static Inner Class (Regular Inner Class)


A non-static inner class requires an instance of the outer class to be instantiated.
It can access all members of the outer class.

public class Outer {


private String message = "Hello from Outer!";

class Inner {
void display() {
System.out.println(message);
}
}

public static void main(String[] args) {


Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display();
}
}

Output:

Hello from Outer!

3. Local Inner Class

Inner Class 2
A local inner class is defined inside a method or a block. It is local to the scope in
which it is defined and cannot be accessed outside that scope.

public class Outer {


void displayMessage() {
class LocalInner {
void show() {
System.out.println("This is a local inner class.");
}
}

LocalInner localInner = new LocalInner();


localInner.show();
}

public static void main(String[] args) {


Outer outer = new Outer();
outer.displayMessage();
}
}

Output:

This is a local inner class.

4. Anonymous Inner Class

An anonymous inner class is a one-time use class without a name. It is commonly


used when implementing interfaces or extending a class.

public class Main {


interface Greeting {
void sayHello();
}

Inner Class 3
public static void main(String[] args) {
Greeting greet = new Greeting() {
@Override
public void sayHello() {
System.out.println("Hello from Anonymous Inner Class!");
}
};

greet.sayHello();
}
}

Output:

Hello from Anonymous Inner Class!

Example: Extending a Class

public class Outer {


void display() {
System.out.println("This is Outer class.");
}

public static void main(String[] args) {


Outer outer = new Outer() {
@Override
void display() {
System.out.println("This is Anonymous Inner Class extending Oute
r.");
}
};

outer.display();

Inner Class 4
}
}

Output:

This is Anonymous Inner Class extending Outer.

Inner Class 5
Wrapper Class
In Java, wrapper classes are used to convert primitive data types (like int , double ,
char , etc.) into corresponding objects. Each primitive type has a corresponding

wrapper class in the java.lang package.

Primitive Type Wrapper Class


byte Byte

short Short

int Integer

long Long

float Float

double Double

char Character

boolean Boolean

Why Use Wrapper Classes?

1. Object-Oriented Context: Many data structures in Java (like ArrayList ) work


with objects, not primitives.

2. Utility Methods: Wrapper classes provide useful methods (e.g., parsing


strings into numbers).

3. Autoboxing and Unboxing: Automatic conversion between primitives and


wrapper objects makes coding easier.

4. Collections Framework: Wrapper classes allow primitives to be stored in


collections like ArrayList .

Autoboxing and Unboxing

Autoboxing: Automatically converting a primitive type into its corresponding


wrapper class.

Wrapper Class 1
Unboxing: Automatically converting a wrapper class object into its
corresponding primitive type.

public class Main {


public static void main(String[] args) {
// Autoboxing: Primitive to Wrapper
int a = 10;
Integer wrapperA = a; // Automatically boxed

// Unboxing: Wrapper to Primitive


Integer wrapperB = new Integer(20);
int b = wrapperB; // Automatically unboxed

System.out.println("Autoboxed: " + wrapperA);


System.out.println("Unboxed: " + b);
}
}

Output:

Autoboxed: 10
Unboxed: 20

Methods in Wrapper Classes

Wrapper classes provide various utility methods:

1. Parsing Strings to Primitives

Convert a string to a number or boolean.

int num = Integer.parseInt("123");


double decimal = Double.parseDouble("45.67");
boolean bool = Boolean.parseBoolean("true");

2. Converting Primitives to Strings

Wrapper Class 2
Convert numbers or booleans to strings.

String strNum = Integer.toString(456);


String strBool = Boolean.toString(true);

3. Value Methods

Get the primitive value from a wrapper object.

Integer obj = Integer.valueOf(100);


int val = obj.intValue(); // Returns 100

4. Comparing Values

Compare wrapper objects.

Integer a = 5, b = 10;
System.out.println(a.compareTo(b)); // Output: -1 (a < b)

Wrapper Class Method Description


Integer parseInt(String) Converts a string to an int .
Integer valueOf(String) Converts a string to an Integer object.
Integer toString(int) Converts an int to a string.
Double parseDouble(String) Converts a string to a double .
Boolean parseBoolean(String) Converts a string to a boolean .
Character isDigit(char) Checks if a character is a digit.
Character isLetter(char) Checks if a character is a letter.

Performance Considerations

Memory Usage: Wrapper objects consume more memory than primitive types
because they store additional metadata.

Wrapper Class 3
Boxing/Unboxing Overhead: Frequent boxing/unboxing can impact
performance. For performance-critical applications, prefer primitives.

When to Use Wrapper Classes

1. When working with Collections Framework (e.g., ArrayList , HashMap ).

2. When you need to use utility methods provided by wrapper classes.

3. When you need to pass data as objects (e.g., for serialization).

Wrapper Class 4
Enums
In Java, an enum (short for "enumeration") is a special data type that represents a
fixed set of constants. It is used when you know all possible values for a variable
at compile time. Enums are type-safe, which means they ensure the variable can
only hold one of the predefined constant values.

Why Use Enums?

1. Readability: Makes the code more readable compared to using plain


constants.

2. Type Safety: Prevents invalid values from being assigned.

3. Predefined Methods: Provides useful methods like name() , ordinal() , and values() .

4. Organized Code: Groups related constants together.

Declaring an Enum

An enum is defined using the enum keyword.

enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUND
AY
}

public class Main {


public static void main(String[] args) {
Day today = Day.SATURDAY;

if (today == Day.SATURDAY || today == Day.SUNDAY) {


System.out.println("It's the weekend!");
} else {
System.out.println("It's a weekday.");
}

Enums 1
}
}

Output:

It's the weekend!

Enum Features
1. Iterating Over Enum Constants

You can use the values() method to loop through all enum constants.

enum Color {
RED, GREEN, BLUE
}

public class Main {


public static void main(String[] args) {
for (Color c : Color.values()) {
System.out.println(c);
}
}
}

Output:

RED
GREEN
BLUE

2. Using ordinal() and name()

ordinal() : Returns the position of the constant (starting from 0).

name() : Returns the name of the constant as a String .

Enums 2
enum Season {
SPRING, SUMMER, FALL, WINTER
}

public class Main {


public static void main(String[] args) {
Season s = Season.SUMMER;

System.out.println("Name: " + s.name()); // Output: SUMMER


System.out.println("Ordinal: " + s.ordinal()); // Output: 1
}
}

3. Adding Fields and Methods


Enums can have fields, constructors, and methods.

enum Planet {
MERCURY(3.30e23, 2.44e6),
EARTH(5.97e24, 6.37e6),
JUPITER(1.90e27, 6.99e7);

private final double mass; // in kilograms


private final double radius; // in meters

Planet(double mass, double radius) {


this.mass = mass;
this.radius = radius;
}

public double surfaceGravity() {


double G = 6.67300E-11;
return G * mass / (radius * radius);
}
}

Enums 3
public class Main {
public static void main(String[] args) {
for (Planet p : Planet.values()) {
System.out.printf("%s: Surface Gravity = %.2f m/s^2%n",
p, p.surfaceGravity());
}
}
}

Output:

MERCURY: Surface Gravity = 3.70 m/s^2


EARTH: Surface Gravity = 9.81 m/s^2
JUPITER: Surface Gravity = 24.79 m/s^2

Important Questions

1. What is the difference between a class and an enum?

Feature Class Enum

Used to create objects and define Used to represent a fixed set of


Purpose
behaviors. constant values.

Can be instantiated using the Cannot be instantiated (implicitly


Instantiation
new keyword. final ).

Type-safe; only predefined


Type-Safety No restriction on values of fields.
constants allowed.

Cannot extend a class (implicitly


Inheritance Can extend another class.
extends java.lang.Enum ).

Can have methods, fields, and


Methods/Fields Can have any methods or fields. constructors but is designed
primarily for constants.

Representing predefined, fixed


Use Case General-purpose programming.
values (e.g., days, colors).

Enums 4
2. Can enums extend classes or implement interfaces?

Enums cannot extend classes because they already extend java.lang.Enum .

Enums can implement interfaces, which allows them to inherit behavior from
the interface.

interface Printable {
void print();
}

enum Level implements Printable {


LOW, MEDIUM, HIGH;

@Override
public void print() {
System.out.println(this + " level");
}
}

public class Main {


public static void main(String[] args) {
Level.HIGH.print(); // Output: HIGH level
}
}

3. Can you create an enum inside a class?

Yes, you can define an enum inside a class, either as a static or non-static
member.

public class Main {


enum Direction {
NORTH, SOUTH, EAST, WEST
}

public static void main(String[] args) {

Enums 5
Direction dir = Direction.NORTH;
System.out.println("Direction: " + dir); // Output: Direction: NORTH
}
}

4. Can enums have constructors?

Yes, enums can have constructors, but they are private or package-private by
default. They are used to initialize fields in the enum constants.

enum Color {
RED("Stop"), GREEN("Go"), YELLOW("Caution");

private String meaning;

Color(String meaning) {
this.meaning = meaning;
}

public String getMeaning() {


return meaning;
}
}

public class Main {


public static void main(String[] args) {
System.out.println(Color.RED.getMeaning()); // Output: Stop
}
}

5. Can an enum have an abstract method?

Yes, an enum can have abstract methods. Each constant must then provide an
implementation for the method.

Enums 6
enum Operation {
ADD {
@Override
public int apply(int a, int b) {
return a + b;
}
},
SUBTRACT {
@Override
public int apply(int a, int b) {
return a - b;
}
};

public abstract int apply(int a, int b);


}

public class Main {


public static void main(String[] args) {
System.out.println(Operation.ADD.apply(5, 3)); // Output: 8
System.out.println(Operation.SUBTRACT.apply(5, 3)); // Output: 2
}
}

6. Can enums have a main() method?

Yes, an enum can have a main() method like any other class.

enum Greeting {
HELLO, HI, HEY;

public static void main(String[] args) {


for (Greeting g : Greeting.values()) {
System.out.println(g);
}

Enums 7
}
}

7. What happens if two enum constants have the same value?

Enum constants are unique. If you try to define two constants with the same
name, the compiler will throw an error.

8. How are enums stored in memory?

Enums are implemented as a special type of class. Each enum constant is a static
and final instance of the enum. The constants are initialized when the enum class
is loaded.

Enums 8
Packages
In Java, packages are a way to organize and group related classes and interfaces.
They act like folders on your computer to keep your code neat and manageable.
Packages also help avoid name conflicts between classes.

Why Use Packages?

1. Organization: Group related classes together.

2. Avoid Name Conflicts: Different packages can have classes with the same
name.

3. Access Control: Define which classes can be accessed outside the package.

4. Reusability: Easily reuse classes from other projects.

Types of Packages

1. Built-in Packages: Provided by Java (e.g., java.util , java.io ).

2. User-defined Packages: Created by the programmer.

How to Use Packages

The folder structure for Java packages should match the package name. Each
part of the package name corresponds to a folder. Let's break it down with an
example.

Example Package Structure


Package Name: mypackage

The folder structure should look like this:

ProjectFolder
├── Main.java

Packages 1
└── mypackage
└── Calculator.java

Step 1: Create a Package


You create a package using the package keyword.
Example:

// Save this file as Calculator.java inside a folder named "mypackage"


package mypackage;

public class Calculator {


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

Step 2: Use the Package


To use the Calculator class from the mypackage package, you need to import it.
Example:

// Save this file as Main.java


import mypackage.Calculator; // Import the class

public class Main {


public static void main(String[] args) {
Calculator calc = new Calculator(); // Create an object
int sum = calc.add(5, 3); // Call the add method
System.out.println("Sum: " + sum); // Output: Sum: 8
}
}

Step 3: Compile and Run

1. Navigate to the folder containing mypackage and Main.java .

Packages 2
2. Compile the Calculator class:

javac mypackage/Calculator.java

3. Compile the Main class:

javac Main.java

4. Run the program:

java Main

Packages 3
Real life Examples

OOP concepts in a TV Remote


A TV remote is a great real-life example to explain Object-Oriented Programming
(OOP) concepts.

1. Class and Object


Class: TVRemote

Properties: brand , color , batteryLevel , powerButton

Behaviors: turnOn() , turnOff() , changeChannel() , adjustVolume()

Object:

myRemote (an instance of TVRemote ) with brand = "Sony" , color = "Black" , and
batteryLevel = 100 .

Explanation:

The TVRemote class defines what a remote is (its properties and behaviors).

The myRemote object is a specific remote with its own values for the properties.

2. Encapsulation
Class: TVRemote

Properties: batteryLevel (private), powerButton (private)

Behaviors: turnOn() , turnOff() , checkBatteryLevel()

Explanation:

The batteryLevel property is marked as private , so it cannot be accessed directly


from outside the class.

To check the battery level, you must use the public method checkBatteryLevel() .

Real life Examples 1


This ensures that the battery level is only accessed in a controlled way,
preventing unauthorized access or invalid operations.

3. Polymorphism
Method Overloading:

The TVRemote class has multiple adjustVolume() methods:

adjustVolume(int level) (sets volume to a specific level)

adjustVolume(boolean increase) (increases or decreases volume by 1)

The correct method is chosen based on the arguments passed.

Method Overriding:

A SmartTVRemote class (subclass of TVRemote ) overrides the turnOn() method to


provide its own implementation:

Explanation:

Overloading: The adjustVolume() method can handle different types of inputs.

Overriding: The SmartTVRemote class provides a specific way to turn on the TV,
different from the general TVRemote class.

4. Inheritance
Superclass: TVRemote

Properties: brand , color

Behaviors: turnOn() , turnOff()

Subclass: SmartTVRemote (inherits from TVRemote )

Additional Behaviors: connectToWiFi() , openApp()

Explanation:

The SmartTVRemote class inherits the properties and behaviors of the TVRemote

class and adds its own unique behaviors ( connectToWiFi() , openApp() ).

This represents an "is-a" relationship: A SmartTVRemote is a TVRemote .

Real life Examples 2


5. Abstract Class
Abstract Class: Remote

Abstract Method: controlDevice() (no implementation)

Concrete Method: powerOn() (prints "Device is powering on.")

Subclass: TVRemote (extends Remote )

Implements controlDevice() to control a TV.

Explanation:

The Remote class defines a common structure for all remotes but leaves the
implementation of controlDevice() to its subclasses.

The TVRemote class provides a specific implementation of controlDevice() .

6. Interfaces
Interface: PowerControl

Methods: turnOn() , turnOff()

Class: TVRemote (implements PowerControl )

Implements turnOn() and turnOff() for controlling the TV.

Explanation:

The PowerControl interface defines what a power-controllable device should do.

The TVRemote class implements the interface and provides specific


functionality for turning the TV on and off.

OOP Concepts in a Pen


A pen is a great real-life example to explain Object-Oriented Programming (OOP)
concepts in a simple and practical way.

Class and Object


Class: Pen

Real life Examples 3


Properties: brand , color , inkLevel , tipSize , penType

Behaviors: write() , refillInk() , changeTipSize()

Object:

myPen(an instance of Pen ) with brand = "Parker" , color = "Blue" , inkLevel = 80 , tipSize

= 0.5mm , penType = "Ballpoint"

Explanation:

The Pen class is like a blueprint that defines the common characteristics and
behaviors of all pens.

The myPen object is a specific pen with its own values for these properties.

Encapsulation (Data Hiding & Protection)


Class: Pen

Private Properties: inkLevel (cannot be accessed directly)

Public Methods: write() , checkInkLevel()

Explanation:

The inkLevel is private, meaning it cannot be modified directly from outside


the class.

The checkInkLevel() method allows controlled access to check the ink level.

This prevents unauthorized access or accidental modification.

Method Overloading (Compile-Time Polymorphism)


The write() method can take different types of arguments:

write() → Writes a default message.

write(String text) → Writes custom text.

write(String text, int fontSize) → Writes with a specified font size.

Explanation:

Real life Examples 4


The write() method behaves differently based on the number of parameters,
allowing flexibility.

Method Overriding (Run-Time Polymorphism)


A FountainPen writes differently from a BallpointPen , so we override the write()

method.

Explanation:

Overriding allows the FountainPen class to provide a customized writing


experience, different from a generic Pen .

Inheritance ("is-a" Relationship)


Superclass: Pen (common properties for all pens)

Subclasses: FountainPen , BallpointPen , GelPen

Explanation:

FountainPen "is-a" Pen, so it inherits properties like brand , color , and


behavior write() .

It adds its own unique behavior like refillInk() .

Abstract Class (Partial Implementation)


An abstract class Pen provides a general definition of a pen but leaves some
details undefined.

Explanation:

The Pen class cannot be instantiated because it has an abstract method


( write() ).

GelPen must provide an implementation for write() .

Interfaces (Complete Abstraction)


Interface: Writable (defines behaviors that every writable object must have)

Class: Pen implements Writable

Real life Examples 5


Explanation:

The Writable interface ensures that any erasable pen must provide methods for
write() and erase() .

This is useful when multiple classes must follow a common contract.

Real life examples of each concept

Class and Object – Blueprint and Instance

Class: A Car is a blueprint that defines common properties like brand , model ,
color , and behaviors like start() , stop() , and accelerate() .

Object: A specific car, like a red Tesla Model 3, is an instance of the Car

class.

In Real Life: The Car class is like a blueprint in a factory, while a specific car you
own is an object of that class.

Encapsulation – Data Hiding and Protection

Real-Life Example: ATM Machine


Encapsulation: In an ATM, your bank balance is hidden from direct access.
You interact via methods like withdrawMoney(amount) , but you cannot directly
modify balance .

balance → private variable.

getBalance() → method to know balance.

In Real Life: Encapsulation ensures that sensitive data (balance) is only modified
through defined methods and is not directly accessible.

Method Overloading (Compile-Time Polymorphism)

A coffee machine can make coffee with different ingredients:

makeCoffee() → Plain coffee

Real life Examples 6


makeCoffee(String type) → Different flavors (Espresso, Latte)

makeCoffee(String type, int sugarLevel) → With sugar customization

In Real Life: A coffee machine provides the same function ( makeCoffee() ), but with
different arguments (parameters).

Method Overriding (Run-Time Polymorphism)

In an e-commerce application, there is a common method processPayment() .

However, the actual payment process differs based on whether the user pays
with a credit card, net banking, UPI etc.

In Real Life:

The Payment class defines a generic processPayment() method.

CreditCardPayment and UPIPayment override it with their own implementation.

At runtime, Java determines which method to call based on the actual object
type.

Inheritance – "Is-a" Relationship

Inheritance allows a Car and a Bike to reuse common properties of a Vehicle

while adding their own specific features.

In Real Life: A Car "is-a" Vehicle, meaning it inherits all vehicle behaviors but can
also add new ones.

Abstract Class – Partial Implementation

An abstract class defines a general category ( Smartphone ), but the details


( iPhone vs. Samsung ) are implemented by subclasses.

In Real Life: Smartphone is abstract because it cannot exist alone—it needs a


specific brand (iPhone, Samsung).

Abstract Methods: makeCall() and runApp() are abstract methods in the


Smartphone class, so they don't have implementations. The subclasses iPhone

Real life Examples 7


and Samsung must implement these methods.

Concrete Methods: connectToWifi() is a concrete method in Smartphone , so both


iPhone and Samsung inherit this behavior without modification.

Interface – Complete Abstraction

A remote control defines a common interface for controlling different devices,


but each device implements its own specific logic for turning on, off, or
adjusting settings.

Explanation:

Interface RemoteControl : Defines common actions for controlling any remote-


controlled device: turnOn() , turnOff() , and adjustVolume() .

Classes Television and AirConditioner : Each class implements the RemoteControl


interface, but they provide their own specific behavior for the methods (e.g.,
turning on the TV vs. turning on the AC).

Real life Examples 8

You might also like