OOPS IN JAVA PART - 3

OOPS IN JAVA PART - 3

Notes Of Kunal Kushwaha Sir Java + DSA + Interview Preparation Course By Me

‘ THIS ’ KEYWORD IN STATIC FUNCTIONS

In Java, the keyword this refers to the current instance of the class. It is used to differentiate instance variables from local variables when they have the same name. However, this has a specific context: it can only be used within non-static methods (instance methods) because it refers to the current instance of the class, and static methods do not have access to any particular instance.

?

Here's why you cannot use this inside a static method, explained with an example:

?

public class Example {

    private int number;

 

    public void instanceMethod() {

        this.number = 10;  // 'this' can be used in an instance method

        System.out.println("Inside instance method: " + this.number);

    }

 

    public static void staticMethod() {

        // 'this' cannot be used in a static method, and the next line will result in a compilation error

        // this.number = 20;

 

        // Attempting to use 'this' in a static context will lead to a compilation error

        // System.out.println("Inside static method: " + this.number);

    }

}        

?

?

In the example above:

?

- The instanceMethod is a non-static method, and it can use this to refer to the instance of the class and access instance variables like number.

?

- The staticMethod, being a static method, cannot use this because it doesn't operate on a specific instance of the class. It operates at the class level, and there might not be any instance of the class in existence when the method is called. Therefore, the use of this is not allowed in static methods.

?

If you need to access instance variables or methods from a static context, you need to do so through an instance of the class. Create an instance of the class and then use that instance to access non-static members.

?

?

Static variables are often used when you want a value to be shared among all instances of a class or when the variable is related to the class itself rather than a specific instance. Common use cases include constants, counters, or shared configuration values.

In Java, when you have a non-static member (field or method) inside a static context (such as a static method or a static block), or a static member inside a non-static context, there are certain rules and considerations to keep in mind.

?

### Non-static member inside a static context:

?

1. Instance Variables (Non-static Fields):

??

??? If you have an instance variable (non-static field) within a static method or a static block, you cannot directly access it. This is because static methods are associated with the class itself, not with any specific instance. To use non-static members, you need an instance of the class.

public class Example {

    int instanceVariable = 42;

 

    public static void staticMethod() {

        // This will result in a compilation error

        // System.out.println(instanceVariable);

       

        // To access instanceVariable, you need an instance of Example

        Example exampleInstance = new Example();

        System.out.println(exampleInstance.instanceVariable);

    }

}        

?

?

2. Instance Methods:

?

??? Similarly, when calling an instance method from a static context, you need to create an instance of the class to invoke the method.

?

public class Example {

    public void instanceMethod() {

        System.out.println("Instance method");

    }

 

    public static void staticMethod() {

        // This will result in a compilation error

        // instanceMethod();

 

        // To call instanceMethod, you need an instance of Example

        Example exampleInstance = new Example();

        exampleInstance.instanceMethod();

    }

}
        

?

### Static member inside a non-static context:

?

1. Static Variables (Class Variables):

?

??? If you have a static variable (class variable) within a non-static method, you can access it directly.

?

public class Example {

    static int staticVariable = 42;

 

    public void nonStaticMethod() {

        // Accessing staticVariable directly is allowed

        System.out.println(staticVariable);

    }

}        

?

?

2. Static Methods:

?

??? You can call a static method from a non-static context without creating an instance of the class.

?

public class Example {

    public static void staticMethod() {

        System.out.println("Static method");

    }

 

    public void nonStaticMethod() {

        // Calling staticMethod directly is allowed

        staticMethod();

    }

}        

?

?

Understanding these principles is important for writing Java code that follows the rules of the language and leverages the distinction between static and non-static contexts appropriately.

?

STATIC BLOCK

In Java, a static block is declared using the static keyword, followed by an open and close curly brace containing the code to be executed.

The static block is executed only once when the class is loaded into the Java Virtual Machine (JVM). Subsequent attempts to load the class will not re-execute the static block. This ensures that initialization tasks or setup code inside the static block are performed only once during the lifetime of the program, regardless of how many instances of the class are created.

