суббота, 13 января 2024 г.

Polymorphism in Java

    Polymorphism is a concept by which we can perform a single action in different ways.

There are two types of polymorphism in Java: compile-time polymorphism and runtime polymorphism. We can perform polymorphism in java by method overloading and method overriding.

  • Compile-time Polymorphism (Method Overloading):

  • Method overloading occurs when a class has multiple methods with the same name but different parameters (number, type, or order of parameters).
  • The compiler determines which method to call based on the number and types of arguments passed during the method invocation.

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

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


  • Runtime Polymorphism (Method Overriding):

  • Runtime polymorphism is achieved through method overriding. It occurs when a subclass provides a specific implementation for a method that is already defined in its superclass.
  • The overridden method in the subclass should have the same signature (name, return type, and parameters) as the method in the superclass.
  • Runtime polymorphism can't be achieved by data members.


class Animal {
public void makeSound() {
System.out.println("Some generic sound");
}
}

class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Bark");
}
}

class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow");
}
}

Final Keyword In Java

    The final keyword in java is used to restrict the user. The java final keyword can be used in many context. Final can be:

  1. variable
  2. method
  3. class

  • final variable
If you make any variable as final, you cannot change the value of final variable(It will be constant).
public class FinalVariableExample {
public static void main(String[] args) {
final int MAX_VALUE = 100;
// Attempting to change the value will result in a compilation error
// MAX_VALUE = 200; // Error: cannot assign a value to final variable
System.out.println("Maximum value: " + MAX_VALUE);
}
}

  • final method

If you make any method as final, you cannot override it.

class Parent {
final void myMethod() {
System.out.println("This is a final method in the Parent class.");
}
}

class Child extends Parent {
// Attempting to override the final method will result in a compilation error
// void myMethod() {} // Error: myMethod() in Child cannot override final
// method in Parent
}

public class FinalMethodExample {
public static void main(String[] args) {
Child child = new Child();
child.myMethod(); // Calls the method from the Parent class
}
}

  • final class

If you make any class as final, you cannot extend it.

final class FinalClass {
// Class implementation
}

// Attempting to create a subclass will result in a compilation error
// class SubClass extends FinalClass {} // Error: cannot inherit
// from final FinalClass

The final keyword can be applied with the variables, a final variable that have no value it is called blank final variable or uninitialized final variable. It can be initialized in the constructor only. The blank final variable can be static also which will be initialized in the static block only.

public class BlankFinalVariableExample {
// Blank final variable (instance variable)
final int instanceVariable;

// Blank final static variable
static final int staticVariable;

// Static block to initialize the static variable
static {
staticVariable = 50;
}

// Constructor to initialize the instance variable
public BlankFinalVariableExample(int value) {
instanceVariable = value;
}

public static void main(String[] args) {
BlankFinalVariableExample obj = new BlankFinalVariableExample(10);
System.out.println("Instance Variable: " + obj.instanceVariable);
System.out.println("Static Variable: " + staticVariable);
}
}

Equals() and Hashcode() in Java

    The equals() and hashcode() are the two important methods provided by the Object class for comparing objects. Since the Object class is the parent class for all Java objects, hence all objects inherit the default implementation of these two methods. 

  • equals()

  • The java equals() is a method of lang.Object class, and it is used to compare two objects.
  • To compare two objects that whether they are the same, it compares the values of both the object's attributes.
  • By default, two objects will be the same only if stored in the same memory location.

  • hashcode()
  • A hashcode is an integer value associated with every object in Java, facilitating the hashing in hash tables.
  • To get this hashcode value for an object, we can use the hashcode() method in Java. It is the means hashcode() method that returns the integer hashcode value of the given object.
  • Since this method is defined in the Object class, hence it is inherited by user-defined classes also.
  • The hashcode() method returns the same hash value when called on two objects, which are equal according to the equals() method. And if the objects are unequal, it usually returns different hash values.
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
MyClass myObj = (MyClass) obj;
// Compare fields for equality
return Objects.equals(field1, myObj.field1) && Objects.equals(field2, myObj.field2);
}


@Override
public int hashCode() {
return Objects.hash(field1, field2);
}


Encapsulation in Java

    Encapsulation in Java is a fundamental concept in object-oriented programming (OOP) that refers to the bundling of data and methods that operate on that data within a single unit, which is called a class in Java. Java Encapsulation is a way of hiding the implementation details of a class from outside access and only exposing a public interface that can be used to interact with the class.

In Java, encapsulation is achieved by declaring the instance variables of a class as private, which means they can only be accessed within the class. To allow outside access to the instance variables, public methods called getters and setters are defined, which are used to retrieve and modify the values of the instance variables, respectively. By using getters and setters, the class can enforce its own data validation rules and ensure that its internal state remains consistent.

public class MyClass {
private int myPrivateVariable;

public int getMyPrivateVariable() {
return myPrivateVariable;
}

public void setMyPrivateVariable(int value) {
this.myPrivateVariable = value;
}
}

