BEU B.Tech Java Unit-2 Notes 3rd Semester | Unit 2 – Classes & Objects (New Syllabus) 2026

Download BEU B.Tech Java notes for 3rd semester based on the new Bihar Engineering University syllabus. These handwritten-style notes cover Unit 2 topics like classes, objects, constructors, access specifiers, and String class for CSE and AI-ML students.

Updated on

Class in Java

A class in Java is a user-defined data type that acts as a blueprint for creating objects. It groups data (variables) and behavior (methods) into a single unit so that related information stays together. A class defines what properties an object will have and what actions it can perform, but it does not represent a real entity by itself. Memory for a class is allocated only when its objects are created, which makes classes reusable and efficient for building large programs.

Important points

  • A class is a logical entity, not a physical one

  • A class does not occupy memory until an object is created

  • Variables inside a class are called instance variables

  • Methods inside a class define the behavior of objects

  • A single class can be used to create many objects

  • Class members can be variables, methods, constructors, and blocks

  • Classes support data hiding and code reusability

  • A class name should start with a capital letter by convention

  • A Java program can contain multiple classes

  • One class may contain the main() method

Syntax

class ClassName {
    dataType variable1; // instance member variable
    dataType variable2; // instance member variable

    returnType methodName() {
        // method body
    }
}

Example of a Class

class Student {
    int rollNumber; // instance member variable
    String name;

    void showDetails() {  //method
        System.out.println("Roll Number: " + rollNumber);
        System.out.println("Name: " + name);
    }
}

In this example, Student is a class that defines two variables and one method, but no memory is used yet because no object has been created.

Object in Java

An object in Java is an instance of a class that represents a real-world entity and is used to access the variables and methods defined in that class.

It represents physical or logical things such as a student, car, or employee. An object contains state (data stored in variables) and behavior (actions defined by methods). When an object is created, memory is allocated in the heap memory for all instance variables of the class. Java programs mainly work by creating objects and accessing class members through them.

Important points

  • An object is an instance of a class

  • Objects occupy memory, classes do not

  • Memory for an object is allocated in heap memory

  • Each object has its own copy of instance variables

  • Multiple objects can be created from the same class

  • Objects are created using the new keyword

  • Object reference is used to access variables and methods

  • Objects communicate with each other using method calls

  • Without an object, non-static members cannot be accessed

  • Object lifetime is managed automatically by Java garbage collection

Syntax

ClassName objectName = new ClassName();

Explanation of syntax

  • ClassName → name of the class

  • objectName → reference variable

  • new → allocates memory and creates object

  • ClassName() → constructor call

Full Java Example Using Object

class Student {

    int rollNumber; //instance variables
    String name;

    void setData(int r, String n) {  //method
        rollNumber = r;
        name = n;
    }

    void displayData() {  //method
        System.out.println("Roll Number: " + rollNumber);
        System.out.println("Name: " + name);
    }

    public static void main(String[] args) {

        // object creation
        Student s1 = new Student();

        // accessing data using object
        s1.setData(101, "Amit");
        s1.displayData();
    }
}

Output

Roll Number: 101
Name: Amit

What happens internally (very important for exams)

  • JVM loads the Student class

  • new keyword allocates memory in heap

  • Constructor initializes the object

  • s1 stores the reference of the object

  • Methods are called using the object reference

New Keyword in Java (Object Creation & Memory Concept)

The new keyword in Java is used to create an object of a class by allocating memory in heap memory and returning a reference to that object.

Important points

  • new keyword is used to create objects in Java

  • It allocates memory dynamically at runtime

  • Memory is allocated in heap memory

  • new returns a reference to the created object

  • The reference is stored in a reference variable

  • Constructor of the class is automatically called

  • Without new, an object cannot be created

  • Each use of new creates a separate object

  • Objects created using new are managed by garbage collection

Syntax of Object Creation using new

ClassName objectName = new ClassName();

Memory Concept

When the new keyword is used:

  • Class is already loaded by JVM

  • new allocates memory in heap

  • Constructor initializes the object

  • Reference variable stores the memory address

  • Object can be accessed using the reference

Note:
Reference variable is stored in stack memory, while the actual object is stored in heap memory.

Full Java Example Demonstrating new Keyword

class Book {

    String title;
    int price;

    void setData(String t, int p) {
        title = t;
        price = p;
    }

    void display() {
        System.out.println("Book Name: " + title);
        System.out.println("Price: " + price);
    }

    public static void main(String[] args) {

        Book b1 = new Book();   // object created using new
        Book b2 = new Book();   // another object

        b1.setData("Java Basics", 300);
        b2.setData("Advancedjava Advance", 500);

        b1.display();
        b2.display();
    }
}

Output

Book Name: Java Basics
Price: 300
Book Name: Java Advance
Price: 500

Key understanding

  • b1 and b2 are two different objects

  • Both objects have separate memory

  • Changes in one object do not affect the other

Declaring, Defining, and Accessing Objects in Java

In Java, an object is used by first declaring a reference, then defining (creating) the object, and finally accessing its variables and methods using the dot operator.

Declaring an Object

Declaring an object means creating a reference variable of a class type. At this stage, no memory is allocated for the object.

Reference variable is stored in stack memory and it points to the object stored in heap memory, which contains instance variables and methods of the class.

Syntax

ClassName objectName;

Example

Student s1;

Important points

  • Only a reference variable is created

  • No object exists yet

  • No memory is allocated in heap

Defining an Object

Defining an object means allocating memory for the object using the new keyword. Now the object actually exists in memory.

Syntax

objectName = new ClassName();

Example

s1 = new Student();

Important points

  • Memory is allocated in heap

  • Constructor is called automatically

  • Object is ready to use

Declaring and Defining Together

Java also allows declaring and creating an object in a single statement.

Syntax

ClassName objectName = new ClassName();

Example

Student s1 = new Student();

Accessing Object Members (Dot Operator)

To access variables and methods of an object, Java uses the dot (.) operator. The dot operator is used to access instance variables and methods of a class through an object reference.

Syntax

objectName.variableName;
objectName.methodName();

Example

s1.rollNumber = 101;
s1.display();

Important points

  • Dot operator connects object with its members

  • Used for both variables and methods

  • Works only with objects (non-static members)

Full Java Example (Declaration → Creation → Access)

class Student {

    int rollNumber;
    String name;

    void display() {
        System.out.println(rollNumber);
        System.out.println(name);
    }

    public static void main(String[] args) {

        Student s1;              // declaration
        s1 = new Student();      // object creation

        s1.rollNumber = 101;     // accessing variable
        s1.name = "Amit";

        s1.display();            // accessing method
    }
}

Output

101
Amit

Exam Memory Tip

  • Declaration → no memory

  • new → heap memory allocation

  • Dot operator → access members

Dot (.) operator uses reference → reaches object → accesses members

  • Reference variable → stored in stack

  • Object → stored in heap

  • new → allocates heap memory

  • Reference variable → does not contain object

  • Multiple references can point to different objects

  • If reference becomes null, object becomes unreachable

  • Unreachable objects are removed by garbage collection

Static Keyword

The static keyword in Java is used to define variables and methods that belong to the class itself instead of belonging to individual objects. Static members are created only once and are shared by all objects of the class.