?

Here's a bit more detail:

?

1. Class Loading: The static block is executed during the class loading phase, which occurs when the class is first referenced in the program.

?

2. One-Time Execution: Once the static block is executed, its code is not run again for subsequent class loading events. This is by design, as static blocks are intended for one-time initialization tasks.

?

Here's a simple example to illustrate this:

?

public class MyClass {

    static {

        System.out.println("Static block executed!");

    }

 

    public static void main(String[] args) {

        // Creating an instance of MyClass

        MyClass obj1 = new MyClass();

 

        // Creating another instance of MyClass

        MyClass obj2 = new MyClass();

    }
}        


?

?

In this example, when the program is run, you will see the "Static block executed!" message printed only once, even though two instances of MyClass are created. The static block is executed only during the first class loading event.

?

NESTED CLASS

If you are trying to create an instance of a non-static inner class without an instance of the outer class, it will result in a compilation error. Non-static inner classes are associated with an instance of the outer class, so you need an instance of the outer class to create an instance of the inner class.

?

Consider the following example:

?

public class Outer {

    private int outerField;

 

    public class Inner {

        public void display() {

            System.out.println("Inner class method. Outer field: " + outerField);

        }

    }

 

    public static void main(String[] args) {

        // Attempt to create an instance of Inner without an instance of Outer

        Inner inner = new Inner(); // Compilation error here

    }

}        

?

?

In this example, attempting to create an instance of the Inner class directly in the main method without an instance of the Outer class will result in a compilation error.

?

To fix this, you need to create an instance of the outer class first, and then use that instance to create an instance of the inner class:

?

public class Outer {

    private int outerField;

 

    public class Inner {

        public void display() {

            System.out.println("Inner class method. Outer field: " + outerField);

        }

    }

 

    public static void main(String[] args) {

        Outer outerInstance = new Outer();

        Outer.Inner inner = outerInstance.new Inner(); // Creating instance of Inner with an instance of Outer

        inner.display();

    }

}        

?

?

Here, outerInstance.new Inner() creates an instance of the Inner class associated with the outerInstance of the Outer class.

?

STATIC NESTED CLASS

When you declare an inner class as static in Java, it means that the inner class is no longer associated with an instance of the outer class. This allows you to create instances of the inner class without requiring an instance of the outer class. A static inner class is essentially a top-level class that happens to be nested inside another class for organizational purposes.

?

Here's an example to illustrate a static inner class:

?

public class Outer {

    private static int outerStaticField;

 

    // Static nested class

    public static class StaticNested {

        private int nestedField;

 

        public StaticNested(int nestedField) {

            this.nestedField = nestedField;

        }

 

        public void display() {

            System.out.println("Static nested class method. Nested field: " + nestedField);

            System.out.println("Accessing outer static field: " + outerStaticField);

        }

    }

 

    public static void main(String[] args) {

        // Creating an instance of the static nested class without an instance of the outer class

        StaticNested nestedInstance = new StaticNested(42);

        nestedInstance.display();

    }

}        

?

In this example:

?

- StaticNested is a static nested class, and it can be instantiated without an instance of the Outer class.

- The main method creates an instance of StaticNested directly.

- The static nested class has access to static members of the outer class (`outerStaticField`), but it does not have access to instance members of the outer class.

?

To create an instance of a static nested class, you use the following syntax:

?

Outer.StaticNested nestedInstance = new Outer.StaticNested(42);

?

By marking the inner class as static, you indicate that it is not dependent on any specific instance of the outer class, and you can use it more like a standalone class. This can be useful in scenarios where the inner class does not need access to the instance members of the outer class or when you want to group related classes together for organizational purposes.

Each instance of a static nested class has its own state