StringBuilder Class in Java

 StringBuilder class is used to create mutable (modifiable) String. The Java StringBuilder class is same as StringBuffer class except that it is non-synchronized.  

A list of differences between StringBuffer and StringBuilder is given below:



public class StringBuilderExample {
public static void main(String[] args) {
// Creating a StringBuilder
StringBuilder stringBuilder = new StringBuilder("Hello");

// Appending characters
stringBuilder.append(" World");

// Inserting characters at a specific position
stringBuilder.insert(5, ", ");

// Deleting characters
stringBuilder.delete(11, 16);

// Updating characters
stringBuilder.replace(6, 11, "Java");

// Converting to String
String result = stringBuilder.toString();

System.out.println(result); // Output: Hello Java, World
}
}









воскресенье, 7 января 2024 г.

StringBuffer Class in Java

    StringBuffer class is used to create mutable (modifiable) String objects. The StringBuffer class in Java is the same as String class except it is mutable i.e. it can be changed. StringBuffer class is thread-safe i.e. multiple threads cannot access it simultaneously. So it is safe and will result in an order.

No.

String

StringBuffer

1)

The String class is immutable.

The StringBuffer class is mutable, meaning you can modify the content of the string without creating a new object.

2)

String is slow and consumes more memory when we concatenate too many strings because every time it creates new instance.

StringBuffer is fast and consumes less memory when we concatenate strings.

3)

String class overrides the equals() method of Object class. So you can compare the contents of two strings by equals() method.

StringBuffer class doesn't override the equals() method of Object class.

4)

String class is slower while performing concatenation operation.

StringBuffer class is faster while performing concatenation operation.

5)

String class uses String constant pool.

StringBuffer uses Heap memory.


StringBuffer has an initial capacity, and it automatically expands its capacity if needed when you append or insert characters. You can also set the initial capacity explicitly using a constructor. The default capacity of the buffer is 16.If the number of character increases from its current capacity, it increases the capacity by (oldcapacity*2)+2. For example if your current capacity is 16, it will be (16*2)+2=34.


public class StringBufferExample {
    public static void main(String[] args) {
        // Creating a StringBuffer object
        StringBuffer stringBuffer = new StringBuffer("Hello");

        // Appending characters
        stringBuffer.append(" World");

        // Inserting characters at a specific position
        stringBuffer.insert(5, " Java");

        // Deleting characters
        stringBuffer.delete(5, 10);

        // Replacing characters
        stringBuffer.replace(6, 10, "JavaScript");

        // Reversing the content
        stringBuffer.reverse();

        // Displaying the final result
        System.out.println(stringBuffer.toString());
    }
}

суббота, 6 января 2024 г.

