воскресенье, 10 марта 2024 г.

Enums in Java

    The Enum is a data type which contains a fixed set of constants. The Java enum constants are static and final implicitly.

  • Points to remember for Java Enum
  • Enum improves type safety
  • Enum can be easily used in switch
  • Enum can be traversed
  • Enum can have fields, constructors and methods
  • Enum may implement many interfaces but cannot extend any class because it internally extends Enum class
xcxcxcxc

public enum TrafficSignal {
RED("Stop", 30),
YELLOW("Prepare to Stop", 5),
GREEN("Go", 45);

private final String action;
private final int durationSeconds;

// Constructor
TrafficSignal(String action, int durationSeconds) {
this.action = action;
this.durationSeconds = durationSeconds;
}

// Method to get the action associated with the traffic signal
public String getAction() {
return action;
}

// Method to get the duration of the signal in seconds
public int getDurationSeconds() {
return durationSeconds;
}
}

public class Main {
public static void main(String[] args) {
// Using enum constants
TrafficSignal redSignal = TrafficSignal.RED;
TrafficSignal greenSignal = TrafficSignal.GREEN;

// Accessing fields and methods
System.out.println("Red signal: " + redSignal.getAction() + " for " +
redSignal.getDurationSeconds() + " seconds");
System.out.println("Green signal: " + greenSignal.getAction() + " for " +
greenSignal.getDurationSeconds() + " seconds");
}
}

Constructor of enum type is private. If you don't declare private compiler internally creates private constructor.

public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
}

public class Main {
public static void main(String[] args) {
// Retrieves the enum constant associated with the specified string
Day day = Day.valueOf("MONDAY");
System.out.println("Day retrieved using valueOf(): " + day);

// Returns an array containing all of the enum constants
Day[] days = Day.values();
System.out.println("All days retrieved using value():");
for (Day d : days) {
System.out.println(d);
}

// Returns the ordinal value of the enum constant
System.out.println("Ordinal value of TUESDAY: " + Day.TUESDAY.ordinal());
}
}

пятница, 8 марта 2024 г.

Exception Handling in Java

    An exception is an event that disrupts the normal flow of a program's instructions during execution. Exceptions can occur for various reasons, such as invalid input, resource unavailability, or programming errors.


Exception handling is a fundamental feature that allows developers to manage and respond to exceptional conditions or errors that occur during the execution of a Java program. Java provides a robust and structured mechanism for handling exceptions.

  • Hierarchy of Java Exception classes
The java.lang.Throwable class is the root class of Java Exception hierarchy inherited by two subclasses: Exception and Error.

  • Types of Java Exceptions

There are mainly two types of exceptions: checked and unchecked. An error is considered as the unchecked exception. However, according to Oracle, there are three types of exceptions namely:

  1. Checked Exception
  2. Unchecked Exception
  3. Error

Checked Exceptions:
  • Checked exceptions are exceptions that are checked by the compiler at compile time. This means that the compiler ensures that these exceptions are either caught or declared to be thrown by the method where they can occur. Examples of checked exceptions include IOException, FileNotFoundException, ParseException, and SQLException.

Unchecked Exceptions (Runtime Exceptions):

  • Unchecked exceptions, also known as runtime exceptions, are exceptions that are not checked by the compiler at compile time. Instead, they occur at runtime and are not required to be caught or declared by the method where they occur.
  • Unchecked exceptions usually represent programming errors or logical errors in the code. They can occur due to incorrect use of APIs, improper data manipulation, or invalid arguments to methods. Examples of unchecked exceptions include NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException, and IllegalArgumentException.

Error:

  • Errors in Java represent serious problems that are typically beyond the control of the application. They usually indicate issues with the runtime environment or system resources.
  • Examples of errors include OutOfMemoryError, StackOverflowError, and VirtualMachineError.

Java try block is used to enclose the code that might throw an exception. It must be used within the method.

If an exception occurs at the particular statement in the try block, the rest of the block code will not execute. So, it is recommended not to keep the code in try block that will not throw an exception.

Java try block must be followed by either catch or finally block.

Java catch block is used to handle the Exception by declaring the type of exception within the parameter. The declared exception must be the parent class exception ( i.e., Exception) or the generated exception type

Java finally block is always executed whether an exception is handled or not. Therefore, it contains all the necessary statements that need to be printed regardless of the exception occurs or not.

public class ExceptionHandlingExample {
public static void main(String[] args) {
try {
int data = 50 / 0; // may throw exception
System.out.println("Result: " + data);
} catch (ArithmeticException e) {
System.err.println("Error: Division by zero is not allowed.");
} finally {
System.out.println("Cleanup code executed.");
}
}
}