Important concepts

  • Static members belong to the class, not to objects
    This means a static variable or static method is associated with the class name. It is not tied to any specific object. Even if no object is created, static members can still be used.

  • Memory for static members is created at class loading time
    When the JVM loads a class into memory, it immediately allocates memory for all static variables and static methods. This happens before the main() method starts executing.

  • Static members exist before object creation
    Since memory is already created at class loading time, static members are available even when no object of the class exists.

  • Only one copy of static variable is created
    No matter how many objects you create from a class, there will still be only one shared static variable in memory.

  • Static members are shared by all objects
    If one object changes the value of a static variable, that updated value is seen by all other objects of the same class.

  • Static members are stored in class-level memory (method area)
    Static data is stored in the class area of memory, while objects are stored separately in heap memory.

  • Static methods can be accessed without creating an object
    Because static methods belong to the class, they can be called using the class name directly.

  • Static methods cannot directly access non-static members
    Non-static variables belong to objects, but static methods do not know which object’s data to use, so direct access is not allowed.

  • main() method is static for JVM execution
    The JVM calls the main() method without creating an object, which is why main() must be static.

Syntax

Static variable

static dataType variableName;

Static method

static returnType methodName() {
    // code
}

Accessing static members

We can access the static members (variables and methods) of a class without creating an object of that class. Static members belong to the class, so they are usually accessed using the class name. Static members can also be accessed using an object of the class, but it is not recommended.

ClassName.staticVariable;
ClassName.staticMethod();

Accessing static members using an object is allowed, but it is not recommended because it creates confusion.

Example: Accessing static members without creating object

class Demo {

    // static variable
    static int number = 10;

    // static method
    static void show() {
        System.out.println("Static method called");
    }

    public static void main(String[] args) {

        // accessing static variable using class name
        System.out.println(Demo.number);

        // accessing static method using class name
        Demo.show();
    }
}

Explanation

  • number is a static variable

  • show() is a static method

  • No object is created

  • Static members are accessed using the class name

Output

10
Static method called

Static Variables

Static variables are variables that belong to the class, not to individual objects. Only one copy of a static variable is created, and this copy is shared by all objects of the class. The memory for static variables is created when the class is loaded into memory.

Because static variables are shared, if one object changes the value of a static variable, the updated value is visible to all other objects of the same class.

Example

class Example {
    static int counter = 0;
}

Here, counter is created only once and shared by all objects of Example.

Static Methods

Static methods are methods that belong to the class, not to objects. They can be called without creating an object of the class. Static methods can directly access only static variables and static methods, because non-static members belong to objects.

Static methods are commonly used for utility work where object data is not required.

Example

class Example {
    static void display() {
        System.out.println("Static method called");
    }
}

Here, display() can be called using Example.display() without creating any object.

Static Blocks

Static blocks are used to initialize static data of a class. The code written inside a static block is executed only once, at the time when the class is loaded into memory by the JVM.

Static blocks are executed before the main() method.

Example

class Example {
    static {
        System.out.println("Static block executed");
    }
}

This message will be printed as soon as the class is loaded.

Static Nested Classes

A static nested class is a class defined inside another class using the static keyword. A static nested class does not need an object of the outer class to be created.

Static nested classes can access only static members of the outer class directly.

Syntax

class OuterClass {
    static class NestedStaticClass {
    }
}

Object Creation Rule

OuterClass.NestedStaticClass obj =
        new OuterClass.NestedStaticClass();
  • Object created → NestedStaticClass

  • Object NOT created → OuterClas

Access Rule

What static nested class CAN access directly

  • Static variables of outer class

  • Static methods of outer class

What static nested class CANNOT access directly

  • Non-static variables of outer class

  • Non-static methods of outer class

Access Rule Example

class Outer {
    int a = 10;
    static int b = 20;

    static class Inner {
        void show() {
            // System.out.println(a); ❌ not allowed
            System.out.println(b);   // ✅ allowed
        }
    }
}
Reason
  • Non-static members need an object

  • Static nested class has no outer object reference

Accessing Non-Static Members

class Outer {
    int a = 10;

    static class Inner {
        void show() {
            Outer obj = new Outer();
            System.out.println(obj.a); // ✅ allowed
        }
    }
}

Example

class OuterClass {
    static class NestedStaticClass {
        void display() {
            System.out.println("Static nested class method called");
        }
    }
}

Here, NestedStaticClass can be created without creating an object of OuterClass.

Example 1: Static Variable and Static Method

public class StaticExample {

    static int counter = 0;

    static void incrementCounter() {
        counter++;
    }

    public static void main(String[] args) {
        StaticExample.incrementCounter();
        System.out.println("Counter: " + StaticExample.counter);
    }
}

Output

Counter: 1

Explanation:
The static variable counter is shared, and the static method updates it without creating any object.

Example 2: Static Block

public class StaticBlockExample {

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

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

Output

Static block executed
Main method executed

Explanation:
The static block runs first when the class is loaded, then the main() method runs.

Example 3: Static Nested Class

public class OuterClassExample {

    static class NestedStaticClass {
        void display() {
            System.out.println("Static nested class method called");
        }
    }

    public static void main(String[] args) {
        OuterClassExample.NestedStaticClass obj =
            new OuterClassExample.NestedStaticClass();

        obj.display();
    }
}

Output

Static nested class method called

Explanation:
The static nested class is created and used without creating an object of the outer class.

  • Static variables → shared class data

  • Static methods → called without object

  • Static blocks → run once at class loading

  • Static nested classes → independent of outer object

Static Nested Class Can Have

  1. Static variables

  2. Non-static variables

  3. Static methods

  4. Non-static methods

  5. Constructors

  6. Any access modifier (private, protected, public)

Static Nested Class Cannot

  1. Access outer non-static members directly

  2. Use Outer.this

  3. Automatically access outer object data

Key Characteristics

  • Class-Level Association: static members are loaded into memory with the class during runtime, existing only once regardless of how many objects (instances) of that class are created.

  • Instance Independence: You can access static members directly using the class name, without needing to instantiate an object of the class first.

  • Memory Management: Using static fields can be more memory efficient as the value is shared, not duplicated for every object. 

Uses of static Keyword in Java

  • To share common data among all objects
    Static variables are used when a value is the same for all objects of a class. Instead of creating a separate copy for each object, a single shared copy is used, which saves memory.

  • To access members without creating an object
    Static variables and methods can be used directly with the class name. This is useful when we do not want to create an object just to use a method or variable.

  • To reduce memory usage
    Since static variables are created only once at class loading time, they help reduce memory consumption compared to non-static variables that are created for every object.

  • To define utility or helper methods
    Methods that perform common tasks and do not depend on object data are made static. Examples include mathematical calculations or helper functions.

  • To allow JVM to call the main() method
    The main() method is static so that the JVM can start program execution without creating any object of the class.

  • To maintain a single value across the program
    Static variables are used when a value must remain consistent throughout the program, such as counters, configuration values, or constants (with static final).

Methods in Java

A method in Java is a block of code written inside a class that performs a specific task and is executed only when it is called.

Important points

  • A method must always be defined inside a class and cannot be written outside a class.

  • A method contains the logic or instructions needed to perform a task in a program.

  • A method runs only when it is called; defining a method alone does not execute it.

  • A method can be called multiple times, which avoids writing the same code again and again.

  • A method can take input values called parameters, which allow it to work with different data.

  • A method may return a value using the return statement, or it may return nothing using void.

  • Methods make programs easier to read, understand, test, and maintain.