In a nested static class, the behavior is different compared to non-static nested classes (inner classes). A static nested class is essentially like a top-level class nested within another class for organizational purposes. Unlike inner (non-static) classes, static nested classes do not have a direct relationship with an instance of the outer class. They are more like regular top-level classes that happen to be nested within another class.

?

Here's an example to illustrate the behavior of static nested classes:

?

public class Outer {

    private static int outerStaticVariable = 0;

 

    // Static nested class

    public static class StaticNested {

        private int nestedVariable;

 

        public StaticNested(int nestedVariable) {

            this.nestedVariable = nestedVariable;

            outerStaticVariable++; // Incrementing the outer static variable on each instance creation

        }

 

        public void display() {

            System.out.println("Outer Static Variable: " + outerStaticVariable);

            System.out.println("Nested Variable: " + nestedVariable);

        }

    }

 

    public static void main(String[] args) {

        Outer.StaticNested nestedObj1 = new Outer.StaticNested(10);

        nestedObj1.display();

 

        Outer.StaticNested nestedObj2 = new Outer.StaticNested(20);

        nestedObj2.display();

    }

}        

?

?

?

In this example:

?

- outerStaticVariable is a static variable in the Outer class.

- StaticNested is a static nested class within the Outer class.

?

When you create instances of StaticNested (`nestedObj1` and nestedObj2), they don't have a direct relationship with instances of the outer class. Therefore, the nestedVariable is specific to each instance of StaticNested, and each instance maintains its own state.

?

Output:

?

Outer Static Variable: 1

Nested Variable: 10

Outer Static Variable: 2

Nested Variable: 20

?

?

In summary, static nested classes are more like standalone classes and don't share the same kind of relationship with the outer class instances as inner classes do. Each instance of a static nested class has its own state, and changes in one instance won't affect another.

SINGLETON CLASS IN JAVA

A Singleton class is a design pattern that restricts the instantiation of a class to one single instance and provides a global point of access to that instance. This pattern is useful when you want to ensure that there is only one instance of a class and that it can be easily accessed from anywhere in your code.

?

Here's a detailed explanation of how to create a Singleton class and its internal declaration in Java:

?

### Singleton Class Example:

?

public class Singleton {

    // Private static instance variable to hold the single instance of the class

    private static Singleton instance;

 

    // Private constructor to prevent instantiation from outside the class

    private Singleton() {

        // Initialization code, if any

    }

 

    // Public method to get the single instance of the class

    public static Singleton getInstance() {

        if (instance == null) {

            // If the instance doesn't exist, create a new one

            instance = new Singleton();

        }

        return instance;

    }

 

    // Other methods and properties of the singleton class

    public void showMessage() {

        System.out.println("Hello from Singleton!");

    }

}        

?

?

### Internal Declaration Breakdown:

?

1. Private Static Instance Variable:

?? - private static Singleton instance;

?? - The class has a private static variable to hold the single instance of the class.

?? - This variable is static because it belongs to the class itself and not to any specific instance.

?

2. Private Constructor:

?? - private Singleton() {...}

?? - The class has a private constructor to prevent instantiation from outside the class.

?? - This ensures that no one can create an instance of the class using the new keyword from outside the class.

?

3. Public Method to Get Instance:

?? - public static Singleton getInstance() {...}

?? - The class provides a public static method (`getInstance`) to get the single instance of the class.

?? - This method checks if the instance is null. If it is, it creates a new instance. Otherwise, it returns the existing instance.

?

4. Initialization Code (Optional):

?? - Inside the private constructor, you can include any initialization code that needs to be executed when the singleton instance is created.

?

5. Other Methods and Properties:

?? - The class can have other methods and properties as needed.

?? - Access to these methods and properties is through the single instance obtained by calling getInstance().

?

### Usage:

?

public class Main {

    public static void main(String[] args) {

        // Getting the singleton instance

        Singleton singletonInstance = Singleton.getInstance();

 

        // Using methods and properties of the singleton instance

        singletonInstance.showMessage();

    }

}?        

### Notes:

- The Singleton pattern ensures that only one instance of the class exists in the JVM.