A try block can be followed by one or more catch blocks. Each catch block must contain a different exception handler. So, if you have to perform different tasks at the occurrence of different exceptions, use java multi-catch block.

public class MultipleCatchBlock1 {
public static void main(String[] args) {
try {
int a[] = new int[5];
a[5] = 30/0;
} catch(ArithmeticException e) {
System.out.println("Arithmetic Exception occurs");
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("ArrayIndexOutOfBounds Exception occurs");
} catch(Exception e) {
System.out.println("Parent Exception occurs");
}
System.out.println("rest of the code");
}
}


public class MultipleExceptionExample {
public static void main(String args[]) {
try {
int array[] = new int[10];
array[10] = 30/0;
}
catch (Exception | ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
}
}
}

The Java throw keyword is used to throw an exception explicitly. We can throw either checked or unchecked exceptions in Java by throw keyword.


Throwing an unchecked exception doesn't require you to declare it using the throws clause in the method signature or handle it with a try-catch block.

public class UncheckedExceptionExample {
public static void main(String[] args) {
try {
// Call a method that throws an unchecked exception
int result = divide(10, 0);
System.out.println("Result: " + result); // This line won't be reached
} catch (ArithmeticException e) {
// Catch and handle the exception
System.out.println("An arithmetic exception occurred: " + e.getMessage());
}
}

public static int divide(int dividend, int divisor) {
// Check if divisor is zero
if (divisor == 0) {
// Throw an unchecked exception
throw new ArithmeticException("Error: Division by zero");
}
// Return the result of the division
return dividend / divisor;
}
}



For checked exceptions, it is indeed required to either handle the exception using a try-catch block or declare the exception in the method signature using the throws keyword.

public class CheckedExample {
public static void main(String[] args) {
try {
// Call a method that throws a checked exception
readFile("nonexistent_file.txt");
} catch (FileNotFoundException e) {
// Catch and handle the exception
System.out.println("File not found: " + e.getMessage());
}
}

public static void readFile(String filename) throws FileNotFoundException {
// Check if file exists
File file = new File(filename);
if (!file.exists()) {
// Throw FileNotFoundException explicitly
throw new FileNotFoundException("File '" + filename + "' not found");
}
// Try to open the file
try {
FileReader reader = new FileReader(file);
// Read data from the file (this won't be executed in this example)
reader.close();
} catch (IOException e) {
// Handle the IOException if opening or reading from the file fails
System.out.println("Error reading file: " + e.getMessage());
}
}
}

The Java throws keyword is used to declare an exception. It gives an information to the programmer that there may occur an exception. 

 If we are calling a method that declares an exception, we must either caught or declare the exception.

There are two cases:

  1. Case 1: We have caught the exception i.e. we have handled the exception using try/catch block.
  2. Case 2: We have declared the exception i.e. specified throws keyword with the method.
import java.io.*;

class M {
void method() throws IOException {
throw new IOException("device error");
}
}

public class Testthrows2 {
public static void main(String args[]) {
try {
M m = new M();
m.method();
} catch(Exception e) {
System.out.println("exception handled");
}

System.out.println("normal flow...");
}
}


class M {
void method() {
System.out.println("device operation performed");
}
}

class Testthrows3 {
public static void main(String args[]) throws IOException { // declare exception
M m = new M();
m.method();

System.out.println("normal flow...");
}
}


There are many rules if we talk about method overriding with exception handling.

If the superclass method does not declare an exception, subclass overridden method cannot declare the checked exception.

class Parent{
// defining the method
void msg() {
System.out.println("parent method");
}
}
public class TestExceptionChild extends Parent{
// overriding the method in child class
// gives compile time error
void msg() throws IOException {
System.out.println("TestExceptionChild");
}
public static void main(String args[]) {
Parent p = new TestExceptionChild();
p.msg();
}
}

If the superclass method does not declare an exception, subclass overridden method cannot declare the checked exception but can declare unchecked exception.

class Parent{
void msg()throws ArithmeticException {
System.out.println("parent method");
}
}
public class TestExceptionChild2 extends Parent{
void msg()throws Exception {
System.out.println("child method");
}
public static void main(String args[]) {
Parent p = new TestExceptionChild2();
try {
p.msg();
}
catch (Exception e){}
}
}

If the superclass method declares an exception, subclass overridden method can declare the same subclass exception or no exception but cannot declare parent exception.

class Parent{
void msg()throws ArithmeticException {
System.out.println("parent method");
}
}
public class TestExceptionChild2 extends Parent{
void msg()throws Exception {
System.out.println("child method");
}
public static void main(String args[]) {
Parent p = new TestExceptionChild2();
try {
p.msg();
}
catch (Exception e){}
}
}