  • Methods help in breaking a large program into smaller and manageable parts.

Syntax of Defining a Method

returnType methodName(parameterList) {
    // method body
}

Calling a Method

  • A non-static method is called using an object of the class.

  • A static method is called using the class name and does not need an object.

Method with No Parameters and No Return Value

class Demo {

    // method definition
    void showMessage() {
        System.out.println("Hello from method");
    }

    public static void main(String[] args) {

        // creating object of class
        Demo d = new Demo();

        // calling the method using object
        d.showMessage();
    }
}

Output

Hello from method

Explanation

  • showMessage() is a method defined inside the class

  • void means the method does not return any value

  • The method is called using object d

  • When the method is called, its code is executed

Method with Parameters

class Demo {

    // method with parameters
    void add(int a, int b) {
        System.out.println(a + b);
    }

    public static void main(String[] args) {

        // object creation
        Demo d = new Demo();

        // passing values to the method
        d.add(10, 20);
    }
}

Output

30

Explanation

  • a and b receive values 10 and 20

  • The method adds the values and prints the result

  • Parameters allow the method to work with different values

Method with Return Value

class Demo {

    // method that returns a value
    int square(int x) {
        return x * x;   // returning result
    }

    public static void main(String[] args) {

        Demo d = new Demo();

        // calling method and storing returned value
        int result = d.square(5);

        System.out.println(result);
    }
}

Output

25

Explanation

  • The method returns an integer value

  • return sends the value back to the caller

  • The returned value is stored in result

Static Method

  • A static method belongs to the class, not to objects.

  • A static method is called using the class name.

  • A static method cannot directly access non-static variables or methods.

class Demo {

    // static method
    static void greet() {
        System.out.println("Welcome");
    }

    public static void main(String[] args) {

        // calling static method using class name
        Demo.greet();
    }
}

Output

Welcome

Explanation

  • Static methods belong to the class

  • No object is needed to call a static method

  • Static methods are called using the class name

Access Specifiers with Methods

  • Methods can be declared as public, private, protected, or default.

  • Access specifiers control from where a method can be called.

class Demo {

    public void show() {
        System.out.println("Public method");
    }

    public static void main(String[] args) {
        Demo d = new Demo();
        d.show();
    }
}

main() Method

  • main() is the starting point of program execution.

  • main() is static so that JVM can call it without creating an object.

  • The signature of main() must be correct, otherwise the program will not run.

public static void main(String[] args)

Passing Object as Parameter in Java

Passing an object as a parameter in Java means sending the reference of an object to a method, so that the method can access and modify the data of that object.

Important points

  • When an object is passed to a method, its reference is passed, not a copy of the object.

  • The method receives access to the same object in memory.

  • Any change made to the object inside the method affects the original object.

  • Object passing allows methods to work with multiple values together.

  • Passing objects helps reduce the number of parameters in a method.

Syntax: Passing Object to Method

returnType methodName(ClassName objectReference) {
    // use objectReference
}

Example: Passing Object to Method

class Student {

    int roll;
    String name;

    // method that accepts object as parameter
    void showData(Student s) {
        System.out.println(s.roll);
        System.out.println(s.name);
    }

    public static void main(String[] args) {

        // creating object of Student
        Student s1 = new Student();

        // assigning values
        s1.roll = 101;
        s1.name = "Amit";

        // calling method and passing object
        s1.showData(s1);
    }
}

Output

101
Amit

Explanation

  • s1 is an object created in main()

  • The method showData() receives the object reference s

  • s and s1 both refer to the same object in memory

  • The method accesses the object data using s.roll and s.name

Example: Modifying Object Inside Method

class Student {

    int marks;

    // method modifies object data
    void updateMarks(Student s) {
        s.marks = 90;
    }

    public static void main(String[] args) {

        Student s1 = new Student();
        s1.marks = 50;

        // passing object to method
        s1.updateMarks(s1);

        // value changed after method call
        System.out.println(s1.marks);
    }
}

Output

90

Explanation

  • Object reference is passed to the method

  • The method changes the value of marks

  • Since both references point to the same object, the change is reflected in main()

Key Exam Understanding

  • Java uses call by value, but for objects the value is the reference

  • Methods can change object data through the reference

  • No new object is created when passing an object

Returning Object from Method in Java

Returning an object from a method in Java means the method sends an object reference back to the caller, so the caller can use that object outside the method.

Important points

  • A method can return an object just like it returns an int or string.

  • When an object is returned, its reference is returned, not a new copy.

  • The returned object can be stored in a reference variable.

  • Returning objects helps in sharing data between methods.

  • The returned object refers to the same memory location created inside the method.

Syntax: Returning Object from Method

ClassName methodName() {
    return objectReference;
}

Example: Returning Object from Method

class Student {

    int roll;
    String name;

    // method that returns an object
    Student createStudent() {

        // creating object inside method
        Student s = new Student();

        // assigning values
        s.roll = 101;
        s.name = "Amit";

        // returning object
        return s;
    }

    public static void main(String[] args) {

        Student obj = new Student();

        // receiving returned object
        Student s1 = obj.createStudent();

        // accessing data of returned object
        System.out.println(s1.roll);
        System.out.println(s1.name);
    }
}

Output

101
Amit

Explanation

  • The method createStudent() creates an object of Student.

  • The object reference is returned using return s.

  • In main(), the returned object is stored in s1.

  • s1 now points to the object created inside the method.

Example: Returning Object After Modification

class Box {

    int length;

    // method modifies and returns object
    Box update(Box b) {
        b.length = 20;
        return b;
    }

    public static void main(String[] args) {

        Box b1 = new Box();
        b1.length = 10;

        Box b2 = new Box();

        // receiving returned object
        b2 = b2.update(b1);

        System.out.println(b2.length);
    }
}

Output

20

Explanation

  • Object b1 is passed to the method.

  • The method modifies the object and returns it.

  • b2 stores the reference of the same object.

Exam Key Understanding

  • Methods can return object references.

  • Returned objects do not create extra memory copies.

  • Returned objects can be used like normal objects.

Access modifiers in Java

Access modifiers in Java are keywords that set the accessibility (scope or visibility) of a class, constructor, field, or method.They decide from where a member of a class can be accessed, such as within the same class, same package, subclass, or from anywhere.

Why access specifiers are needed

  • They help in data hiding so that important data is protected

  • They control who can use what in a program

  • They improve security of the program

  • They support proper object-oriented design

Types of Access Modifiers in Java

Java provides four types of access modifiers:

  • public

  • private

  • protected

  • default (no keyword used)

public Access Modifier

The public access modifier allows a class member (variable, method, or constructor) to be accessed from anywhere in the program.

Important points

  • A public member can be accessed inside the same class.

  • A public member can be accessed from another class in the same package.

  • A public member can be accessed from a class in a different package.

  • There is no restriction on accessing public members.

  • Public access is used when data or methods need to be available everywhere.

Syntax

public dataType variableName;
public returnType methodName() {
}

Example: public variable and public method

class Demo {

    // public variable
    public int number = 10;

    // public method
    public void show() {
        System.out.println(number);
    }

    public static void main(String[] args) {

        // creating object of class
        Demo d = new Demo();

        // accessing public variable
        System.out.println(d.number);

        // calling public method
        d.show();
    }
}

Output

10
10

Explanation

  • The variable number is declared as public, so it can be accessed anywhere.

  • The method show() is also public and can be called using an object.