- The approach shown here is known as "lazy initialization," where the instance is created only when needed.

- The getInstance() method is static, allowing access without creating an instance of the class.

- While this implementation is simple, it is not thread-safe. For thread-safe implementations, consider using synchronization or the double-checked locking pattern.

- In modern Java, you may also consider using the java.util.concurrent package's AtomicReference for a thread-safe lazy initialization approach.

?

INHERITANCE

Inheritance is one of the fundamental concepts in object-oriented programming (OOP) that allows one class to inherit the properties and behaviors of another class. It promotes code reusability and the creation of a hierarchical structure in your code. Inheritance supports the creation of a more specialized class (subclass or derived class) based on an existing, more generalized class (superclass or base class).

?

Here's a detailed explanation of inheritance in Java:

?

### Basic Terminology:

?

- Superclass (Base Class or Parent Class):

? - The class whose properties and behaviors are inherited by another class.

? - Also referred to as the base class or parent class.

?

- Subclass (Derived Class or Child Class):

? - The class that inherits properties and behaviors from another class.

? - Also referred to as the derived class or child class.

?

### Syntax of Inheritance in Java:

?

// Superclass definition

class Animal {

    String species;

 

    void eat() {

        System.out.println("Animal is eating");

    }

}

 

// Subclass definition inheriting from Animal

class Dog extends Animal {

    void bark() {

        System.out.println("Dog is barking");

    }

}        

?

### Key Concepts:

?

1. Extends Keyword:

?? - The extends keyword is used to indicate that a class is inheriting from another class.

?? - In the example above, class Dog extends Animal indicates that Dog is a subclass of Animal.

?

2. Inherited Members:

?? - The subclass inherits the fields and methods (members) of the superclass.

?? - In the example, Dog inherits the species field and the eat() method from Animal.

?

3. Access Modifiers:

?? - The access modifiers (public, protected, private) play a crucial role in determining the visibility of inherited members.

?? - Members marked as private in the superclass are not directly accessible in the subclass.

?

4. Method Overriding:

?? - The subclass can provide its own implementation for a method that is already defined in the superclass. This is known as method overriding.

?? - In the example, Dog could override the eat() method with its own implementation.

@Override

void eat() {

    System.out.println("Dog is eating");

}        

?

?

5. Constructor Chaining:

?? - Constructors are not inherited, but the subclass constructor can invoke the constructor of the superclass using the super keyword.

?? - Example: super(); in the constructor of the subclass.

?

### Example Usage:

?

public class Main {

    public static void main(String[] args) {

        // Creating an instance of the subclass

        Dog myDog = new Dog();

 

        // Accessing inherited fields and methods

        myDog.species = "Canine";

        myDog.eat();

 

        // Accessing subclass-specific method

        myDog.bark();

    }

}        

### Types of Inheritance:

?

1. Single Inheritance:

?? - A class inherits from only one superclass.

?

2. Multiple Inheritance (not directly supported in Java):

?? - A class can inherit from multiple superclasses through interfaces.

?

3. Multilevel Inheritance:

?? - A class is derived from another class, and that derived class serves as the base class for another class.

?

4. Hierarchical Inheritance:

?? - Multiple classes inherit from a single superclass.

?

?

### 1. Single Inheritance with super:

?

// Base class

class Animal {

    void eat() {

        System.out.println("Animal is eating");

    }

}

 

// Derived class inheriting from Animal

class Dog extends Animal {

    void bark() {

        System.out.println("Dog is barking");

    }

 

    // Using super to call the eat method from the base class

    void eat() {

        super.eat();

        System.out.println("Dog is eating");

    }

}

 

// Usage in main

public class SingleInheritanceExample {

    public static void main(String[] args) {

        Dog myDog = new Dog();

        myDog.eat(); // Using method with super from the derived class

        myDog.bark();

    }

}        

?

?

### 2. Multiple Inheritance (using interfaces) with super:

?

/