вторник, 13 февраля 2024 г.

Interface in Java

 An interface in Java is a blueprint of a class. It has static constants and abstract methods.

The interface in Java is a mechanism to achieve abstraction. There can be only abstract methods in the Java interface, not method body. It is used to achieve abstraction and multiple inheritance in Java.

It cannot be instantiated just like the abstract class.

The Java compiler adds public and abstract keywords before the interface method. Moreover, it adds public, static and final keywords before data members.


// Defining an interface
interface Animal {
void eat();
void sleep();
}

// Implementing the interface
class Dog implements Animal {
@Override
public void eat() {
System.out.println("Dog is eating");
}

@Override
public void sleep() {
System.out.println("Dog is sleeping");
}
}

// Main class to demonstrate usage
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.eat();
dog.sleep();
}
}


  • Multiple inheritance in Java by interface


  • Default Method in Interface
Starting from Java 8, interfaces can have default methods. Default methods are methods within an interface that have a default implementation. They allow you to add new methods to an existing interface without breaking compatibility with classes that already implement the interface.
When a class implements an interface that contains a default method, it can choose whether to use the default implementation provided by the interface or provide its own implementation.
interface Animal {
void eat();
void sleep();

// Default method
default void breathe() {
System.out.println("Animal is breathing");
}
}

class Dog implements Animal {
@Override
public void eat() {
System.out.println("Dog is eating");
}

@Override
public void sleep() {
System.out.println("Dog is sleeping");
}
}

public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.eat();
dog.sleep();
dog.breathe(); // Calling default method
}
}


  • Static Method in Interface
Starting from Java 8, interfaces can also contain static methods. Static methods in interfaces are similar to static methods in classes, but they are scoped within the interface and cannot be overridden in implementing classes.
interface Animal {
void eat();
void sleep();

// Static method
static void info() {
System.out.println("This is an Animal");
}
}

class Dog implements Animal {
@Override
public void eat() {
System.out.println("Dog is eating");
}

@Override
public void sleep() {
System.out.println("Dog is sleeping");
}
}

public class Main {
public static void main(String[] args) {
Animal.info(); // Calling static method directly from interface

Dog dog = new Dog();
dog.eat();
dog.sleep();
}
}

  • Private Method in Interface
Starting from Java 9, interfaces can contain private methods, which are methods scoped within the interface and are only accessible within the interface itself. Private methods in interfaces are primarily used to implement shared code or helper methods that are used by default or static methods within the interface.

interface Animal {
void eat();
void sleep();

// Default method
default void breathe() {
inhale();
exhale();
}

// Private method
private void inhale() {
System.out.println("Animal is inhaling");
}

// Private method
private void exhale() {
System.out.println("Animal is exhaling");
}
}

class Dog implements Animal {
@Override
public void eat() {
System.out.println("Dog is eating");
}

@Override
public void sleep() {
System.out.println("Dog is sleeping");
}
}

public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.eat();
dog.sleep();
dog.breathe(); // Calling default method
}
}

Abstract class in Java

    Abstraction is a process of hiding the implementation details and showing only functionality to the user.

A class which is declared with the abstract keyword is known as an abstract class in Java. 

  • An abstract class must be declared with an abstract keyword.
  • It can have abstract and non-abstract methods.
  • It cannot be instantiated.
  • It can have constructors and static methods also.
  • It can have final methods which will force the subclass not to change the body of the method.

If there is an abstract method in a class, that class must be abstract.

If you are extending an abstract class that has an abstract method, you must either provide the implementation of the method or make this class abstract.

abstract class Animal {
private String name;
// Constructor
public Animal(String name) {
this.name = name;
}
// Abstract method
public abstract void makeSound();
// Concrete method
public void sleep() {
System.out.println(name + " is sleeping.");
}
// Getter method
public String getName() {
return name;
}
}

class Dog extends Animal {
// Constructor
public Dog(String name) {
super(name);
}
// Implementation of abstract method
@Override
public void makeSound() {
System.out.println(getName() + " says: Woof!");
}
}

class Cat extends Animal {
// Constructor
public Cat(String name) {
super(name);
}
// Implementation of abstract method
@Override
public void makeSound() {
System.out.println(getName() + " says: Meow!");
}
}

public class Main {
public static void main(String[] args) {
Animal dog = new Dog("Buddy");
Animal cat = new Cat("Whiskers");
dog.makeSound();
dog.sleep();
cat.makeSound();
cat.sleep();
}
}