  • The object d accesses both the public variable and public method without any restriction.

private Access Modifier

The private access modifier allows a class member (variable or method) to be accessed only inside the same class in which it is declared.

Important points

  • A private member can be accessed only within the same class.

  • A private member cannot be accessed from another class.

  • A private member cannot be accessed from the same package outside the class.

  • A private member cannot be accessed by subclasses.

  • Private access is mainly used for data hiding and security.

  • Private variables are usually accessed using public methods (getter/setter).

Syntax

private dataType variableName;
private returnType methodName() {
}

Example: private variable and private method

class Demo {

    // private variable
    private int number = 10;

    // private method
    private void show() {
        System.out.println(number);
    }

    public static void main(String[] args) {

        // creating object of class
        Demo d = new Demo();

        // calling private method inside same class
        d.show();
    }
}

Output

10

Explanation

  • The variable number is private, so it cannot be accessed outside this class.

  • The method show() is also private and can be called only inside the same class.

  • Since main() is inside the same class, accessing the private method is allowed.

  • If we try to access number or show() from another class, it will cause a compile-time error.

default Access Modifier

The default access modifier is used when no access keyword is written. A default member can be accessed only within the same package.

or

If no access modifier is specified, the member or class has default access. This means it is accessible by any other class within the same package but cannot be accessed from outside that package.Important points

  • Default access is applied when no access modifier is specified.

  • Default members can be accessed inside the same class.

  • Default members can be accessed by other classes in the same package.

  • Default members cannot be accessed from outside the package.

  • Default access is also called package-private access.

  • Default access helps in sharing data within a package only.

Syntax

dataType variableName;
returnType methodName() {
}

Example: default variable and default method

class Demo {

    // default access variable
    int number = 20;

    // default access method
    void show() {
        System.out.println(number);
    }

    public static void main(String[] args) {

        // creating object of class
        Demo d = new Demo();

        // accessing default variable
        System.out.println(d.number);

        // calling default method
        d.show();
    }
}

Output

20
20

Explanation

  • No access modifier is written before number and show(), so they have default access.

  • The variable and method are accessible inside the same class.

  • They are also accessible to other classes in the same package.

  • They cannot be accessed from a class in a different package.

protected Access Modifier

The protected access modifier allows a class member (variable or method) to be accessed within the same package and also in subclasses outside the package.

Important points

  • A protected member can be accessed inside the same class.

  • A protected member can be accessed by other classes in the same package.

  • A protected member can be accessed by a subclass in a different package.

  • A protected member cannot be accessed by a non-subclass outside the package.

  • Protected access is mainly used in inheritance.

  • It provides more access than private but less access than public.

Syntax

protected dataType variableName;
protected returnType methodName() {
}

Example: protected variable and method with inheritance

class Parent {

    // protected variable
    protected int number = 30;

    // protected method
    protected void show() {
        System.out.println(number);
    }
}

class Child extends Parent {

    public static void main(String[] args) {

        // creating object of child class
        Child c = new Child();

        // accessing protected member through inheritance
        c.show();
    }
}

Output

30

Explanation

  • The variable number and method show() are declared as protected.

  • The class Child extends Parent, so it becomes a subclass.

  • The subclass can access protected members of the parent class.

  • This access is possible even if the subclass is in a different package.

Very important exam note

  • protected members are not accessible outside the package without inheritance.

  • protected is mainly used when data should be shared with child classes.

Accessibility Summary

The following table summarizes the accessibility of each modifier: 

Modifier 

Within Class

Within Package

Within Subclass (different package)

Globally (different package & non-subclass)

private

Yes

No

No

No

default

Yes

Yes

No

No

protected

Yes

Yes

Yes

No

public

Yes

Yes

Yes

Yes

Array of Objects in Java

An array of objects in Java is an array that stores references of objects of a class, instead of storing primitive values like int or char.

Important points

  • An array of objects stores object references, not actual objects.

  • Each element of the array refers to an object of the same class.

  • Memory for the array is created first, then memory for each object is created separately.

  • Objects inside the array must be created using the new keyword.

  • Array of objects is useful when we need to store multiple objects of the same type.

Syntax

ClassName[] arrayName = new ClassName[size];

After this, each object is created separately:

arrayName[index] = new ClassName();

Example: Array of Objects

class Student {

    int roll;
    String name;

    void show() {
        System.out.println(roll + " " + name);
    }

    public static void main(String[] args) {

        // creating array to store 3 Student objects
        Student[] arr = new Student[3];

        // creating objects inside the array
        arr[0] = new Student();
        arr[1] = new Student();
        arr[2] = new Student();

        // assigning values to objects
        arr[0].roll = 101;
        arr[0].name = "Amit";

        arr[1].roll = 102;
        arr[1].name = "Ravi";

        arr[2].roll = 103;
        arr[2].name = "Neha";

        // accessing objects using loop
        for (int i = 0; i < 3; i++) {
            arr[i].show();
        }
    }
}

Output

101 Amit
102 Ravi
103 Neha

Explanation

  • Student[] arr creates an array that can store Student object references.

  • new Student[3] creates space for 3 references, not objects.

  • Each object is created separately using new Student().

  • The dot operator is used to access object members inside the array.

  • The loop is used to access all objects one by one.

Declaring an Array of Objects

Declaring an array of objects means creating a reference for an array that can hold object references, but no memory is allocated yet.

Syntax

ClassName[] arrayName;

Example

Student[] arr;

At this stage:

  • Only the array reference is created

  • No array memory

  • No objects

Initializing an Array of Objects

Initializing an array of objects means allocating memory for the array that stores object references. At this stage, objects are not created, only reference slots are created.

Syntax

arrayName = new ClassName[size];

Example

arr = new Student[3];

At this stage:

  • Memory for 3 references is created

  • Each element contains null

  • No Student object exists yet

Defining (Creating) Objects inside the Array

Defining an object means creating the actual object in heap memory using the new keyword and storing its reference in the array.

Syntax

arrayName[index] = new ClassName();

Example

arr[0] = new Student();
arr[1] = new Student();
arr[2] = new Student();

At this stage:

  • Actual objects are created in heap

  • Array elements point to these objects

Declaring, Initializing, and Defining Together

Syntax

ClassName[] arrayName = new ClassName[size];
arrayName[index] = new ClassName();

Example

Student[] arr = new Student[2];
arr[0] = new Student();
arr[1] = new Student();

Complete Example

class Student {

    int roll;
    String name;

    void show() {
        System.out.println(roll + " " + name);
    }

    public static void main(String[] args) {

        // declaring and initializing array
        Student[] arr = new Student[2];

        // defining objects inside array
        arr[0] = new Student();
        arr[1] = new Student();

        // assigning values
        arr[0].roll = 101;
        arr[0].name = "Amit";

        arr[1].roll = 102;
        arr[1].name = "Ravi";

        // accessing objects
        arr[0].show();
        arr[1].show();
    }
}

Output

101 Amit
102 Ravi

summary

  • Declaration → creates array reference

  • Initialization → creates reference array

  • Definition → creates actual objects

  • Array → stores references no actual objects

  • Objects → stored in heap separately

  • arr[i] → points to an object

  • arr[i].variable → accesses object data

Constructors in Java

A constructor in Java is a special method of a class that is used to initialize objects. It is automatically called when an object of the class is created. The constructor has the same name as the class and does not have any return type.

  • A constructor is used to initialize the data members of a class.