// Interface 1

interface Flyable {

    void fly();

}

 

// Interface 2

interface Swimmable {

    void swim();

}

 

// Class implementing multiple interfaces

class FlyingFish implements Flyable, Swimmable {

    @Override

    public void fly() {

        System.out.println("FlyingFish can fly");

    }

 

    @Override

    public void swim() {

        System.out.println("FlyingFish can swim");

    }

 

    // Using super to call the swim method from the Swimmable interface

    void dive() {

        super.swim();

        System.out.println("FlyingFish is diving");

    }

}

 

// Usage in main

public class MultipleInheritanceExample {

    public static void main(String[] args) {

        FlyingFish fish = new FlyingFish();

        fish.fly();

        fish.dive(); // Using method with super from the class

    }

}        

?

?

### 3. Multilevel Inheritance with super:

?

// Grandparent class

class Vehicle {

    void start() {

        System.out.println("Vehicle is starting");

    }

}

 

// Parent class inheriting from Vehicle

class Car extends Vehicle {

    void drive() {

        System.out.println("Car is driving");

    }

 

    // Using super to call the start method from the grandparent class

    void startCar() {

        super.start();

        System.out.println("Car is starting");

    }

}

 

// Child class inheriting from Car

class SportsCar extends Car {

    void race() {

        System.out.println("SportsCar is racing");

    }

 

    // Using super to call the startCar method from the parent class

    void startSportsCar() {

        super.startCar();

        System.out.println("SportsCar is starting");

    }

}

 

// Usage in main

public class MultilevelInheritanceExample {

    public static void main(String[] args) {

        SportsCar myCar = new SportsCar();

        myCar.startSportsCar(); // Using method with super from the class

        myCar.drive();

        myCar.race();

    }

}        

?

?

### 4. Hierarchical Inheritance with super:

?

// Parent class

class Shape {

    void draw() {

        System.out.println("Drawing a shape");

    }

}

 

// Child class 1 inheriting from Shape

class Circle extends Shape {

    void draw() {

        super.draw(); // Using method from the parent class

        System.out.println("Drawing a circle");

    }

}

 

// Child class 2 inheriting from Shape

class Rectangle extends Shape {

    void draw() {

        super.draw(); // Using method from the parent class

        System.out.println("Drawing a rectangle");

    }

}

 

// Usage in main

public class HierarchicalInheritanceExample {

    public static void main(String[] args) {

        Circle myCircle = new Circle();

        myCircle.draw(); // Using method with super from the class

    }

}        

?

?

In each example, the use of super is incorporated to demonstrate its usage in accessing members or invoking methods from the superclass. The specific use of super may vary based on the context and the scenario in which it is employed.


?

### Best Practices:

?

- Use inheritance when there is a clear "is-a" relationship between the superclass and subclass.

- Prefer composition over inheritance in situations where code reuse is achieved through aggregation rather than inheritance.

- Be mindful of the potential pitfalls of deep inheritance hierarchies, such as the diamond problem and increased complexity.

?

In summary, inheritance is a powerful mechanism in OOP that facilitates code reuse, polymorphism, and the creation of a well-organized class hierarchy. It is essential to understand its principles and use it judiciously to design robust and maintainable software.

?

PARENT CHILD RELATIONSHIP IN JAVA

In Java, a parent class reference variable can be used to refer to an object of a child class through a mechanism called polymorphism. This allows for flexibility in programming and enables you to write more generic code. However, there are limitations on what you can do with that reference variable.

?

Let's illustrate this with examples:

?

### Parent Class Reference Variable with Child Object:

?

class Parent {

    int parentVariable;

 

    void parentMethod() {

        System.out.println("Parent method");

    }

}

 

class Child extends Parent {

    int childVariable;

 

    void childMethod() {

        System.out.println("Child method");

    }

}

 

public class Main {