String in Java

    A string is an object that represents a sequence of characters.

    There are two ways to create String object:

    • By string literal

    Each time you create a string literal, the JVM checks the "string constant pool" first. If the string already exists in the pool, a reference to the pooled instance is returned. If the string doesn't exist in the pool, a new string instance is created and placed in the pool. 

    String s1="Welcome";
    String s2="Welcome";//It doesn't create a new instance


    • By new keyword
    String s=new String("Welcome");//creates two objects and one reference variable

    JVM will create a new string object in normal (non-pool) heap memory, and the literal "Welcome" will be placed in the string constant pool. The variable s will refer to the object in a heap (non-pool).

    String objects are immutable. Immutable simply means unmodifiable or unchangeable. Once String object is created its data or state can't be changed but a new String object is created.

    class Testimmutablestring{
    public static void main(String args[]){
    String s="Sachin";
    s.concat(" Tendulkar");//concat() method appends the string at the end
    System.out.println(s);//will print Sachin because strings are immutable objects
    }
    }



    There are three ways to compare String in Java:
    • By Using equals() Method
    The String class equals() method compares the original content of the string. It compares values of string for equality. 

    class Teststringcomparison1{
    public static void main(String args[]){
    String s1="Sachin";
    String s2="Sachin";
    String s3=new String("Sachin");
    String s4="Saurav";
    System.out.println(s1.equals(s2));//true
    System.out.println(s1.equals(s3));//true
    System.out.println(s1.equals(s4));//false
    }
    }
    • By Using == Operator

    The == operator compares references not values.

    class Teststringcomparison3{
    public static void main(String args[]){
    String s1="Sachin";
    String s2="Sachin";
    String s3=new String("Sachin");
    System.out.println(s1==s2);//true (because both refer to same instance)
    System.out.println(s1==s3);//false(because s3 refers to instance created in nonpool)
    }
    }
    • By compareTo() Method
    The String class compareTo() method compares values lexicographically and returns an integer value that describes if first string is less than, equal to or greater than second string.

    Suppose s1 and s2 are two String objects. If:

    • s1 == s2 : The method returns 0.
    • s1 > s2 : The method returns a positive value.
    • s1 < s2 : The method returns a negative value.
    class Teststringcomparison4{
    public static void main(String args[]){
    String s1="Sachin";
    String s2="Sachin";
    String s3="Ratan";
    System.out.println(s1.compareTo(s2));//0
    System.out.println(s1.compareTo(s3));//1(because s1>s3)
    System.out.println(s3.compareTo(s1));//-1(because s3 < s1 )
    }
    }

    пятница, 5 января 2024 г.

    Instance initializer block in Java

        An instance initializer block is a block of code within a class that is executed when an instance of the class is created. It is also known as an instance initialization block. The instance initializer block is defined without any keyword, and it is enclosed within curly braces '{}'.

    public class Example {
    private int x;

    // Instance initializer block
    {
    System.out.println("Instance initializer block executed");
    x = 10; // Common initialization code
    }

    // Constructor
    public Example() {
    System.out.println("Constructor executed");
    }

    // Getter method
    public int getX() {
    return x;
    }

    public static void main(String[] args) {
    Example obj = new Example();
    System.out.println("Value of x: " + obj.getX());
    }
    }

    Instance initializer block executed
    Constructor executed
    Value of x: 10

    The instance initializer block is executed in the order in which the classes are initialized, starting from the superclass to the subclass. The 'super' keyword can be used in the instance initializer block to explicitly call the superclass's instance initializer block or constructor.

    class Superclass {
    int superClassVariable;

    // Superclass instance initializer block
    {
    System.out.println("Superclass Instance Initializer Block");
    superClassVariable = 5;
    }

    // Superclass constructor
    public Superclass() {
    System.out.println("Superclass Constructor");
    }
    }

    class Subclass extends Superclass {
    int subclassVariable;

    // Subclass instance initializer block
    {
    System.out.println("Subclass Instance Initializer Block");
    subclassVariable = 10;
    }

    // Subclass constructor
    public Subclass() {
    super(); // This implicitly calls the superclass constructor
    System.out.println("Subclass Constructor");
    }
    }

    public class Example {
    public static void main(String[] args) {
    Subclass obj = new Subclass();
    System.out.println("Superclass Variable: " + obj.superClassVariable);
    System.out.println("Subclass Variable: " + obj.subclassVariable);
    }
    }


    Superclass Instance Initializer Block
    Superclass Constructor
    Subclass Instance Initializer Block
    Subclass Constructor
    Superclass Variable: 5
    Subclass Variable: 10

    super keyword in Java

        The 'super' keyword is used to refer to the immediate parent class object. It can be used to call the superclass methods, access superclass fields, and invoke the superclass constructor. The 'super' keyword is often used in the context of inheritance.

    Here are the main uses of the super keyword in Java:

    • Accessing Superclass Fields:
    You can use 'super' to access fields from the superclass if a subclass has a field with the same name.

    class Animal {
    String name = "Animal";
    }

    class Dog extends Animal {
    String name = "Dog";

    void printNames() {
    System.out.println(name); // prints "Dog"
    System.out.println(super.name); // prints "Animal"
    }
    }

    • Invoking Superclass Methods:
    You can use 'super' to invoke methods from the superclass. This is particularly useful when a subclass overrides a method, and you still want to call the superclass version.

    class Animal {
    void makeSound() {
    System.out.println("Generic animal sound");
    }
    }

    class Dog extends Animal {
    void makeSound() {
    super.makeSound(); // calls the makeSound method of the superclass
    System.out.println("Bark");
    }
    }

    • Invoking Superclass Constructor:
    The 'super' keyword is also used to invoke the superclass constructor from the subclass constructor. It must be the first statement in the subclass constructor.

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

    class Dog extends Animal {
    Dog() {
    super(); // invokes the constructor of the superclass (Animal)
    System.out.println("Dog constructor");
    }
    }


    Method Overriding in Java

        Method overriding in Java is a concept that allows a subclass to provide a specific implementation for a method that is already defined in its superclass. This enables a subclass to provide a specialized version of a method that is already defined in its superclass. Method overriding is a key feature of object-oriented programming and facilitates polymorphism.

    Here are the key points to understand about method overriding in Java:

      • Inheritance: Method overriding is closely tied to inheritance. The method that is to be overridden must be defined in the superclass and inherited by the subclass.
      • Method Signature: The overriding method in the subclass must have the same method signature (name, return type, and parameter types) as the method in the superclass.
      • Access Modifiers: The access level of the overriding method in the subclass should be the same as or more accessible than the overridden method in the superclass. For example, if the superclass method is declared as protected, the overriding method in the subclass can be protected or public, but not private.
      • Return Type: The return type of the overriding method in the subclass must be the same as or a subtype of the return type of the overridden method in the superclass. In Java 5 and later versions, covariant return types allow the return type to be a subtype.
      • Exception Handling: The overriding method is allowed to throw the same, narrower, or no exceptions as the overridden method. However, it is not allowed to throw broader exceptions.
    class Animal {
    void makeSound() {
    System.out.println("Some generic sound");
    }
    }

    class Cat extends Animal {
    @Override
    void makeSound() {
    System.out.println("Meow");
    }
    }

    public class Main {
    public static void main(String[] args) {
    Animal animal = new Cat(); // Polymorphism
    animal.makeSound(); // Calls the overridden method in Cat
    }
    }