  • The name of the constructor must be the same as the class name.

  • A constructor does not have any return type, not even void.

  • A constructor is automatically called when an object is created using the new keyword.

  • Constructors help in setting initial values of objects.

  • Every class has at least one constructor, either defined by the programmer or provided by Java.

Syntax

ClassName() {
    // constructor body
}

Key Characteristics

  • Same Name as Class: A constructor's name must exactly match the name of the class in which it is defined.

  • No Return Type: Constructors do not have a return type, not even void.

  • Automatic Invocation: They are called implicitly (automatically) when an object is instantiated using the new keyword.

  • No Inheritance: Constructors are not inherited by subclasses, though a subclass constructor can call a superclass constructor using the super keyword.

  • Access Modifiers: Constructors can use any access modifier (public, protected, private, or default), which controls where objects of the class can be instantiated. 

Types of Constructors in Java

Java has the following types of constructors:

  1. Default constructor

  2. Parameterized constructor

1. Default Constructor

A default constructor is a constructor that does not take any parameters. It is used to initialize an object with default values when the object is created. If a programmer does not write any constructor in a class, Java automatically provides a default constructor.

  • A default constructor has no parameters.

  • It has the same name as the class.

  • It does not have any return type.

  • It is called automatically when an object is created.

  • Java provides a default constructor only when no constructor is written by the programmer.

  • If any constructor is defined in a class, Java does not provide the default constructor automatically.

  • This constructor initializes instance variables with their default values (e.g., 0 for int, null for objects, false for boolean).

Syntax

ClassName() {
    // initialization code
}

Example of Default Constructor

class Student {

    int roll;
    String name;

    // default constructor
    Student() {
        // initializing variables
        roll = 0;
        name = "Not Assigned";
    }

    public static void main(String[] args) {

        // creating object of Student class
        Student s1 = new Student();

        // printing values initialized by constructor
        System.out.println(s1.roll);
        System.out.println(s1.name);
    }
}

Output

0
Not Assigned

Code Flow Explanation

First, the program starts execution from the main() method.
Then, the statement new Student() creates an object of the Student class.
At the time of object creation, the default constructor Student() is called automatically.
Inside the constructor, the variables roll and name are initialized.
Finally, the values of these variables are printed in the main() method.

2. Parameterized Constructor

A parameterized constructor is a constructor that takes parameters. It is used to initialize an object with user-defined values at the time of object creation.This constructor accepts one or more parameters. It allows you to initialize the object's attributes with specific, custom values provided at the time of object creation, ensuring the object starts with a user-defined state. 

  • It is a constructor that accepts parameters

  • It is used to initialize instance variables with given values

  • It is called automatically when an object is created

  • It has the same name as the class

  • It does not have a return type, not even void

  • Different objects can have different values using the same constructor

  • It helps in setting required data at object creation time

  • If a parameterized constructor is defined, Java does not provide a default constructor automatically

Syntax

ClassName(dataType parameter1, dataType parameter2) {
    // initialization code
}

Example

class Student {

    int roll;
    String name;

    // parameterized constructor
    Student(int r, String n) {
        // assigning values received from object creation
        roll = r;
        name = n;
    }

    public static void main(String[] args) {

        // creating objects and passing values
        Student s1 = new Student(101, "Amit");
        Student s2 = new Student(102, "Ravi");

        // printing values
        System.out.println(s1.roll + " " + s1.name);
        System.out.println(s2.roll + " " + s2.name);
    }
}

Output

101 Amit
102 Ravi

Code Flow Explanation

The program starts execution from the main() method.
When new Student(101, "Amit") is executed, memory is allocated for the object.
The parameterized constructor is automatically called with values 101 and "Amit".
These values are assigned to the instance variables roll and name.
The same process happens for the second object s2.
Finally, the initialized values are printed.

Constructor Overloading in Java

Constructor overloading means having more than one constructor in the same class with different parameter lists. Each constructor performs a different type of initialization based on the parameters passed during object creation.

  • All constructors must have the same name as the class, but they must differ in the number, type, or order of parameters so that Java can identify them.

  • When an object is created, Java decides which constructor to call based on the arguments passed. This decision is made at compile time.

  • Because the constructor call is decided at compile time, constructor overloading is an example of compile-time polymorphism.

  • Constructors cannot be overloaded by changing the return type because constructors do not have a return type.

  • Constructor overloading helps in flexible and meaningful object initialization.

Syntax

ClassName() {
    // code
}

ClassName(dataType parameter) {
    // code
}

ClassName(dataType parameter1, dataType parameter2) {
    // code
}

Example

class Student {

    int roll;
    String name;

    // default constructor
    Student() {
        roll = 0;
        name = "Not Assigned";
    }

    // parameterized constructor with one parameter
    Student(int r) {
        roll = r;
        name = "Not Assigned";
    }

    // parameterized constructor with two parameters
    Student(int r, String n) {
        roll = r;
        name = n;
    }

    public static void main(String[] args) {

        // calling default constructor
        Student s1 = new Student();

        // calling constructor with one parameter
        Student s2 = new Student(101);

        // calling constructor with two parameters
        Student s3 = new Student(102, "Amit");

        System.out.println(s1.roll + " " + s1.name);
        System.out.println(s2.roll + " " + s2.name);
        System.out.println(s3.roll + " " + s3.name);
    }
}

Output

0 Not Assigned
101 Not Assigned
102 Amit

The program starts execution from the main() method.
When new Student() is executed, the constructor with no parameters is called.
When new Student(101) is executed, the constructor with one parameter is called.
When new Student(102, "Amit") is executed, the constructor with two parameters is called.
Java decides which constructor to call based on the arguments passed during object creation.

Method Overloading

Method overloading means defining more than one method with the same name in the same class, but with different parameter lists. It allows a method to perform similar tasks with different types or numbers of inputs.

  • Method overloading allows multiple methods with the same method name so that similar operations can be performed using different inputs.

  • Methods are overloaded by changing the number of parameters, data types of parameters, or order of parameters, which helps Java identify which method should be called.

  • Method overloading does not depend on return type. Changing only the return type is not allowed because it does not help Java differentiate methods.

  • When a method is called, Java decides which overloaded method to execute at compile time, based on the arguments passed.

  • Because the method call is resolved at compile time, method overloading is an example of compile-time polymorphism.

  • Method overloading improves code readability and reusability, because the same method name can be used for related operations.

Syntax

returnType methodName(parameters) {
}

returnType methodName(differentParameters) {
}

Example

class Calculator {

    // method with two int parameters
    int add(int a, int b) {
        return a + b;
    }

    // method with three int parameters
    int add(int a, int b, int c) {
        return a + b + c;
    }

    // method with double parameters
    double add(double a, double b) {
        return a + b;
    }

    public static void main(String[] args) {

        Calculator c = new Calculator();

        System.out.println(c.add(10, 20));
        System.out.println(c.add(10, 20, 30));
        System.out.println(c.add(5.5, 4.5));
    }
}

Output

30
60
10.0

When the program runs, the main() method is executed first.
Java checks the arguments passed in each method call.
Based on the number and type of arguments, Java selects the correct overloaded add() method at compile time.
The selected method is then executed and returns the result.

this Keyword in Java

The this keyword in Java is a reference variable that refers to the current object of the class. It is mainly used to distinguish between instance variables and local variables and to access members of the current class.

  • The this keyword always refers to the current calling object.

