Unit-5 Notes.docx.pdf
Document Details
Uploaded by LionheartedAspen
Dayananda Sagar College of Engineering
Tags
Related
- Computer Operator & Programming Assistant Year 1 JAVA S1.pdf
- Java Language Presentation PDF
- Introduction to Java Programming and Data Structures (2019) by Y. Daniel Liang - PDF
- Java Programming in JAVA (CSE2006) PDF
- University of Zambia CSC 2000 Computer Programming Past Paper PDF 2021
- Computer Programming Concepts PDF
Full Transcript
Concept of Packages in Java: A package in Java is a namespace that organizes a set of related classes and interfaces. Conceptually, you can think of packages as being similar to different directories on your computer. Packages are used to: 1. Avoid Naming Conflicts: By grouping related classes and...
Concept of Packages in Java: A package in Java is a namespace that organizes a set of related classes and interfaces. Conceptually, you can think of packages as being similar to different directories on your computer. Packages are used to: 1. Avoid Naming Conflicts: By grouping related classes and interfaces into packages, Java allows the same class name to be used in different packages. 2. Provide Access Control: Packages can help encapsulate classes and methods, providing a mechanism to define visibility. 3. Simplify Code Maintenance: By organizing code into packages, it becomes easier to locate and manage related code. 4. Enhance Code Reusability: Classes and interfaces that are logically related can be reused in different projects and packages. Java Program Demonstrating Usage of Packages Let's create two classes to demonstrate the usage of packages. We'll define one class inside a package and another class outside the package. The class inside the package will be accessed by the class outside the package. Step 1: Define a Class Inside a Package First, we create a package named `com.example.utils` and define a class `HelloWorld` inside this package. File: com/example/utils/HelloWorld.java package com.example.utils; public class HelloWorld { public void sayHello() { System.out.println("Hello from the HelloWorld class inside the com.example.utils package!"); } } Step 2: Define a Class Outside the Package Next, we create a class `Main` in the default package (i.e., not inside any package) that accesses the `HelloWorld` class from the `com.example.utils` package. File: Main.java import com.example.utils.HelloWorld; public class Main { public static void main(String[] args) { HelloWorld hello = new HelloWorld(); hello.sayHello(); } } Step 3: Compile and Run the Program To compile and run the program, you need to follow these steps: 1. Create Directory Structure: - Create the directory structure for the package: `com/example/utils/` - Place `HelloWorld.java` inside `com/example/utils/` - Place `Main.java` in the root directory 2. Compile the Classes: javac com/example/utils/HelloWorld.java javac Main.java 3. Run the Main Class: java Main Expected Output Hello from the HelloWorld class inside the com.example.utils package! Explanation - Package Declaration: The `HelloWorld` class starts with `package com.example.utils;` to indicate that it belongs to the `com.example.utils` package. - Import Statement: In `Main.java`, we use `import com.example.utils.HelloWorld;` to import the `HelloWorld` class so it can be used in the `Main` class. - Accessing the Class: We create an instance of `HelloWorld` in the `Main` class and call its `sayHello` method to demonstrate functionality across packages. By organizing classes into packages, Java helps in maintaining a clean and modular codebase, facilitating easier maintenance and avoiding class name conflicts. Concept of Access Modifiers: Access Modifiers in Java Access modifiers in Java determine the visibility and accessibility of classes, methods, and variables. They play a crucial role in encapsulation, which is one of the fundamental principles of object-oriented programming. The four access modifiers in Java are: 1. public: The member is accessible from any other class. 2. protected: The member is accessible within the same package and by subclasses. 3. default (package-private): If no access modifier is specified, the member is accessible only within the same package. 4. private: The member is accessible only within the same class. Significance of Access Modifiers - Encapsulation: Access modifiers help in encapsulating the data by restricting access to the internal state of an object. This prevents direct modification of fields and ensures controlled access through methods. - Data Hiding: By restricting access to certain members, access modifiers help in hiding the internal implementation details of a class from other classes. - Security: Access modifiers enhance security by controlling who can access and modify the data. - Flexibility: They provide flexibility to change the implementation without affecting other parts of the program. Java Program Demonstrating Access Modifiers Let's create a Java program with a class that defines methods and variables with different access modifiers. We'll then access these members from within the class, a subclass, and a different package class. Step 1: Define a Class with Different Access Modifiers File: com/example/base/BaseClass.java package com.example.base; public class BaseClass { public String publicField = "Public Field"; protected String protectedField = "Protected Field"; String defaultField = "Default Field"; private String privateField = "Private Field"; public void publicMethod() { System.out.println("Public Method"); } protected void protectedMethod() { System.out.println("Protected Method"); } void defaultMethod() { System.out.println("Default Method"); } private void privateMethod() { System.out.println("Private Method"); } public void accessWithinClass() { System.out.println(publicField); System.out.println(protectedField); System.out.println(defaultField); System.out.println(privateField); publicMethod(); protectedMethod(); defaultMethod(); privateMethod(); } } Step 2: Access Members from a Subclass in the Same Package File: com/example/base/SubClass.java package com.example.base; public class SubClass extends BaseClass { public void accessFromSubclass() { System.out.println(publicField); System.out.println(protectedField); System.out.println(defaultField); // System.out.println(privateField); // Not accessible publicMethod(); protectedMethod(); defaultMethod(); // privateMethod(); // Not accessible } } Step 3: Access Members from a Class in a Different Package File: com/example/other/OtherClass.java package com.example.other; import com.example.base.BaseClass; public class OtherClass { public void accessFromDifferentPackage() { BaseClass base = new BaseClass(); System.out.println(base.publicField); // System.out.println(base.protectedField); // Not accessible // System.out.println(base.defaultField); // Not accessible // System.out.println(base.privateField); // Not accessible base.publicMethod(); // base.protectedMethod(); // Not accessible // base.defaultMethod(); // Not accessible // base.privateMethod(); // Not accessible } } Step 4: Main Class to Demonstrate Access File: Main.java import com.example.base.BaseClass; import com.example.base.SubClass; import com.example.other.OtherClass; public class Main { public static void main(String[] args) { BaseClass base = new BaseClass(); base.accessWithinClass(); SubClass sub = new SubClass(); sub.accessFromSubclass(); OtherClass other = new OtherClass(); other.accessFromDifferentPackage(); } } Explanation 1. BaseClass: Defines fields and methods with different access modifiers and provides a method (`accessWithinClass()`) to access all members within the class. 2. SubClass: A subclass of `BaseClass` within the same package that accesses the `public`, `protected`, and `default` members but not the `private` members. 3. OtherClass: A class in a different package that accesses only the `public` members of `BaseClass`. Expected Output Public Field Protected Field Default Field Private Field Public Method Protected Method Default Method Private Method Public Field Protected Field Default Field Public Method Protected Method Default Method Public Field Public Method This example demonstrates how access modifiers control the visibility of class members within the same class, subclasses, and different package classes. It highlights the importance of access control in encapsulating and securing the internal state and behavior of objects. Interfaces: Interfaces in Java An interface in Java is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Interfaces cannot contain instance fields or constructors, and they are abstract by nature. This means that the methods in an interface do not have a body—they are meant to be implemented by classes. Key Differences Between Interfaces and Classes 1. Nature of Methods: - Interface: Methods in an interface are abstract by default (without implementation). From Java 8 onwards, interfaces can also have default methods (with implementation) and static methods. - Class: A class can have concrete methods (with implementation). 2. Fields: - Interface: Fields in an interface are implicitly `public`, `static`, and `final`. - Class: A class can have instance variables and can control their visibility using access modifiers (`private`, `protected`, `public`). 3. Inheritance: - Interface: A class can implement multiple interfaces, allowing multiple inheritance of type. - Class: A class can extend only one class (single inheritance). 4. Constructors: - Interface: Interfaces cannot have constructors. - Class: Classes have constructors to initialize objects. Java Program Demonstrating Interfaces Let's create an interface with method signatures and a class that implements this interface. Step 1: Define the Interface File: Printable.java public interface Printable { void print(); void printDetails(String details); } Step 2: Implement the Interface in a Class File: Document. public class Document implements Printable { @Override public void print() { System.out.println("Printing the document..."); } @Override public void printDetails(String details) { System.out.println("Document details: " + details); } } Step 3: Demonstrate the Implementation File: Main. public class Main { public static void main(String[] args) { Printable printable = new Document(); printable.print(); printable.printDetails("This is a sample document."); } } Explanation 1. Interface Definition (`Printable.`): - The `Printable` interface declares two methods: `print()` and `printDetails(String details)`. 2. Class Implementation (`Document.`): - The `Document` class implements the `Printable` interface and provides concrete implementations for the `print()` and `printDetails(String details)` methods. 3. Main Class (`Main.`): - In the `Main` class, an instance of `Document` is created and assigned to a variable of type `Printable`. - The `print()` and `printDetails(String details)` methods are called on the `printable` object. Expected Output Printing the document... Document details: This is a sample document. This example demonstrates how interfaces in are used to define a contract for what a class can do without specifying how it does it. By implementing the interface, the `Document` class provides the actual behavior of the methods declared in the `Printable` interface. This allows for more flexible and modular code design, promoting loose coupling and easier maintenance. Exceptions: Exception Handling in Java Exception handling in Java is a powerful mechanism that handles runtime errors, allowing the normal flow of the program to be maintained. Java provides a robust and object-oriented way to handle exceptions, making programs more reliable and resilient to runtime errors. Key Concepts 1. Exception: An unwanted or unexpected event that occurs during the execution of a program, disrupting the normal flow of instructions. 2. Types of Exceptions: - Checked Exceptions: Exceptions that are checked at compile-time (e.g., `IOException`, `SQLException`). - Unchecked Exceptions: Exceptions that are not checked at compile-time (e.g., `ArithmeticException`, `NullPointerException`). - Errors: Serious problems that a reasonable application should not try to catch (e.g., `OutOfMemoryError`, `StackOverflowError`). 3. Keywords: - try: The block of code that might throw an exception. - catch: The block of code that handles the exception. - finally: The block of code that is always executed, regardless of whether an exception is thrown or not. - throw: Used to explicitly throw an exception. - throws: Used to declare an exception. Why Use Exception Handling? - Improves Program Reliability: By handling exceptions, you can provide meaningful error messages and ensure the program continues to run. - Separates Error Handling Code: Keeps the main logic separate from the error-handling logic, improving code readability and maintenance. - Provides Custom Error Messages: Allows for custom messages and responses to specific error conditions. Java Program Demonstrating Exception Handling Let's write a Java program that demonstrates exception handling using `try-catch` blocks. File: ExceptionHandlingDemo.java import java.util.Scanner; public class ExceptionHandlingDemo { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); try { System.out.print("Enter a number: "); int number = scanner.nextInt(); System.out.print("Enter a divisor: "); int divisor = scanner.nextInt(); int result = number / divisor; System.out.println("Result: " + result); } catch (ArithmeticException e) { System.out.println("Error: Division by zero is not allowed."); } catch (Exception e) { System.out.println("Error: An unexpected error occurred."); } finally { System.out.println("Execution completed."); scanner.close(); } } } Explanation 1. Input from User: The program prompts the user to enter a number and a divisor. 2. try Block: The code that might throw an exception is placed inside the `try` block. - It reads two integers from the user. - It performs the division operation which might throw an `ArithmeticException` if the divisor is zero. 3. catch Block: The `catch` blocks handle specific exceptions. - The first `catch` block handles `ArithmeticException` (division by zero). - The second `catch` block is a generic handler for any other exceptions. 4. finally Block: The `finally` block contains code that is always executed, regardless of whether an exception is thrown or caught. In this case, it closes the `Scanner` object. Expected Output Case 1: Normal Execution Enter a number: 10 Enter a divisor: 2 Result: 5 Execution completed. Case 2: Division by Zero Enter a number: 10 Enter a divisor: 0 Error: Division by zero is not allowed. Execution completed. Case 3: Invalid Input Enter a number: ten Error: An unexpected error occurred. Execution completed. This example demonstrates how to use `try-catch` blocks to handle exceptions and prevent the program from crashing, thus ensuring the program can handle unexpected situations gracefully. Try Catch Finally Block: The try-catch-finally Block in Java The `try-catch-finally` block in Java is used for handling exceptions and ensuring that specific code runs regardless of whether an exception is thrown. It consists of three parts: 1. try Block: Contains code that might throw an exception. 2. catch Block: Contains code that handles the exception. You can have multiple `catch` blocks to handle different types of exceptions. 3. finally Block: Contains code that will always execute, regardless of whether an exception occurred or not. It is typically used for resource cleanup, such as closing files or releasing resources. Usage of try-catch-finally Block - try: Encapsulates the code that might throw an exception. - catch: Handles the exception if one is thrown in the try block. Multiple catch blocks can be used to handle different exception types. - finally: Executes code that needs to run regardless of whether an exception occurred, such as closing resources. Extending the Previous Program to Include a finally Block We'll extend the previous program to include a `finally` block that prints a message regardless of whether an exception occurred. Step 1: Update BaseClass with a Method That May Throw an Exception File: com/example/base/BaseClass.java package com.example.base; public class BaseClass { public String publicField = "Public Field"; protected String protectedField = "Protected Field"; String defaultField = "Default Field"; private String privateField = "Private Field"; public void publicMethod() { System.out.println("Public Method"); } protected void protectedMethod() { System.out.println("Protected Method"); } void defaultMethod() { System.out.println("Default Method"); } private void privateMethod() { System.out.println("Private Method"); } public void accessWithinClass() { System.out.println(publicField); System.out.println(protectedField); System.out.println(defaultField); System.out.println(privateField); publicMethod(); protectedMethod(); defaultMethod(); privateMethod(); } public void riskyMethod(int divisor) { try { int result = 10 / divisor; System.out.println("Result: " + result); } catch (ArithmeticException e) { System.out.println("Error: Division by zero is not allowed."); } finally { System.out.println("Finally block executed."); } } } Step 2: Demonstrate the Finally Block in Main Class File: Main.java import com.example.base.BaseClass; import com.example.base.SubClass; import com.example.other.OtherClass; public class Main { public static void main(String[] args) { BaseClass base = new BaseClass(); base.accessWithinClass(); SubClass sub = new SubClass(); sub.accessFromSubclass(); OtherClass other = new OtherClass(); other.accessFromDifferentPackage(); System.out.println("\nDemonstrating finally block:"); base.riskyMethod(2); // Should execute without exception base.riskyMethod(0); // Should cause ArithmeticException } } Explanation 1. riskyMethod in BaseClass: - Contains a `try` block that performs a division operation which might throw an `ArithmeticException`. - The `catch` block handles `ArithmeticException` (division by zero). - The `finally` block prints a message regardless of whether an exception occurred or not. 2. Main Class: - Calls `riskyMethod` with a non-zero divisor (which does not cause an exception). - Calls `riskyMethod` with zero (which causes an `ArithmeticException`). Expected Output Public Field Protected Field Default Field Private Field Public Method Protected Method Default Method Private Method Public Field Protected Field Default Field Public Method Protected Method Default Method Public Field Public Method Demonstrating finally block: Result: 5 Finally block executed. Error: Division by zero is not allowed. Finally block executed. This example demonstrates how to use the `try-catch-finally` block to handle exceptions and ensure that specific code runs regardless of whether an exception occurs. The `finally` block is particularly useful for resource cleanup and ensuring certain actions are always performed. Built-In Exceptions: Aasd Built-in Exceptions in Java Java provides a rich set of built-in exceptions, categorized into two types: checked and unchecked exceptions. 1. Checked Exceptions: These exceptions are checked at compile-time. They are subclasses of `Exception`. Examples include `IOException`, `SQLException`, and `ClassNotFoundException`. 2. Unchecked Exceptions: These exceptions are not checked at compile-time but are checked at runtime. They are subclasses of `RuntimeException`. Examples include `ArithmeticException`, `NullPointerException`, `ArrayIndexOutOfBoundsException`, and `IllegalArgumentException`. Examples of Built-in Exceptions 1. ArithmeticException: Thrown when an arithmetic operation is attempted with illegal operands, such as division by zero. 2. NullPointerException: Thrown when an application attempts to use `null` in a case where an object is required. 3. ArrayIndexOutOfBoundsException: Thrown when an array has been accessed with an illegal index. 4. IOException: Thrown when an I/O operation fails or is interrupted. 5. ClassNotFoundException: Thrown when an application tries to load a class through its name but no definition for the class is found. Java Program Demonstrating Built-in Exception Let's create a Java program that intentionally throws an `ArrayIndexOutOfBoundsException` and catches it using a `catch` block. File: ExceptionDemo.java public class ExceptionDemo { public static void main(String[] args) { int[] array = {1, 2, 3, 4, 5}; try { // Intentionally accessing an invalid array index System.out.println("Accessing element at index 5: " + array); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception caught: " + e); System.out.println("Array index is out of bounds. Please check the index."); } finally { System.out.println("Finally block executed."); } System.out.println("Program continues after exception handling."); } } Explanation 1. try Block: - Attempts to access an element at index 5 of the array, which is out of bounds (the valid indices are 0 to 4). 2. catch Block: - Catches the `ArrayIndexOutOfBoundsException` and prints a custom error message. - The `catch` block helps in handling the exception gracefully without crashing the program. 3. finally Block: - Prints a message indicating that the `finally` block is executed, regardless of whether an exception occurred. Expected Output Exception caught: java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5 Array index is out of bounds. Please check the index. Finally block executed. Program continues after exception handling. This program demonstrates how to intentionally throw a built-in exception and handle it using a `try-catch-finally` block. The `ArrayIndexOutOfBoundsException` is caught, and a custom message is displayed, ensuring that the program continues to execute smoothly even after an exception occurs. Multiple catch clauses Multiple Catch Clauses in Java In Java, you can use multiple catch clauses to handle different types of exceptions separately. This allows you to provide specific exception handling logic for different types of exceptions that might be thrown within the `try` block. Each catch clause is an exception handler that handles the type of exception specified in its parameter. Key Points 1. Multiple catch Blocks: You can have multiple catch blocks to handle different exceptions. 2. Order of catch Blocks: The order of the catch blocks is important. You should catch the most specific exceptions first and the most general exceptions last. 3. Exception Hierarchy: If an exception type can be caught by more than one catch block, the first matching catch block in the sequence will be executed. Modified Program with Multiple Catch Clauses Let's modify the previous program to include multiple catch clauses to handle `ArrayIndexOutOfBoundsException` and `ArithmeticException` separately. File: ExceptionDemo.java public class ExceptionDemo { public static void main(String[] args) { int[] array = {1, 2, 3, 4, 5}; int divisor = 0; // This will cause an ArithmeticException try { // Intentionally accessing an invalid array index System.out.println("Accessing element at index 5: " + array); // This will cause an ArithmeticException int result = 10 / divisor; System.out.println("Result: " + result); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception caught: " + e); System.out.println("Array index is out of bounds. Please check the index."); } catch (ArithmeticException e) { System.out.println("Exception caught: " + e); System.out.println("Cannot divide by zero. Please check the divisor."); } finally { System.out.println("Finally block executed."); } System.out.println("Program continues after exception handling."); } } Explanation 1. try Block: - Attempts to access an element at index 5 of the array, which is out of bounds. - Attempts to divide a number by zero, which will cause an `ArithmeticException`. 2. Multiple catch Blocks: - The first `catch` block handles `ArrayIndexOutOfBoundsException` and prints a custom error message. - The second `catch` block handles `ArithmeticException` and prints a different custom error message. 3. finally Block: - Prints a message indicating that the `finally` block is executed, regardless of whether an exception occurred. Expected Output Exception caught: java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5 Array index is out of bounds. Please check the index. Finally block executed. Program continues after exception handling. Testing Different Exceptions To test the `ArithmeticException`, you can comment out the line that accesses the invalid array index: Modified try Block for Testing ArithmeticException try { // Commenting out the invalid array index access // System.out.println("Accessing element at index 5: " + array); // This will cause an ArithmeticException int result = 10 / divisor; System.out.println("Result: " + result); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception caught: " + e); System.out.println("Array index is out of bounds. Please check the index."); } catch (ArithmeticException e) { System.out.println("Exception caught: " + e); System.out.println("Cannot divide by zero. Please check the divisor."); } finally { System.out.println("Finally block executed."); } Expected Output for ArithmeticException Exception caught: java.lang.ArithmeticException: / by zero Cannot divide by zero. Please check the divisor. Finally block executed. Program continues after exception handling. This program demonstrates how to use multiple catch clauses to handle different types of exceptions separately. By catching specific exceptions, you can provide more meaningful error messages and handle different error conditions appropriately. Interfaces: Importance of Interfaces in Java Interfaces in Java play a crucial role in providing a way to achieve abstraction and multiple inheritance. They define a contract that implementing classes must follow, which promotes loose coupling and flexibility in design. Advantages of Interfaces 1. Abstraction: Interfaces allow you to define methods that must be implemented by the classes, providing a way to specify what a class should do, without specifying how it should do it. 2. Multiple Inheritance: Java does not support multiple inheritance for classes, but interfaces provide a way to achieve multiple inheritance by allowing a class to implement multiple interfaces. 3. Loose Coupling: Interfaces promote loose coupling between components, making the code more flexible and easier to maintain and extend. 4. Testability: Interfaces make it easier to test the code by allowing you to create mock implementations for testing purposes. Java Program Demonstrating Interfaces Let's create a Java program that defines an interface with a method signature and implements it in multiple classes. #Step 1: Define the Interface File: Printable.java public interface Printable { void print(); } #Step 2: Implement the Interface in Multiple Classes File: Document.java public class Document implements Printable { @Override public void print() { System.out.println("Printing document..."); } } File: Image.java public class Image implements Printable { @Override public void print() { System.out.println("Printing image..."); } } #Step 3: Demonstrate the Usage of Interfaces File: Main.java public class Main { public static void main(String[] args) { Printable document = new Document(); Printable image = new Image(); document.print(); image.print(); } } Explanation 1. Printable Interface (`Printable.java`): - Defines a method signature `print()`, which must be implemented by any class that implements the `Printable` interface. 2. Document Class (`Document.java`): - Implements the `Printable` interface and provides a concrete implementation for the `print()` method. 3. Image Class (`Image.java`): - Implements the `Printable` interface and provides a concrete implementation for the `print()` method. 4. Main Class (`Main.java`): - Demonstrates the usage of the `Printable` interface by creating instances of `Document` and `Image` and calling their `print()` methods. Expected Output Printing document... Printing image... This program demonstrates how interfaces in Java can be used to define a contract that multiple classes can implement. By doing so, it promotes code reuse, flexibility, and the ability to write more modular and maintainable code. Programming Problem for practice: 1) Write a program for below problem statement: suppose you are developing a media player application that supports different types of media files such as audio and video. Each media file type requires specific functionalities, such as play, pause, stop, and seek. You want to design an efficient and extensible system that can handle various media file types seamlessly. public interface MediaPlayer { void play(); void pause(); void stop(); void seek(int position); } public class AudioPlayer implements MediaPlayer { @Override public void play() { System.out.println("Playing audio..."); } @Override public void pause() { System.out.println("Pausing audio..."); } @Override public void stop() { System.out.println("Stopping audio..."); } @Override public void seek(int position) { System.out.println("Seeking audio to position: " + position + " seconds..."); } } public class VideoPlayer implements MediaPlayer { @Override public void play() { System.out.println("Playing video..."); } @Override public void pause() { System.out.println("Pausing video..."); } @Override public void stop() { System.out.println("Stopping video..."); } @Override public void seek(int position) { System.out.println("Seeking video to position: " + position + " seconds..."); } } public class Main { public static void main(String[] args) { MediaPlayer audioPlayer = new AudioPlayer(); MediaPlayer videoPlayer = new VideoPlayer(); System.out.println("Audio Player Operations:"); audioPlayer.play(); audioPlayer.pause(); audioPlayer.seek(30); audioPlayer.stop(); System.out.println("\nVideo Player Operations:"); videoPlayer.play(); videoPlayer.pause(); videoPlayer.seek(120); videoPlayer.stop(); } } 2) define an interface for shapes in a drawing application. Each shape should be able to calculate its area and perimeter. Solution : // Define the Shape interface public interface Shape { double calculateArea(); double calculatePerimeter(); } // Implement the Shape interface for Circle public class Circle implements Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override public double calculateArea() { return Math.PI * radius * radius; } @Override public double calculatePerimeter() { return 2 * Math.PI * radius; } } // Implement the Shape interface for Rectangle public class Rectangle implements Shape { private double length; private double width; public Rectangle(double length, double width) { this.length = length; this.width = width; } @Override public double calculateArea() { return length * width; } @Override public double calculatePerimeter() { return 2 * (length + width); } } public class Main { public static void main(String[] args) { Shape circle = new Circle(5); Shape rectangle = new Rectangle(4, 6); System.out.println("Circle Area: " + circle.calculateArea()); System.out.println("Circle Perimeter: " + circle.calculatePerimeter()); System.out.println("Rectangle Area: " + rectangle.calculateArea()); System.out.println("Rectangle Perimeter: " + rectangle.calculatePerimeter()); } } Problem practice: 1) Use Exception handling and write a program for below problem statement: Suppose you are developing a banking application that processes transactions for customer accounts. During transaction processing, various errors and exceptional situations can occur, such as insufficient funds, invalid account numbers, network failures, etc. You want to design a robust system that can handle these exceptions gracefully and provide meaningful error messages to users 2) handle a common scenario of dividing two numbers, where we'll catch and handle the ArithmeticException that occurs if the divisor is zero. public class ExceptionHandlingExample { public static void main(String[] args) { int dividend = 10; int divisor = 0; try { int result = dividend / divisor; System.out.println("Result of division: " + result); } catch (ArithmeticException e) { System.out.println("Error: Division by zero is not allowed."); } System.out.println("Program continues after exception handling."); } }