Java Programming Examples and Tasks
Java Programming Examples and Tasks
Encapsulation is essential in object-oriented programming because it restricts unauthorized access to an object's data and ensures internal representation is hidden from the outside. The 'Student' class demonstrates this by using private fields for 'name' and 'age', exposing them only through public getter and setter methods. This control allows validation or modification logic within the setters and getters, ensuring data integrity and maintaining the object's invariants .
The Counter class illustrates differences between static and non-static variables, where static variables are shared across all instances, and non-static variables are instance-specific. The 'count' variable is static, incremented every time a new 'Counter' is created, reflecting the total number of 'Counter' instances. In contrast, 'instanceNumber' is non-static, preserving its unique number per instance, determined by the static 'count' at instantiation, demonstrating how static fields provide class-wide properties while non-static preserve individual state .
Using synchronized methods in Java ensures that only one thread can execute a method at any moment, effectively preventing race conditions and ensuring data consistency. In the 'SynchronizedExample' given, the shared resource 'printNumbers' method is synchronized, meaning when one thread enters, the other is blocked until the first thread finishes executing. This guarantees that the numbers are printed sequentially without interleaving from different threads .
Interfaces resolve the diamond problem by allowing a class to implement multiple interfaces without the ambiguity issues related to method inheritance seen with classes. In the example, class 'C' implements interfaces 'A' and 'B', each defining different methods. Because interfaces only provide method signatures without implementation, 'C' provides its specific implementations, eliminating method conflicts typical in class-based multiple inheritance, ensuring clear and consistent behavior .
Abstract classes and inheritance in Java improve code reusability by allowing a superclass to define general behaviors for its subclasses, which can override these behaviors as needed. In the provided example, the 'Animal' class is abstract with a method 'makeSound()'. Subclasses 'Dog' and 'Cat' inherit properties from 'Animal' and provide specific sound implementations. This allows for flexibility and reuse of the 'Animal' class structure, reducing code duplication and improving maintainability .
Data structures like HashMap are important in Java for efficient data access and manipulation, increasing performance by providing constant-time complexity for basic operations such as insertions, deletions, and lookups. The HashMap example demonstrates managing key-value pairs, where users can quickly add, remove, or update entries. Its use in storing and retrieving data mapped by keys showcases the efficiency and speed improvements in handling large data sets compared to more basic structures like lists or arrays .
Exceptions in Java help maintain robust applications by providing a mechanism to handle errors gracefully. In the example, the custom exception 'InsufficientBalanceException' extends the Exception class to signal errors related to insufficient funds during a withdrawal operation. By throwing and catching this exception, the program avoids undefined behaviors or crashes and provides clear feedback ('Insufficient balance for withdrawal') to the user, enhancing user experience and system reliability .
Handling checked exceptions in Java is crucial because they enforce error handling at compile time, ensuring potential errors are addressed. In the custom exception example, 'InsufficientBalanceException' is a checked exception, meaning its occurrence must be declared or caught by the method with 'throws'. This mechanism compels developers to provide explicit error handling for predictable conditions, improving robustness and reliability by preventing certain runtime errors from manifesting unchecked .
Composition in Java involves building classes using references to other objects, allowing more flexible and maintainable designs compared to inheritance. In the example, a 'Car' class contains a reference to an 'Engine' object, which it uses to perform actions like 'drive'. Unlike inheritance, where a subclass is a type of its parent class, composition allows a class to utilize different features by combining them, promoting code reuse and reducing the fragility often introduced by deep inheritance chains .
JDBC (Java Database Connectivity) allows Java applications to interact with databases by using a set of APIs to execute SQL queries. In the 'JDBCExample', a connection to a MySQL database 'testdb' is established using DriverManager.getConnection(). SQL queries are executed using a Statement object, which creates a table and inserts data if the table does not exist. Queries are also used to fetch data, iterating over the ResultSet to process the retrieved information, demonstrating how JDBC manages database interactions through a consistent interface .