  • It is used only inside instance methods and constructors, not inside static methods.

  • It helps remove confusion between instance variables and method or constructor parameters having the same name.

  • It can be used to call instance variables, instance methods, and constructors of the same class.

  • this improves code clarity and avoids naming conflicts.

  • The this keyword cannot be used in static methods or static contexts because static members belong to the class as a whole, not a specific object instance.

  •  this() must be the first statement in a constructor

    When the this() keyword is used to call another constructor of the same class, it must always be written as the first statement inside the constructor. This is required because Java needs to complete the constructor chaining before executing any other statements. If this() is written after any other line of code, the compiler will generate an error. Writing this() first ensures that the called constructor initializes the object properly before any further operations are performed.

Here is a very simple and clear example showing that this() must be the first statement in a constructor.

Example of this() as the First Statement

class Student {

    int roll;
    String name;

    // default constructor
    Student() {
        // calling parameterized constructor
        this(101, "Amit");
    }

    // parameterized constructor
    Student(int r, String n) {
        roll = r;
        name = n;
    }

    void show() {
        System.out.println(roll + " " + name);
    }

    public static void main(String[] args) {

        // creating object using default constructor
        Student s1 = new Student();
        s1.show();
    }
}

Output

101 Amit

How this code works

When the object s1 is created, the default constructor is called first.
Inside the default constructor, this(101, "Amit") is written as the first statement, so the parameterized constructor is called.
The parameterized constructor initializes the variables roll and name.
After initialization, the show() method prints the values.

If you write any statement before this() inside a constructor, the program will give a compile-time error.

Primary Uses of the this Keyword

The this keyword has several key applications: 

Referring to Current Class Instance Variables: The most common use is to differentiate between instance variables (class fields) and local variables (method or constructor parameters) that share the same name. This eliminates naming conflicts and improves code clarity.

class Student {
    int id; // Instance variable
    void setId(int id) {
        this.id = id; // 'this.id' refers to the instance variable
    }
}

Invoking Current Class Constructors (this()): The this() constructor call can be used to call another constructor in the same class. This is useful for constructor chaining, which reduces code duplication by allowing one constructor to reuse the initialization code of another.

class Rectangle {
    int width, height;
    Rectangle() {
        this(10, 20); // Calls the parameterized constructor
    }
    Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }
}

Note: The this() call must be the first statement in a constructor.

Invoking Current Class Methods: The this keyword can be used to explicitly call a method of the current class. The compiler often does this implicitly, but using this can make the code more readable.

class MyClass {
    void methodA() {
        this.methodB(); // Explicitly calling another method in the same class
    }
    void methodB() {
        // ... method logic ...
    }
}
  • Passing the Current Object as an Argument: this can be passed as an argument to a method or constructor when another class or method needs a reference to the current object. This is frequently used in event handling or when building a "fluent" interface (method chaining).

  • Returning the Current Class Instance: A method can return the this keyword to return the current object itself. This enables method chaining, allowing multiple operations to be performed on the same object in a single statement. 

1. Using this to Refer Instance Variables

When local variables or constructor parameters have the same name as instance variables, this is used to differentiate them.

whenever the name of the instance and local variable both are same then our runtime environment JVM confused that which one is local variable and which one is instance variable to avoid this problem we should use this keyword.

class Student {

    int roll; //instance variable
    String name;

    // constructor with parameters
    Student(int roll, String name) {
        // this.roll refers to instance variable
        this.roll = roll;
        // this.name refers to instance variable
        this.name = name;
    }

    void show() {
        System.out.println(roll + " " + name);
    }

    public static void main(String[] args) {

        // creating object and passing values
        Student s1 = new Student(101, "Amit");
        s1.show();
    }
}

Output

101 Amit

Explanation

The constructor parameters and instance variables have the same name.
this.roll refers to the instance variable, while roll refers to the parameter.
Without this, Java would not know which variable to assign.

When the object is created, the constructor is called.
The parameters roll and name have the same names as instance variables.
this.roll and this.name clearly refer to the instance variables of the current object.
The values are stored in the object and printed using the show() method.

2. Using this to Call Instance Methods

The this keyword can be used to call another method of the same class.

class Demo {

    void display() { //instance method
        System.out.println("Display method");
    }

    void show() {
        // calling another method of same object
        this.display();
    }

    public static void main(String[] args) {

        // creating object
        Demo d = new Demo();
        d.show();
    }
}

Output

Display method

Explanation

The method show() uses this.display() to calls another method display() using this keyword.

this.display() means the display method of the current object is executed.

3. Using this to Call Constructor (Constructor Chaining)

The this() keyword is used to call another constructor of the same class.
It must always be the first statement inside the constructor.

class Student {

    int roll;
    String name;

    // default constructor
    Student() {
        // calling parameterized constructor
        this(100, "Default");
    }

    // parameterized constructor
    Student(int roll, String name) {
        this.roll = roll;
        this.name = name;
    }

    void show() {
        System.out.println(roll + " " + name);
    }

    public static void main(String[] args) {

        // creating object using default constructor
        Student s1 = new Student();
        s1.show();
    }
}

Output

100 Default

Code working

The default constructor is called first.
Inside it, this(100, "Default") calls the parameterized constructor.
The parameterized constructor initializes the variables.
This avoids writing the same initialization code again.

4. Using this to Pass Current Object as Parameter

The this keyword can be passed as an argument to a method to represent the current object.

class Demo {

    void show(Demo obj) {
        System.out.println("Method called");
    }

    void call() {
        // passing current object to method
        show(this);
    }

    public static void main(String[] args) {

        Demo d = new Demo();
        d.call();
    }
}

Output

Method called

Code working

The method call() passes the current object using this.
The method show() receives the same object reference and executes normally.

5. Using this to Return Current Object

The this keyword can be returned from a method to return the current object.

class Demo {

    Demo getObject() {
        // returning current object
        return this;
    }

    public static void main(String[] args) {

        Demo d1 = new Demo();
        Demo d2 = d1.getObject();

        System.out.println(d1 == d2);
    }
}

Output

true

Code working

The method returns this, which refers to the current object.
Both d1 and d2 point to the same object in memory, so the result is true.

Garbage Collection in Java

Garbage collection in Java is the automatic runtime process by which the JVM removes objects from memory that are no longer being used by the program. It helps free heap memory and prevents memory leakage.

  • Garbage collection is handled automatically by the JVM, not by the programmer.

  • It works on heap memory, where objects are stored.

  • An object becomes eligible for garbage collection when no reference points to it.

  • The programmer cannot force garbage collection, but can request it using System.gc().

  • The garbage collector in JVM collects only those objects that are created by new keyword. So if you have created any objects without new, you can use finalize() method to perform cleanup processing.

  • Garbage collection improves memory management and program efficiency.

Java provides two important mechanisms related to garbage collection:

  • Using System.gc()

  • Using finalize() method

Using System.gc() Method

The System.gc() method is used to request the JVM to run the garbage collector.

class Demo {

    public static void main(String[] args) {

        Demo d = new Demo();   // object created
        d = null;             // object becomes unreachable

        // requesting garbage collection
        System.gc();
    }
}

How it works

When System.gc() is called, the program requests the JVM to run garbage collection.
The JVM may or may not perform garbage collection immediately.
The decision is completely controlled by the JVM, not the programmer.
This method does not guarantee that garbage collection will occur at that moment.

Using finalize() Method