    public static void main(String[] args) {

        // Using parent class reference variable to point to a child object

        Parent parentReference = new Child();

 

        // Accessing parent class members

        parentReference.parentVariable = 10;

        parentReference.parentMethod();

 

        // Compilation error: parentReference cannot access child-specific members

        // parentReference.childVariable = 20;

        // parentReference.childMethod();

    }

}        

?

?

In this example, the parentReference variable is of type Parent, but it's pointing to an object of the Child class. This is allowed due to polymorphism. However, you can only access members (variables and methods) that are defined in the Parent class using this reference.

?

### Child Class Reference Variable Cannot Point to Parent Object:

?

public class Main {

    public static void main(String[] args) {

        // Using child class reference variable to point to a parent object

        // Compilation error: Incompatible types

        // Child childReference = new Parent();

    }

}        

?

?

In this example, attempting to use a Child class reference variable to point to a Parent class object results in a compilation error. This is not allowed in Java because it violates the "is-a" relationship implied by inheritance. A Child is a Parent, but a Parent is not necessarily a Child.

?

In summary:

?

- A parent class reference variable can be used to refer to a child class object.

- You can only access members that are part of the parent class through this reference.

- A child class reference variable cannot be used to refer to a parent class object directly.

?

SUPER KEYWORD USE

The super keyword in Java is used to refer to the superclass (parent class) of the current object instance or to call the superclass's methods. It has several use cases, and it is particularly useful in scenarios where you have a subclass that overrides a method defined in its superclass. Let's explore the use cases of the super keyword and understand the differences between super and this.

?

### Use Cases of super Keyword:

?

1. Accessing Superclass Members:

?? - You can use super to access members (fields or methods) of the superclass from within the subclass.

?

class Parent {

    int value = 10;

 

    void display() {

        System.out.println("Value in Parent: " + value);

    }

}

 

class Child extends Parent {

    int value = 20;

 

    void display() {

        System.out.println("Value in Child: " + value);

        System.out.println("Value in Parent (using super): " + super.value);

        super.display();

    }

}        

?

?

2. Calling Superclass Constructor:

?? - You can use super to invoke the constructor of the superclass from within the subclass.

?

??

class Parent {

    Parent() {

        System.out.println("Parent constructor");

    }

}

 

class Child extends Parent {

    Child() {

        super(); // Invoking the constructor of the superclass

        System.out.println("Child constructor");

    }

}        

?

3. Preventing Method Overriding:

?? - In rare cases, you might want to prevent a method in a subclass from overriding a method in the superclass. You can use the final keyword along with super to achieve this.

class Parent {

    final void finalMethod() {

        System.out.println("Final method in Parent");

    }

}

 

class Child extends Parent {

    // Compilation error: Cannot override the final method from Parent

    // void finalMethod() {

    //     System.out.println("Trying to override final method in Child");

    // }

}        

?

??

要查看或添加评论,请登录

Akshay pratap Singh的更多文章

  • OOPS IN JAVA PART 2

    OOPS IN JAVA PART 2

    Notes Of Kunal Kushwaha Sir Java + DSA + Interview Preparation Course By Me Objects are reference types In Java…

  • OOPS IN JAVA PART 1

    OOPS IN JAVA PART 1

    Notes Of Kunal Kushwaha Sir Java + DSA + Interview Preparation Course By Me CLASS AND OBJECTS IN JAVA Class: - Think of…

  • SERVER CREATION WITH NODE JS.

    SERVER CREATION WITH NODE JS.

    I have compiled set of notes from the YouTube playlist titled "Backend Development with Express" by the PepCoding…

    3 条评论
  • ARRAYS AND ARRAYLIST

    ARRAYS AND ARRAYLIST

    Notes Of Kunal Kushwaha Sir Java + DSA + Interview Preparation Course By Me Array It is a collection of Same…

    1 条评论
  • Types Of Programming Languages (Easy Explanation).

    Types Of Programming Languages (Easy Explanation).

    Programming Languages Basically Divided Into 3 Types. 1.

    2 条评论

社区洞察

其他会员也浏览了