The finalize() method is called by the garbage collector before destroying an object. It is used to perform cleanup operations like releasing resources.

class Demo {

    protected void finalize() {
        System.out.println("Object is garbage collected");
    }

    public static void main(String[] args) {

        Demo d = new Demo();
        d = null;

        System.gc();
    }
}

How it works

When the object becomes unreachable, it becomes eligible for garbage collection.
Before removing the object from memory, the garbage collector calls the finalize() method.
The finalize() method is executed only once for an object.
The timing of finalize() execution is not guaranteed.

Important Rules About finalize()

  • finalize() is called automatically by the garbage collector.

  • A programmer should not call finalize() directly.

  • It runs at runtime, not compile time.

  • It is used for cleanup tasks, not core program logic.

When an Object Becomes Eligible for Garbage Collection

An object becomes eligible for garbage collection when it is no longer reachable.

Case 1: Reference variable set to null

class Demo {

    public static void main(String[] args) {

        Demo d = new Demo();   // object created
        d = null;             // object becomes unreachable
    }
}
Code working

The object is created and referenced by d.
When d is set to null, the object has no reference.
The object becomes eligible for garbage collection.

Case 2: Reference reassigned to another object

class Demo {

    public static void main(String[] args) {

        Demo d1 = new Demo();   // first object
        Demo d2 = new Demo();   // second object

        d1 = d2;               // first object loses reference
    }
}
Code working

Initially, d1 and d2 refer to different objects.
After assignment, both refer to the same object.
The first object becomes unreachable and eligible for garbage collection.

Case 3: Object created inside a method

class Demo {

    void createObject() {
        Demo d = new Demo();   // object created
    }

    public static void main(String[] args) {
        Demo obj = new Demo();
        obj.createObject();
    }
}
Code working

The object created inside createObject() exists only during method execution.
After the method finishes, the object has no reference.
It becomes eligible for garbage collection.

Requesting Garbage Collection

Java allows requesting garbage collection, but the JVM decides when to run it.

class Demo {

    public static void main(String[] args) {

        Demo d = new Demo();
        d = null;

        // requesting garbage collection
        System.gc();
    }
}
Code working

The program requests garbage collection using System.gc().
The JVM may or may not perform garbage collection immediately.

Key understanding to remember

  • Garbage collection is automatic.

  • It removes unused objects, not variables.

  • Objects without references are cleaned from heap memory.

  • JVM decides the timing of garbage collection.

  • Garbage collection → runtime process

  • System.gc() → request to JVM

  • finalize() → cleanup before object removal

  • JVM controls when and whether garbage collection happens

finalize() Method in Java

The finalize() method is a method defined in the Object class that is called by the garbage collector before an object is destroyed. It is used to perform cleanup operations such as releasing resources.

  • The finalize() method is called automatically by the garbage collector.

  • It is executed before an object is removed from memory.

  • It is used for cleanup tasks like closing files or releasing resources.

  • The programmer should not call finalize() directly.

  • The finalize() method is called at most once for an object.

  • The timing of finalize() execution is not guaranteed.

  • finalize() works at runtime, not at compile time.

Syntax

protected void finalize() {
    // cleanup code
}

Example

class Demo {

    // finalize method
    protected void finalize() {
        System.out.println("Object is garbage collected");
    }

    public static void main(String[] args) {

        Demo d = new Demo();   // object created
        d = null;             // object becomes unreachable

        // requesting garbage collection
        System.gc();
    }
}

Output

Object is garbage collected

Code Working Explanation

First, an object of class Demo is created.
Then the reference variable is set to null, so the object becomes unreachable.
The call to System.gc() requests the JVM to run garbage collection.
Before destroying the object, the garbage collector calls the finalize() method.
The message inside finalize() is printed before the object is removed from memory.

Why System.gc() and finalize() are used together in examples

They are not the same thing and they do different jobs.

Role of System.gc()

System.gc() is used to request the JVM to run the garbage collector.

  • It tells the JVM: “If possible, run garbage collection now.”

  • It does not delete objects directly.

  • The JVM may accept or ignore this request.

So, System.gc() is only a request, not an action.

Role of finalize()

finalize() is a method that is called by the garbage collector before an object is destroyed.

  • It is used to perform cleanup work.

  • It runs only if garbage collection actually happens.

  • It is called automatically, not by the programmer.

So, finalize() runs because of garbage collection, not because we call it.

Why both are written in the same program

We write both together only for learning and demonstration.

  • System.gc() is written to increase the chance that garbage collection will run.

  • finalize() is written to show a visible message when the object is collected.

Without System.gc():

  • Garbage collection may not run during the program execution.

  • finalize() may never be called, so nothing is printed.

Without finalize():

  • Garbage collection may run, but we cannot see it happening.

Simple way to remember

  • System.gc()requests garbage collection

  • finalize()runs before object removal

  • Both work at runtime

  • JVM decides everything

Nested Classes

A nested class in Java is a class that is defined inside another class. Nested classes are used to logically group classes that are used only in one place and to improve code organization and readability. When a nested class is non-static, it is called an inner class.

Types of Nested Classes

  1. Static nested class

  2. Inner class (non-static)

  3. Local inner class

  4. Anonymous inner class

1. Static Nested Class

A static nested class is a class defined inside another class using the static keyword. It belongs to the outer class but does not depend on any object of the outer class. A static nested class can be created without creating an object of the outer class.

Static nested classes are used to logically group related classes and access static members of the outer class without creating an outer class object.

  • A static nested class is declared inside an outer class using the static keyword, which makes it a class-level member of the outer class.

  • Because it is static, the static nested class does not require an object of the outer class to be created. This means it can exist independently at class level.

  • A static nested class can access only static variables and static methods of the outer class directly, because non-static members belong to objects.

  • To define a static nested class, it is written inside the outer class using the static keyword before the class name.

  • Static nested classes are mainly used when the nested class is logically related to the outer class but does not need access to its instance data.

Syntax

class OuterClass {

    static class NestedClass {
        // code
    }
}

Object Creation Syntax

OuterClass.NestedClass obj = new OuterClass.NestedClass();

Example

class Outer {

    static int x = 10;   // static variable of outer class

    // static nested class
    static class Inner {

        void show() {
            // accessing static member of outer class
            System.out.println(x);
        }
    }

    public static void main(String[] args) {

        // creating object of static nested class
        Outer.Inner obj = new Outer.Inner();

        // calling method of nested class
        obj.show();
    }
}

Output

10

How the code works

The class Inner is defined inside the class Outer using the static keyword, so it becomes a static nested class.
The variable x is a static variable of the outer class.
Inside the show() method of the nested class, x is accessed directly because static nested classes can access static members of the outer class.
In the main() method, the object of the static nested class is created using Outer.Inner without creating any object of Outer.
When obj.show() is called, the value of x is printed.

Uses of Static Nested Class in Java

  • A static nested class is used to group related classes together when one class is closely associated with another but does not need access to its instance data.

  • It is used when the nested class needs to access only static members of the outer class and does not depend on outer class objects.

  • Static nested classes help in better code organization by keeping helper or supporting classes inside the main class where they are logically related.

  • They are useful to improve encapsulation, because the nested class can be hidden inside the outer class and not exposed separately.

  • Static nested classes reduce unnecessary object creation, because no outer class object is required to create the nested class object.

  • They are commonly used in utility, helper, and grouping scenarios, where the nested class represents a part of the outer class’s functionality.

2. Inner Class

An inner class is a non-static class that is defined inside another class. It is associated with an object of the outer class and can directly access both static and non-static members of the outer class.

  • An inner class is declared without the static keyword inside another class, which makes it dependent on the outer class object.

  • An inner class cannot exist independently. To create an object of an inner class, an object of the outer class is required first.

  • An inner class can access instance variables, instance methods, and static members of the outer class directly.

  • Each inner class object is linked to a specific outer class object, which means it works with that particular outer object’s data.

  • Inner classes are mainly used when a class is tightly coupled with another class and needs full access to its data.

Syntax

class OuterClass {

    class InnerClass {
        // code
    }
}

Object Creation Syntax

OuterClass outerObj = new OuterClass();
OuterClass.InnerClass innerObj = outerObj.new InnerClass();

Example of Inner Class

class Outer {

    int x = 20;   // instance variable of outer class

    class Inner {

        void show() {
            // accessing instance variable of outer class
            System.out.println(x);
        }
    }

    public static void main(String[] args) {

        // creating object of outer class
        Outer outer = new Outer();

        // creating object of inner class using outer object
        Outer.Inner inner = outer.new Inner();

        inner.show();
    }
}

Output

20

How the code works

The class Inner is defined inside the class Outer without using the static keyword, so it becomes an inner class.
An object of Outer is created first because the inner class depends on it.
Using the outer object, an inner class object is created with outer.new Inner().
The inner class method accesses the instance variable x of the outer class and prints its value.

Key understanding to remember

  • Inner class → depends on outer object

  • Outer object → mandatory for inner object creation

  • Can access both static and non-static members

  • Used when classes are closely connected

3. Local Inner Class

A local inner class is a class that is defined inside a method of another class. It is created and used only within that method and cannot be accessed from outside the method.

  • A local inner class is declared inside a method, not directly inside a class.

  • Its scope is limited to the method in which it is defined.

  • A local inner class cannot be accessed outside that method.

  • It can access instance variables of the outer class.

  • It can access local variables of the method only if they are final or effectively final.

  • Local inner classes are mainly used when a class is needed only for a small task inside a method.

Syntax

class OuterClass {

    void methodName() {

        class LocalInnerClass {
            // code
        }
    }
}

Example of Local Inner Class

class Outer {

    int x = 10;   // instance variable of outer class

    void display() {

        int y = 20;   // local variable (effectively final)

        // local inner class
        class Inner {

            void show() {
                System.out.println(x);
                System.out.println(y);
            }
        }

        // creating object of local inner class
        Inner obj = new Inner();
        obj.show();
    }

    public static void main(String[] args) {

        Outer o = new Outer();
        o.display();
    }
}

Output

10
20

How the code works

The class Inner is defined inside the method display(), so it becomes a local inner class.
The local inner class can access the outer class instance variable x.
It can also access the local variable y because y is not changed after initialization.
The object of the local inner class is created inside the same method where it is defined.
Once the method execution ends, the local inner class is no longer accessible.

Key understanding to remember

  • Local inner class → inside a method

  • Scope → limited to that method only

  • Can access outer instance variables

  • Can access only final or effectively final local variables

3. Anonymous Inner Class

An anonymous inner class is a class without a name that is created for one-time use. It is defined and instantiated at the same time, usually to override a method of a class or implement an interface.

  • An anonymous inner class does not have a class name, so it cannot be reused.

  • It is created only once, at the place where it is required.

  • It is mainly used to override a method of a class or implement an interface.

  • It reduces code length when a class is needed for a single purpose.

  • An anonymous inner class cannot have a constructor because it has no name.

  • It can access instance variables of the outer class.

  • It can access final or effectively final local variables.

Syntax

ClassName obj = new ClassName() {
    // overridden methods
};

Example

class Outer {

    void show() {
        System.out.println("Outer class method");
    }

    public static void main(String[] args) {

        // anonymous inner class
        Outer obj = new Outer() {

            // overriding method
            void show() {
                System.out.println("Anonymous inner class method");
            }
        };

        obj.show();
    }
}

Output

Anonymous inner class method

How the code works

The class Outer has a method show().
Inside the main() method, an anonymous inner class is created that overrides the show() method.
The object obj refers to the anonymous inner class object, not the outer class object.
At runtime, the overridden show() method of the anonymous inner class is executed.
Since the class has no name, it cannot be used again elsewhere.

Key understanding to remember

  • Anonymous inner class → no name

  • Created and used at the same time

  • Used only once

  • Mostly used for method overriding or interface implementation

String Class in Java

The String class in Java is used to create and manipulate a sequence of characters. A string is an object of the String class and is immutable, which means its value cannot be changed once it is created.

  • A string in Java is an object, not a primitive data type.

  • The String class is present in the java.lang package.

  • Strings are immutable, so any change creates a new object.

  • Java provides special memory called the String Constant Pool (SCP) to store string literals.

  • Strings can be created in two different ways.

Ways to Create String Objects

Using String Literal

String s1 = "Java";
  • The string is stored in the String Constant Pool.

  • If the same value already exists, Java reuses the existing object.

Using new Keyword

String s2 = new String("Java");
  • A new object is created in heap memory every time.

  • SCP value may still exist, but reference points to heap object.

Example: String Creation

class Demo {

    public static void main(String[] args) {

        // string literal
        String s1 = "Java";

        // string using new keyword
        String s2 = new String("Java");

        System.out.println(s1);
        System.out.println(s2);
    }
}

Output

Java
Java

How the code works

s1 is created using string literal and stored in the String Constant Pool.
s2 is created using new keyword and stored in heap memory.
Both print the same value, but they refer to different memory locations.

Immutability of String

Once a string object is created, its value cannot be changed. Any modification creates a new string object.

class Demo {

    public static void main(String[] args) {

        String s = "Java";

        // modifying string
        s = s.concat(" Programming");

        System.out.println(s);
    }
}

Output

Java Programming

How the code works

The original string "Java" is not changed.
A new string "Java Programming" is created and assigned to s.
This proves that strings are immutable.

Commonly Used String Methods

length()

String s = "Java";
System.out.println(s.length());

Output:

4

charAt()

String s = "Java";
System.out.println(s.charAt(1));

Output:

a

equals()

String s1 = "Java";
String s2 = "Java";
System.out.println(s1.equals(s2));

Output:

true

equalsIgnoreCase()

String s1 = "JAVA";
String s2 = "java";
System.out.println(s1.equalsIgnoreCase(s2));

Output:

true

toUpperCase() and toLowerCase()

String s = "Java";
System.out.println(s.toUpperCase());
System.out.println(s.toLowerCase());

Output:

JAVA
java

substring()

String s = "Programming";
System.out.println(s.substring(0, 7));

Output:

Program

String Comparison using == and equals()

class Demo {

    public static void main(String[] args) {

        String s1 = "Java";
        String s2 = "Java";
        String s3 = new String("Java");

        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s1.equals(s3));
    }
}

Output

true
false
true

How the code works

== compares references, not values.
s1 and s2 point to the same SCP object, so true.
s3 is a new heap object, so reference comparison is false.
equals() compares content, so it returns true.

Key understanding to remember

  • String → object

  • Immutable → cannot be changed

  • Literal → SCP

  • new keyword → heap

  • == → reference comparison

  • equals() → value comparison

NotesNav

NotesNav

Madhepura college of engineering

Frequently Asked Questions