Tutorial Details
Table of Contents
Basic guides And Resources
JAVA FOUNDATIONAL MATERIAL TUTORIAL
- Module 1: Introduction to Java
- Module 2: Java Basics
- Module 3: Control Flow Statements
- Module 4: Arrays and Strings
- Module 5: Object-Oriented Programming (OOP) Basics
- Module 6: Exception Handling
- Module 7: Java Collections Framework
- Module 8: File Handling
- Module 9: Threads and Multithreading
- Module 10: Java GUI Development
- Module 11: Database Connectivity
- Module 12: Java Networking
- Module 13: Functional Programming in Java
- Module 14: Advanced Topics
- Module 15: Building a Real-World Project
- Resource Materials
Module 1: Introduction to Java
Objective: Understand what Java is, set up the development environment, and write your first Java program while learning the basic syntax and structure of a Java application.
1. What is Java?
Java is a high-level, class-based, object-oriented programming language. It is widely used for building platform-independent applications, ranging from desktop apps to web and mobile solutions.
Key Characteristics:
- Platform Independence: “Write Once, Run Anywhere” (WORA). Java code compiles to bytecode, which can run on any device with a Java Virtual Machine (JVM).
- Object-Oriented: Everything in Java revolves around objects and classes.
- Rich Ecosystem: Includes extensive standard libraries and frameworks for almost every need.
- Used For:
- Web development (using Spring, Hibernate).
- Android app development.
- Enterprise applications.
2. Features of Java
- Platform Independence: Java programs can run on different operating systems without modification.
- Object-Oriented: Encapsulation, inheritance, and polymorphism are key principles.
- Robust: Built-in exception handling and memory management.
- Secure: Security features like bytecode verification and a secure runtime environment.
- Multi-threaded: Supports concurrent programming with threads.
- High Performance: The JVM optimizes performance using Just-In-Time (JIT) compilation.
3. Installing JDK and Setting Up an IDE
A. Installing the Java Development Kit (JDK)
- Download JDK:
- Visit the Oracle JDK Downloads Page or OpenJDK.
- Install JDK:
- Follow the installation instructions for your OS (Windows, macOS, or Linux).
- Verify Installation: Open a terminal/command prompt and type:
This should display the installed Java version.java -version
B. Setting Up an IDE
- Recommended IDEs:
- IntelliJ IDEA (Community Edition for free).
- Eclipse IDE.
- Visual Studio Code (with Java extensions).
- Install IntelliJ IDEA:
- Download and install IntelliJ IDEA from JetBrains.
- Set Up Your First Java Project:
- Open IntelliJ IDEA.
- Click on File > New > Project.
- Select Java as the project type.
- Set the JDK path and project name.
- Click Finish to create the project.
4. Writing and Running Your First Java Program
A. Writing “Hello, World!” Program
- Open IntelliJ IDEA or your preferred IDE.
- Create a new Java class file named
HelloWorld.java
. - Write the following code:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }
B. Explanation of Code
public class HelloWorld
:- Defines a public class named
HelloWorld
. - A Java program must have at least one class.
- Defines a public class named
public static void main(String[] args)
:- Entry point of a Java application.
public
: Accessible from anywhere.static
: Belongs to the class rather than an instance.void
: Returns no value.String[] args
: Array of command-line arguments.
System.out.println("Hello, World!");
:- Prints the message
"Hello, World!"
to the console.
- Prints the message
C. Running the Program
- In IntelliJ IDEA:
- Right-click on the file and select Run HelloWorld.main().
- In the terminal:
- Compile the program:
javac HelloWorld.java
- Run the compiled program:
java HelloWorld
- Compile the program:
5. Understanding Java Syntax and Program Structure
A. Structure of a Java Program
// This is a single-line comment
/*
This is a multi-line comment
*/
public class MyClass { // Class declaration
public static void main(String[] args) { // Main method
// Code goes here
}
}
B. Key Components
- Classes:
- Everything in Java is encapsulated in a class.
- Methods:
- Functions inside classes, e.g.,
main()
method.
- Functions inside classes, e.g.,
- Statements:
- Instructions executed sequentially, e.g.,
System.out.println();
.
- Instructions executed sequentially, e.g.,
- Comments:
- Used to document code.
6. Practical Exercises
Exercise 1: Print Your Name
Modify the “Hello, World!” program to print your name instead.
public class MyName {
public static void main(String[] args) {
System.out.println("Hello, my name is [Your Name]!");
}
}
Exercise 2: Simple Math Operations
Write a program to calculate and print the sum of two numbers.
public class SimpleMath {
public static void main(String[] args) {
int a = 10;
int b = 20;
int sum = a + b;
System.out.println("The sum is: " + sum);
}
}
Exercise 3: Command-Line Arguments
Write a program to accept two numbers as command-line arguments and print their product.
public class CommandLineArgs {
public static void main(String[] args) {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
System.out.println("The product is: " + (a * b));
}
}
7. Summary
Key Takeaways:
- Java Basics:
- Platform-independent, object-oriented programming language.
- Development Setup:
- Install JDK and set up an IDE like IntelliJ IDEA.
- Basic Syntax:
- Programs are written in classes, with the
main
method serving as the entry point.
- Programs are written in classes, with the
- First Program:
- Successfully write and run a “Hello, World!” program.
Module 2: Java Basics
Objective: Learn the foundational concepts of Java programming, including data types, variables, operators, user input/output, type conversion, and best practices.
1. Data Types and Variables
A. Variables
Variables are containers for storing data values. In Java, variables must be declared with a specific data type.
Syntax:
dataType variableName = value;
Example:
int age = 25;
double salary = 50000.50;
char grade = 'A';
boolean isStudent = false;
B. Primitive Data Types
Type | Description | Size | Example |
---|---|---|---|
byte | Integer | 1 byte | -128 to 127 |
short | Integer | 2 bytes | -32,768 to 32,767 |
int | Integer | 4 bytes | -2^31 to 2^31-1 |
long | Large integer | 8 bytes | -2^63 to 2^63-1 |
float | Decimal numbers | 4 bytes | 3.14f |
double | Large decimals | 8 bytes | 3.14159 |
char | Single character | 2 bytes | 'A' |
boolean | Logical values | 1 bit | true or false |
C. Constants
To declare constants, use the final
keyword.
Example:
final double PI = 3.14159;
2. Operators
A. Arithmetic Operators
Used to perform basic mathematical operations.
Operator | Description | Example |
---|---|---|
+ | Addition | a + b |
- | Subtraction | a - b |
* | Multiplication | a * b |
/ | Division | a / b |
% | Modulus | a % b |
Example:
int a = 10, b = 3;
System.out.println("Addition: " + (a + b));
System.out.println("Modulus: " + (a % b));
B. Relational Operators
Used to compare values.
Operator | Description | Example |
---|---|---|
== | Equal to | a == b |
!= | Not equal to | a != b |
> | Greater than | a > b |
< | Less than | a < b |
>= | Greater than or equal to | a >= b |
<= | Less than or equal to | a <= b |
C. Logical Operators
Used for combining multiple conditions.
Operator | Description | Example |
---|---|---|
&& | Logical AND | a > b && a < c |
` | ` | |
! | Logical NOT | !(a > b) |
3. Input and Output in Java
A. Output with System.out.println
Used to print messages to the console.
Example:
System.out.println("Welcome to Java!");
B. Input with Scanner
The Scanner
class is used to get input from the user.
Steps:
- Import the Scanner class:
import java.util.Scanner;
- Create a Scanner object:
Scanner scanner = new Scanner(System.in);
- Read input:
nextInt()
: Reads an integer.nextDouble()
: Reads a double.nextLine()
: Reads a line of text.
Example:
import java.util.Scanner;
public class UserInput {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.print("Enter your age: ");
int age = scanner.nextInt();
System.out.println("Hello, " + name + "! You are " + age + " years old.");
}
}
4. Type Conversion and Casting
A. Implicit Conversion
Java automatically converts smaller data types to larger types (e.g., int
to double
).
Example:
int a = 10;
double b = a; // Implicit conversion
System.out.println(b);
B. Explicit Casting
Used to convert larger types to smaller types manually.
Syntax:
dataType variable = (dataType) value;
Example:
double a = 10.5;
int b = (int) a; // Explicit casting
System.out.println(b);
5. Comments and Coding Best Practices
A. Comments
- Single-line comment:
// This is a single-line comment.
- Multi-line comment:
/* This is a multi-line comment. */
B. Best Practices
- Use meaningful variable names:
int numberOfStudents = 25;
- Follow proper indentation.
- Add comments to explain complex logic.
- Use constants for fixed values:
final double TAX_RATE = 0.05;
6. Practical Exercises
Exercise 1: Basic Calculator
Write a program to take two numbers as input and perform basic arithmetic operations.
Solution:
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter first number: ");
double num1 = scanner.nextDouble();
System.out.print("Enter second number: ");
double num2 = scanner.nextDouble();
System.out.println("Addition: " + (num1 + num2));
System.out.println("Subtraction: " + (num1 - num2));
System.out.println("Multiplication: " + (num1 * num2));
System.out.println("Division: " + (num1 / num2));
}
}
Exercise 2: Even or Odd
Write a program to check if a number entered by the user is even or odd.
Solution:
import java.util.Scanner;
public class EvenOdd {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter a number: ");
int num = scanner.nextInt();
if (num % 2 == 0) {
System.out.println("The number is even.");
} else {
System.out.println("The number is odd.");
}
}
}
Exercise 3: Simple Interest Calculator
Write a program to calculate simple interest (SI = P × R × T / 100
).
Solution:
import java.util.Scanner;
public class SimpleInterest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter principal amount: ");
double principal = scanner.nextDouble();
System.out.print("Enter rate of interest: ");
double rate = scanner.nextDouble();
System.out.print("Enter time in years: ");
double time = scanner.nextDouble();
double simpleInterest = (principal * rate * time) / 100;
System.out.println("The Simple Interest is: " + simpleInterest);
}
}
7. Summary
Key Takeaways:
- Data Types: Java provides a rich set of primitive data types.
- Operators: Perform calculations and comparisons using arithmetic, relational, and logical operators.
- Input/Output: Use
Scanner
for user input andSystem.out.println
for output. - Type Conversion: Learn implicit and explicit conversions.
- Best Practices: Write clean, readable, and well-documented code.
Module 3: Control Flow Statements
Objective: Learn how to control the flow of execution in Java programs using conditional statements, loops, and jump statements.
1. If-Else Statements
A. Syntax
if (condition) {
// Code to execute if condition is true
} else if (anotherCondition) {
// Code to execute if anotherCondition is true
} else {
// Code to execute if none of the above conditions are true
}
B. Example
public class IfElseExample {
public static void main(String[] args) {
int number = 10;
if (number > 0) {
System.out.println("The number is positive.");
} else if (number < 0) {
System.out.println("The number is negative.");
} else {
System.out.println("The number is zero.");
}
}
}
2. Switch-Case
A. Syntax
switch (variable) {
case value1:
// Code to execute for value1
break;
case value2:
// Code to execute for value2
break;
default:
// Code to execute if no cases match
}
B. Example
public class SwitchExample {
public static void main(String[] args) {
int day = 3;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Invalid day");
}
}
}
3. Loops
A. For Loops
Syntax
for (initialization; condition; increment/decrement) {
// Code to execute in each iteration
}
Example
public class ForLoopExample {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.println("Count: " + i);
}
}
}
B. While Loops
Syntax
while (condition) {
// Code to execute while condition is true
}
Example
public class WhileLoopExample {
public static void main(String[] args) {
int i = 1;
while (i <= 5) {
System.out.println("Count: " + i);
i++;
}
}
}
C. Do-While Loops
Syntax
do {
// Code to execute
} while (condition);
Example
public class DoWhileExample {
public static void main(String[] args) {
int i = 1;
do {
System.out.println("Count: " + i);
i++;
} while (i <= 5);
}
}
4. Break, Continue, and Labels
A. Break Statement
Exits the loop immediately.
Example
public class BreakExample {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break;
}
System.out.println("Count: " + i);
}
}
}
B. Continue Statement
Skips the current iteration and moves to the next iteration.
Example
public class ContinueExample {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
continue;
}
System.out.println("Count: " + i);
}
}
}
C. Labels
Used with break
or continue
to exit or continue a specific loop.
Example
public class LabelExample {
public static void main(String[] args) {
outerLoop:
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (i == 2 && j == 2) {
break outerLoop;
}
System.out.println("i = " + i + ", j = " + j);
}
}
}
}
5. Practical Exercises
Exercise 1: Find the Maximum of Three Numbers
Write a program that takes three numbers as input and prints the largest of the three using if-else
.
Solution:
import java.util.Scanner;
public class MaxNumber {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter first number: ");
int num1 = scanner.nextInt();
System.out.print("Enter second number: ");
int num2 = scanner.nextInt();
System.out.print("Enter third number: ");
int num3 = scanner.nextInt();
if (num1 >= num2 && num1 >= num3) {
System.out.println("The largest number is: " + num1);
} else if (num2 >= num1 && num2 >= num3) {
System.out.println("The largest number is: " + num2);
} else {
System.out.println("The largest number is: " + num3);
}
}
}
Exercise 2: Multiplication Table
Write a program that prints the multiplication table of a number using a for
loop.
Solution:
import java.util.Scanner;
public class MultiplicationTable {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter a number: ");
int number = scanner.nextInt();
for (int i = 1; i <= 10; i++) {
System.out.println(number + " x " + i + " = " + (number * i));
}
}
}
Exercise 3: Sum of Even Numbers
Write a program to calculate the sum of all even numbers between 1 and 100 using a while
loop.
Solution:
public class SumEvenNumbers {
public static void main(String[] args) {
int sum = 0;
int i = 1;
while (i <= 100) {
if (i % 2 == 0) {
sum += i;
}
i++;
}
System.out.println("Sum of even numbers from 1 to 100 is: " + sum);
}
}
6. Summary
Key Takeaways:
- If-Else Statements:
- Use for conditional branching.
- Switch-Case:
- Suitable for fixed-value conditions.
- Loops:
For
loops for definite iterations.While
loops for indefinite iterations.Do-while
loops to ensure at least one execution.
- Break and Continue:
- Control loop flow and exit early or skip iterations.
Module 4: Arrays and Strings
Objective: Learn how to work with collections of data using arrays and manipulate text using Java’s String classes and utilities.
1. Arrays
A. Declaring, Initializing, and Accessing Arrays
Syntax:
dataType[] arrayName = new dataType[size];
Example:
public class ArrayExample {
public static void main(String[] args) {
int[] numbers = new int[5]; // Declare and initialize an array of size 5
numbers[0] = 10; // Assign values
numbers[1] = 20;
numbers[2] = 30;
System.out.println("First element: " + numbers[0]);
System.out.println("Second element: " + numbers[1]);
// Iterating through the array
for (int i = 0; i < numbers.length; i++) {
System.out.println("Element at index " + i + ": " + numbers[i]);
}
}
}
B. Multidimensional Arrays
Syntax:
dataType[][] arrayName = new dataType[rows][columns];
Example:
public class MultiDimensionalArray {
public static void main(String[] args) {
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Accessing elements
System.out.println("Element at (1, 1): " + matrix[1][1]); // Outputs 5
// Iterating through the matrix
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
}
}
C. Common Array Operations
1. Sorting
Use Arrays.sort()
to sort an array.
Example:
import java.util.Arrays;
public class ArraySort {
public static void main(String[] args) {
int[] numbers = {5, 3, 8, 1, 2};
Arrays.sort(numbers);
System.out.println("Sorted array: " + Arrays.toString(numbers));
}
}
2. Searching
Use Arrays.binarySearch()
to search in a sorted array.
Example:
import java.util.Arrays;
public class ArraySearch {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};
int index = Arrays.binarySearch(numbers, 3);
System.out.println("Element 3 found at index: " + index);
}
}
2. Strings in Java
A. String Basics
Declaration and Initialization:
String str1 = "Hello";
String str2 = new String("World");
String Methods:
length()
: Returns the length of the string.charAt()
: Returns the character at a specific index.substring()
: Extracts a portion of the string.toUpperCase()
/toLowerCase()
: Converts the string to upper/lower case.
Example:
public class StringMethods {
public static void main(String[] args) {
String str = "Hello, World!";
System.out.println("Length: " + str.length());
System.out.println("Character at index 1: " + str.charAt(1));
System.out.println("Substring (0, 5): " + str.substring(0, 5));
System.out.println("Uppercase: " + str.toUpperCase());
}
}
B. StringBuilder and StringBuffer
StringBuilder:
Used for mutable strings (faster, not thread-safe).
Example:
public class StringBuilderExample {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
sb.append(", World!");
System.out.println(sb.toString());
}
}
StringBuffer:
Similar to StringBuilder
, but thread-safe.
Example:
public class StringBufferExample {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello");
sb.append(", World!");
System.out.println(sb.toString());
}
}
C. Regular Expressions for String Manipulation
Using the Pattern
and Matcher
Classes:
Find Patterns:
import java.util.regex.*; public class RegexExample { public static void main(String[] args) { String text = "The rain in Spain"; String regex = "rain"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(text); while (matcher.find()) { System.out.println("Found: " + matcher.group() + " at index " + matcher.start()); } } }
Replace Patterns:
public class RegexReplace { public static void main(String[] args) { String text = "123-456-7890"; String formatted = text.replaceAll("-", " "); System.out.println("Formatted number: " + formatted); } }
3. Practical Exercises
Exercise 1: Reverse an Array
Write a program to reverse an array.
Solution:
public class ReverseArray {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
for (int i = arr.length - 1; i >= 0; i--) {
System.out.print(arr[i] + " ");
}
}
}
Exercise 2: Count Vowels in a String
Write a program to count the number of vowels in a given string.
Solution:
public class VowelCount {
public static void main(String[] args) {
String str = "Hello, World!";
int count = 0;
for (char c : str.toLowerCase().toCharArray()) {
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
count++;
}
}
System.out.println("Number of vowels: " + count);
}
}
Exercise 3: Palindrome Checker
Write a program to check if a string is a palindrome.
Solution:
public class PalindromeChecker {
public static void main(String[] args) {
String str = "madam";
String reversed = new StringBuilder(str).reverse().toString();
if (str.equals(reversed)) {
System.out.println(str + " is a palindrome.");
} else {
System.out.println(str + " is not a palindrome.");
}
}
}
4. Summary
Key Takeaways:
- Arrays:
- Store collections of similar data types.
- Perform operations like sorting and searching using built-in methods.
- Strings:
- Immutable by default.
- Use
StringBuilder
orStringBuffer
for mutable strings.
- Regular Expressions:
- Useful for pattern matching and string manipulation.
Module 5: Object-Oriented Programming (OOP) Basics
Objective: Learn the foundational principles of Object-Oriented Programming (OOP) in Java, including working with classes, objects, encapsulation, inheritance, and polymorphism.
1. Classes and Objects
A. What are Classes and Objects?
- Class: A blueprint for creating objects. It defines properties (fields) and behaviors (methods).
- Object: An instance of a class.
B. Syntax
class ClassName {
// Fields (attributes)
int attribute;
// Methods (behaviors)
void methodName() {
// Method implementation
}
}
C. Example
class Car {
String brand;
int speed;
void display() {
System.out.println("Brand: " + brand + ", Speed: " + speed);
}
}
public class Main {
public static void main(String[] args) {
Car car = new Car(); // Create an object of Car
car.brand = "Toyota";
car.speed = 120;
car.display();
}
}
2. Constructors
A. What is a Constructor?
- A constructor is a special method used to initialize objects.
- It has the same name as the class and no return type.
B. Types of Constructors
Default Constructor:
- Automatically provided if no constructor is defined.
class Person { String name; Person() { // Default constructor name = "Default Name"; } }
Parameterized Constructor:
- Used to pass initial values to fields.
class Person { String name; Person(String name) { // Parameterized constructor this.name = name; } }
C. Example
class Person {
String name;
// Default Constructor
Person() {
name = "Unknown";
}
// Parameterized Constructor
Person(String name) {
this.name = name;
}
void display() {
System.out.println("Name: " + name);
}
}
public class Main {
public static void main(String[] args) {
Person person1 = new Person(); // Default constructor
person1.display();
Person person2 = new Person("Alice"); // Parameterized constructor
person2.display();
}
}
3. The this
Keyword
- Refers to the current instance of the class.
- Used to resolve naming conflicts between instance variables and method parameters.
Example
class Rectangle {
int width, height;
Rectangle(int width, int height) {
this.width = width; // Resolving variable conflict
this.height = height;
}
int calculateArea() {
return this.width * this.height;
}
}
4. Encapsulation
- Encapsulation is the concept of restricting direct access to certain fields and methods of a class.
- Achieved using private fields and public getters and setters.
A. Example
class BankAccount {
private double balance; // Private field
// Getter
public double getBalance() {
return balance;
}
// Setter
public void setBalance(double balance) {
if (balance >= 0) {
this.balance = balance;
} else {
System.out.println("Invalid balance!");
}
}
}
public class Main {
public static void main(String[] args) {
BankAccount account = new BankAccount();
account.setBalance(1000.50); // Setting value using setter
System.out.println("Balance: " + account.getBalance()); // Accessing value using getter
}
}
5. Inheritance
Inheritance allows a class to inherit properties and methods from another class.
A. Syntax
class ParentClass {
// Fields and methods
}
class ChildClass extends ParentClass {
// Additional fields and methods
}
B. Example
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}
class Dog extends Animal {
void bark() {
System.out.println("The dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Inherited method
dog.bark(); // Child class method
}
}
C. super
Keyword
- Refers to the parent class.
- Used to access parent class methods or constructors.
Example:
class Animal {
Animal() {
System.out.println("Animal Constructor");
}
}
class Dog extends Animal {
Dog() {
super(); // Calls the parent class constructor
System.out.println("Dog Constructor");
}
}
6. Polymorphism
Polymorphism allows methods to perform different behaviors based on the object calling them.
A. Method Overloading
- Same method name with different parameter lists.
Example:
class Calculator {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(5, 10)); // Calls int version
System.out.println(calc.add(5.5, 10.5)); // Calls double version
}
}
B. Method Overriding
- A child class provides its own implementation of a method from the parent class.
Example:
class Animal {
void sound() {
System.out.println("Animal makes a sound.");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog(); // Dynamic method dispatch
myDog.sound(); // Calls Dog's version of sound()
}
}
C. Dynamic Method Dispatch
- A reference of a parent class points to a child class object, and method calls are resolved at runtime.
Example:
Animal animal = new Dog(); // Parent reference, child object
animal.sound(); // Calls Dog's overridden method
7. Practical Exercises
Exercise 1: Create a Student Class
Write a program to create a Student
class with fields name
, rollNumber
, and marks
. Use constructors, getters, and setters.
Exercise 2: Bank Account Inheritance
Create a base Account
class with fields like accountNumber
and balance
. Extend it with a SavingsAccount
class to add interest calculation.
Exercise 3: Calculator with Overloading
Write a program to demonstrate method overloading in a calculator class (e.g., add
, subtract
for different data types).
8. Summary
Key Takeaways:
- Classes and Objects: Understand the relationship between classes (blueprints) and objects (instances).
- Constructors: Use default and parameterized constructors to initialize objects.
- Encapsulation: Protect data using private fields and public getters/setters.
- Inheritance: Reuse code and extend functionality with
extends
and thesuper
keyword. - Polymorphism:
- Overloading: Same method, different parameters.
- Overriding: Redefine parent class methods in the child class.
Module 6: Exception Handling
Objective: Learn how to handle runtime errors gracefully in Java using exception handling techniques, including working with checked and unchecked exceptions, try-catch-finally blocks, throwing exceptions, and creating custom exceptions.
1. What is Exception Handling?
- An exception is an event that disrupts the normal flow of a program.
- Exception handling allows you to manage these events and prevent your program from crashing.
2. Types of Exceptions
A. Checked Exceptions
- Checked at compile-time.
- Must be either caught or declared in the method signature using
throws
. - Examples:
IOException
SQLException
B. Unchecked Exceptions
- Occur at runtime and are not checked at compile-time.
- Extend the
RuntimeException
class. - Examples:
ArithmeticException
NullPointerException
3. Try-Catch-Finally Blocks
A. Try-Catch Block
Used to catch exceptions and handle them.
Syntax:
try {
// Code that may throw an exception
} catch (ExceptionType e) {
// Code to handle the exception
}
Example:
public class TryCatchExample {
public static void main(String[] args) {
try {
int result = 10 / 0; // This will throw ArithmeticException
} catch (ArithmeticException e) {
System.out.println("Error: Division by zero is not allowed.");
}
}
}
B. Finally Block
The finally
block is always executed, regardless of whether an exception occurred or not.
Syntax:
try {
// Code that may throw an exception
} catch (ExceptionType e) {
// Code to handle the exception
} finally {
// Code that will always execute
}
Example:
public class FinallyExample {
public static void main(String[] args) {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[5]); // This will throw ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Error: Array index out of bounds.");
} finally {
System.out.println("This block always executes.");
}
}
}
4. Throwing Exceptions with throw
- Use
throw
to explicitly throw an exception.
Syntax:
throw new ExceptionType("Error message");
Example:
public class ThrowExample {
public static void main(String[] args) {
try {
validateAge(15);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
public static void validateAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("Age must be at least 18.");
}
}
}
5. Custom Exceptions
- You can create your own exception classes by extending the
Exception
class orRuntimeException
.
Example: Creating a Custom Exception
class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}
public class CustomExceptionExample {
public static void main(String[] args) {
try {
withdraw(500, 300);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}
}
public static void withdraw(int balance, int amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Insufficient funds for withdrawal.");
}
System.out.println("Withdrawal successful.");
}
}
6. Practical Exercises
Exercise 1: Handle Division by Zero
Write a program to take two integers as input and handle the division by zero exception.
Solution:
import java.util.Scanner;
public class Division {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
System.out.print("Enter numerator: ");
int numerator = scanner.nextInt();
System.out.print("Enter denominator: ");
int denominator = scanner.nextInt();
int result = numerator / denominator;
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Error: Division by zero is not allowed.");
}
}
}
Exercise 2: Validate User Input
Write a program to validate user input. If the input is negative, throw an exception.
Solution:
import java.util.Scanner;
public class ValidateInput {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
System.out.print("Enter a positive number: ");
int number = scanner.nextInt();
if (number < 0) {
throw new IllegalArgumentException("Number must be positive.");
}
System.out.println("You entered: " + number);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
Exercise 3: File Not Found
Write a program to handle a FileNotFoundException
.
Solution:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileRead {
public static void main(String[] args) {
try {
File file = new File("nonexistentfile.txt");
Scanner scanner = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.println("Error: File not found.");
}
}
}
7. Summary
Key Takeaways:
- Checked vs Unchecked Exceptions:
- Checked exceptions are compile-time errors (e.g.,
IOException
). - Unchecked exceptions occur at runtime (e.g.,
ArithmeticException
).
- Checked exceptions are compile-time errors (e.g.,
- Try-Catch-Finally:
- Use
try
to write code that may throw an exception. - Use
catch
to handle exceptions. - Use
finally
for cleanup operations.
- Use
- Throw and Custom Exceptions:
- Use
throw
to manually throw exceptions. - Create custom exceptions by extending
Exception
orRuntimeException
.
- Use
Module 7: Java Collections Framework
Objective: Learn how to use Java’s built-in data structures to efficiently manage and manipulate collections of data.
1. Introduction to Collections
- The Java Collections Framework (JCF) provides a set of classes and interfaces to store and manipulate groups of objects.
- It includes Lists, Sets, Maps, and Queues.
Key Interfaces in the Collections Framework
Interface | Description |
---|---|
List | An ordered collection of elements that allows duplicates. |
Set | A collection that does not allow duplicate elements. |
Map | A collection of key-value pairs with unique keys. |
Queue | A collection that represents a queue (FIFO). |
2. List
- A List is an ordered collection that allows duplicate elements.
- Common implementations:
ArrayList
: Uses a dynamic array.LinkedList
: Uses a doubly-linked list.
A. ArrayList
Example:
import java.util.ArrayList;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
// Adding elements
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// Accessing elements
System.out.println("First name: " + names.get(0));
// Iterating
for (String name : names) {
System.out.println(name);
}
// Removing elements
names.remove("Bob");
System.out.println("After removal: " + names);
}
}
B. LinkedList
Example:
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
LinkedList<Integer> numbers = new LinkedList<>();
// Adding elements
numbers.add(10);
numbers.add(20);
numbers.addFirst(5); // Adds 5 at the beginning
// Accessing elements
System.out.println("First element: " + numbers.getFirst());
// Removing elements
numbers.removeLast();
System.out.println("After removal: " + numbers);
}
}
3. Set
- A Set is a collection that does not allow duplicate elements.
- Common implementations:
HashSet
: Unordered, does not maintain insertion order.TreeSet
: Sorted in natural order.
A. HashSet
Example:
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> cities = new HashSet<>();
// Adding elements
cities.add("New York");
cities.add("Los Angeles");
cities.add("Chicago");
cities.add("New York"); // Duplicate, will not be added
// Iterating
for (String city : cities) {
System.out.println(city);
}
}
}
B. TreeSet
Example:
import java.util.TreeSet;
public class TreeSetExample {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
// Adding elements
numbers.add(50);
numbers.add(10);
numbers.add(30);
// Displaying sorted elements
System.out.println("Sorted Set: " + numbers);
}
}
4. Map
- A Map is a collection of key-value pairs.
- Common implementations:
HashMap
: Unordered, allows one null key.TreeMap
: Sorted by keys.
A. HashMap
Example:
import java.util.HashMap;
public class HashMapExample {
public static void main(String[] args) {
HashMap<String, Integer> ages = new HashMap<>();
// Adding key-value pairs
ages.put("Alice", 25);
ages.put("Bob", 30);
ages.put("Charlie", 35);
// Accessing values
System.out.println("Bob's age: " + ages.get("Bob"));
// Iterating
for (String name : ages.keySet()) {
System.out.println(name + ": " + ages.get(name));
}
}
}
B. TreeMap
Example:
import java.util.TreeMap;
public class TreeMapExample {
public static void main(String[] args) {
TreeMap<String, Integer> scores = new TreeMap<>();
// Adding key-value pairs
scores.put("Math", 90);
scores.put("English", 85);
scores.put("Science", 95);
// Displaying sorted keys
for (String subject : scores.keySet()) {
System.out.println(subject + ": " + scores.get(subject));
}
}
}
5. Iterators and Enhanced For Loops
A. Iterators
- Used to traverse collections.
- Provides methods like
hasNext()
andnext()
.
Example:
import java.util.ArrayList;
import java.util.Iterator;
public class IteratorExample {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
B. Enhanced For Loop
- A simpler way to iterate over collections.
Example:
import java.util.ArrayList;
public class EnhancedForLoopExample {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
for (int num : numbers) {
System.out.println(num);
}
}
}
6. Practical Exercises
Exercise 1: Remove Duplicates from a List
Write a program to remove duplicate elements from a list using a HashSet
.
Solution:
import java.util.ArrayList;
import java.util.HashSet;
public class RemoveDuplicates {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(2);
numbers.add(3);
HashSet<Integer> uniqueNumbers = new HashSet<>(numbers);
System.out.println("Unique numbers: " + uniqueNumbers);
}
}
Exercise 2: Count Word Frequency
Write a program to count the frequency of words in a given text using a HashMap
.
Solution:
import java.util.HashMap;
public class WordFrequency {
public static void main(String[] args) {
String text = "apple banana apple orange banana apple";
HashMap<String, Integer> wordCount = new HashMap<>();
for (String word : text.split(" ")) {
wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
}
System.out.println("Word Frequency: " + wordCount);
}
}
7. Summary
Key Takeaways:
- Lists:
- Use
ArrayList
for dynamic arrays. - Use
LinkedList
for frequent insertions/deletions.
- Use
- Sets:
- Use
HashSet
for unique elements. - Use
TreeSet
for sorted unique elements.
- Use
- Maps:
- Use
HashMap
for key-value pairs without order. - Use
TreeMap
for sorted key-value pairs.
- Use
- Iterators and Enhanced For Loops:
- Simplify traversal of collections.
Module 8: File Handling
Objective: Learn how to work with files and directories in Java, including reading, writing, handling file paths, and understanding serialization and deserialization.
1. Basics of File Handling in Java
- The
java.io
package provides classes for file handling. - Common Classes:
File
: Represents file and directory paths.FileReader
andFileWriter
: For reading and writing text files.BufferedReader
andBufferedWriter
: For efficient reading and writing.
2. Reading and Writing to Files
A. Writing to a File with FileWriter
Example:
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterExample {
public static void main(String[] args) {
try {
FileWriter writer = new FileWriter("example.txt");
writer.write("Hello, World!\n");
writer.write("Welcome to Java File Handling.");
writer.close();
System.out.println("File written successfully.");
} catch (IOException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
}
B. Reading from a File with FileReader
Example:
import java.io.FileReader;
import java.io.IOException;
public class FileReaderExample {
public static void main(String[] args) {
try {
FileReader reader = new FileReader("example.txt");
int character;
while ((character = reader.read()) != -1) {
System.out.print((char) character);
}
reader.close();
} catch (IOException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
}
C. Using BufferedReader
for Efficient Reading
Example:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderExample {
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new FileReader("example.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
} catch (IOException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
}
3. Handling File Paths and Directories
A. Using the File
Class
Creating and Checking Files/Directories:
import java.io.File;
import java.io.IOException;
public class FileExample {
public static void main(String[] args) {
File file = new File("example.txt");
try {
if (file.createNewFile()) {
System.out.println("File created: " + file.getName());
} else {
System.out.println("File already exists.");
}
} catch (IOException e) {
System.out.println("An error occurred: " + e.getMessage());
}
// Check if it's a file or directory
System.out.println("Is file: " + file.isFile());
System.out.println("Is directory: " + file.isDirectory());
}
}
Working with Directories:
import java.io.File;
public class DirectoryExample {
public static void main(String[] args) {
File directory = new File("MyDirectory");
// Create directory
if (directory.mkdir()) {
System.out.println("Directory created: " + directory.getName());
} else {
System.out.println("Directory already exists.");
}
// List files in the directory
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
System.out.println(file.getName());
}
}
}
}
4. Serialization and Deserialization
Serialization is the process of converting an object into a byte stream, while deserialization is the reverse process.
A. Steps to Serialize and Deserialize
- Implement the
Serializable
interface in your class. - Use
ObjectOutputStream
to serialize. - Use
ObjectInputStream
to deserialize.
B. Example: Serialization
Class to Serialize:
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Serialization:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
public class SerializeExample {
public static void main(String[] args) {
Person person = new Person("Alice", 25);
try {
FileOutputStream fileOut = new FileOutputStream("person.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(person);
out.close();
fileOut.close();
System.out.println("Object serialized successfully.");
} catch (IOException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
}
C. Example: Deserialization
Deserialization:
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
public class DeserializeExample {
public static void main(String[] args) {
try {
FileInputStream fileIn = new FileInputStream("person.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
Person person = (Person) in.readObject();
in.close();
fileIn.close();
System.out.println("Deserialized Object:");
System.out.println("Name: " + person.name);
System.out.println("Age: " + person.age);
} catch (IOException | ClassNotFoundException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
}
5. Practical Exercises
Exercise 1: Count Words in a File
Write a program to count the number of words in a text file.
Exercise 2: File Copy
Write a program to copy the content of one file to another.
Solution:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileCopy {
public static void main(String[] args) {
try {
FileReader reader = new FileReader("source.txt");
FileWriter writer = new FileWriter("destination.txt");
int character;
while ((character = reader.read()) != -1) {
writer.write(character);
}
reader.close();
writer.close();
System.out.println("File copied successfully.");
} catch (IOException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
}
Exercise 3: Directory Explorer
Write a program to list all files and directories in a given directory path.
6. Summary
Key Takeaways:
- Reading and Writing:
- Use
FileReader
andFileWriter
for text files. - Use
BufferedReader
andBufferedWriter
for efficient file handling.
- Use
- File and Directory Management:
- Use the
File
class to create, delete, and check files or directories.
- Use the
- Serialization:
- Use
ObjectOutputStream
andObjectInputStream
to serialize and deserialize objects.
- Use
Module 9: Threads and Multithreading
Objective: Learn how to write concurrent programs in Java using threads and understand thread lifecycle, synchronization, and thread pool management with ExecutorService
.
1. What are Threads and Multithreading?
- A thread is a lightweight process that allows multiple operations to run concurrently.
- Multithreading is the ability of a program to execute multiple threads simultaneously, improving efficiency.
2. Creating Threads in Java
A. Using the Thread
Class
Steps:
- Extend the
Thread
class. - Override the
run()
method. - Call
start()
to begin execution.
Example:
class MyThread extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Thread: " + i);
}
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // Start the thread
}
}
B. Using the Runnable
Interface
Steps:
- Implement the
Runnable
interface. - Override the
run()
method. - Pass the
Runnable
object to aThread
object and callstart()
.
Example:
class MyRunnable implements Runnable {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Runnable Thread: " + i);
}
}
}
public class RunnableExample {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
3. Thread Lifecycle and Methods
A. Thread Lifecycle
- New: Thread object is created but not started.
- Runnable: Thread is ready to run and waiting for CPU time.
- Running: Thread is executing.
- Blocked/Waiting: Thread is waiting for resources or signals.
- Terminated: Thread execution is complete.
B. Common Thread Methods
Method | Description |
---|---|
start() | Starts the thread and invokes the run() method. |
join() | Waits for a thread to finish before proceeding. |
sleep() | Pauses the thread for a specified duration. |
isAlive() | Checks if the thread is still running. |
Example: Using join()
and sleep()
class MyThread extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Thread: " + i);
try {
Thread.sleep(1000); // Pause for 1 second
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
}
}
}
public class ThreadMethodsExample {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
try {
thread.join(); // Main thread waits for MyThread to finish
} catch (InterruptedException e) {
System.out.println("Main thread interrupted");
}
System.out.println("Main thread resumes after MyThread finishes.");
}
}
4. Synchronization and Thread Safety
When multiple threads access shared resources, data inconsistencies can occur. Synchronization ensures that only one thread accesses a resource at a time.
A. Synchronized Methods
Syntax:
synchronized void methodName() {
// Critical section
}
Example:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class SynchronizationExample {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
System.out.println("Final count: " + counter.getCount());
}
}
B. Synchronized Blocks
Example:
class Counter {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public int getCount() {
return count;
}
}
5. Using the ExecutorService for Thread Pools
- The
ExecutorService
framework simplifies thread pool management and execution.
Steps:
- Create an
ExecutorService
usingExecutors
class. - Submit tasks to the thread pool.
- Shutdown the thread pool.
Example:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorServiceExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
Runnable task1 = () -> System.out.println("Task 1 executed by " + Thread.currentThread().getName());
Runnable task2 = () -> System.out.println("Task 2 executed by " + Thread.currentThread().getName());
Runnable task3 = () -> System.out.println("Task 3 executed by " + Thread.currentThread().getName());
executor.submit(task1);
executor.submit(task2);
executor.submit(task3);
executor.shutdown(); // Stop accepting new tasks
}
}
6. Practical Exercises
Exercise 1: Multi-threaded Counter
Create a program with two threads incrementing a shared counter. Ensure thread safety using synchronized
.
Exercise 2: Print Even and Odd Numbers
Write a program with two threads:
- Thread 1 prints even numbers.
- Thread 2 prints odd numbers.
Exercise 3: Task Executor
Create a program using ExecutorService
where multiple threads calculate the factorial of numbers from a list.
7. Summary
Key Takeaways:
- Creating Threads:
- Extend
Thread
or implementRunnable
. - Use
start()
to begin execution.
- Extend
- Thread Methods:
sleep()
,join()
, andisAlive()
manage thread behavior.
- Synchronization:
- Use
synchronized
methods or blocks to ensure thread safety.
- Use
- Thread Pools:
- Use
ExecutorService
to manage thread pools for efficient execution.
- Use
Module 10: Java GUI Development
Objective: Learn how to build graphical user interfaces (GUIs) in Java using Swing, including working with components, handling events, managing layouts, and building a simple GUI application.
1. Introduction to Swing
- Swing is a part of Java’s
javax.swing
package and provides a set of lightweight, platform-independent components for creating GUIs. - Common Swing components:
JFrame
: The main window.JPanel
: A container for other components.JButton
: A clickable button.JTextField
: A text input field.
2. Basic Swing Components
A. Creating a Simple Window
Example:
import javax.swing.*;
public class SimpleWindow {
public static void main(String[] args) {
JFrame frame = new JFrame("My First GUI"); // Create a JFrame
frame.setSize(400, 300); // Set dimensions
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Exit on close
frame.setVisible(true); // Make the window visible
}
}
B. Adding Components to the JFrame
Example:
import javax.swing.*;
public class AddComponents {
public static void main(String[] args) {
JFrame frame = new JFrame("GUI with Components");
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Click Me!"); // Create a button
JTextField textField = new JTextField("Enter text here", 20); // Create a text field
JPanel panel = new JPanel(); // Create a panel
panel.add(button); // Add button to the panel
panel.add(textField); // Add text field to the panel
frame.add(panel); // Add panel to the frame
frame.setVisible(true); // Display the GUI
}
}
3. Event Handling
- Event handling is how a program responds to user interactions like button clicks or typing in a text field.
- Key Classes and Interfaces:
ActionListener
: Listens for actions like button clicks.KeyListener
: Listens for key presses.
A. Handling Button Clicks with ActionListener
Example:
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ButtonClickExample {
public static void main(String[] args) {
JFrame frame = new JFrame("Button Click Example");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Click Me");
JLabel label = new JLabel("Button not clicked");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setText("Button clicked!");
}
});
JPanel panel = new JPanel();
panel.add(button);
panel.add(label);
frame.add(panel);
frame.setVisible(true);
}
}
4. Layout Managers
- Layout managers control how components are arranged in a container.
- Common Layout Managers:
FlowLayout
: Arranges components in a row.BorderLayout
: Divides the container into regions (North, South, East, West, Center).GridLayout
: Arranges components in a grid.
A. FlowLayout
Example:
import javax.swing.*;
import java.awt.*;
public class FlowLayoutExample {
public static void main(String[] args) {
JFrame frame = new JFrame("FlowLayout Example");
frame.setSize(400, 200);
JPanel panel = new JPanel(new FlowLayout());
panel.add(new JButton("Button 1"));
panel.add(new JButton("Button 2"));
panel.add(new JButton("Button 3"));
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
B. BorderLayout
Example:
import javax.swing.*;
import java.awt.*;
public class BorderLayoutExample {
public static void main(String[] args) {
JFrame frame = new JFrame("BorderLayout Example");
frame.setSize(400, 200);
frame.setLayout(new BorderLayout());
frame.add(new JButton("North"), BorderLayout.NORTH);
frame.add(new JButton("South"), BorderLayout.SOUTH);
frame.add(new JButton("East"), BorderLayout.EAST);
frame.add(new JButton("West"), BorderLayout.WEST);
frame.add(new JButton("Center"), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
C. GridLayout
Example:
import javax.swing.*;
import java.awt.*;
public class GridLayoutExample {
public static void main(String[] args) {
JFrame frame = new JFrame("GridLayout Example");
frame.setSize(400, 200);
JPanel panel = new JPanel(new GridLayout(2, 3)); // 2 rows, 3 columns
panel.add(new JButton("Button 1"));
panel.add(new JButton("Button 2"));
panel.add(new JButton("Button 3"));
panel.add(new JButton("Button 4"));
panel.add(new JButton("Button 5"));
panel.add(new JButton("Button 6"));
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
5. Building a Simple GUI Application
Example: A Basic Calculator
Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SimpleCalculator {
public static void main(String[] args) {
JFrame frame = new JFrame("Simple Calculator");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label1 = new JLabel("Number 1:");
JLabel label2 = new JLabel("Number 2:");
JLabel resultLabel = new JLabel("Result: ");
JTextField num1Field = new JTextField(10);
JTextField num2Field = new JTextField(10);
JButton addButton = new JButton("Add");
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(4, 2));
panel.add(label1);
panel.add(num1Field);
panel.add(label2);
panel.add(num2Field);
panel.add(new JLabel()); // Empty cell
panel.add(addButton);
panel.add(resultLabel);
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
int num1 = Integer.parseInt(num1Field.getText());
int num2 = Integer.parseInt(num2Field.getText());
resultLabel.setText("Result: " + (num1 + num2));
} catch (NumberFormatException ex) {
resultLabel.setText("Invalid input!");
}
}
});
frame.add(panel);
frame.setVisible(true);
}
}
6. Practical Exercises
Exercise 1: Login Form
Build a GUI for a login form with fields for username and password and a login button.
Exercise 2: To-Do List
Create a simple to-do list app where users can add tasks and mark them as completed.
Exercise 3: Temperature Converter
Build a GUI to convert temperatures between Celsius and Fahrenheit.
7. Summary
Key Takeaways:
- Swing Components:
- Use
JFrame
,JPanel
,JButton
, and other components to build interfaces.
- Use
- Event Handling:
- Use
ActionListener
to handle user interactions like button clicks.
- Use
- Layout Managers:
- Use
FlowLayout
,BorderLayout
, orGridLayout
to arrange components.
- Use
- Building Applications:
- Combine components, event handling, and layout managers to create functional GUIs.
Module 11: Database Connectivity
Objective: Learn how to connect Java applications to databases using JDBC, set up a database, and perform CRUD operations (Create, Read, Update, Delete) securely with prepared statements and parameterized queries.
1. Introduction to JDBC (Java Database Connectivity)
- JDBC is a Java API that allows you to interact with databases.
- It provides methods to connect to a database, execute SQL queries, and process results.
Key Classes in JDBC
Class/Interface | Description |
---|---|
DriverManager | Manages database connections. |
Connection | Represents a connection to the database. |
Statement | Used to execute SQL queries. |
PreparedStatement | Used for parameterized queries (prevents SQL injection). |
ResultSet | Holds the result of a query. |
2. Setting Up a Database
A. Install MySQL or SQLite
- Install a database system like MySQL or use a lightweight database like SQLite.
- Create a sample database for testing (e.g.,
testdb
) and a table (e.g.,users
).
SQL to Create a Sample Table
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(50),
age INT
);
B. Add JDBC Driver to Your Project
- MySQL: Download the MySQL Connector JAR file and add it to your project’s classpath.
- SQLite: Download the SQLite JDBC driver JAR file.
3. Establishing a Database Connection
A. MySQL Example
Code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/testdb"; // Replace with your database name
String user = "root"; // Replace with your username
String password = "password"; // Replace with your password
try (Connection connection = DriverManager.getConnection(url, user, password)) {
System.out.println("Connected to the database successfully!");
} catch (SQLException e) {
System.out.println("Connection failed: " + e.getMessage());
}
}
}
B. SQLite Example
Code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class SQLiteConnection {
public static void main(String[] args) {
String url = "jdbc:sqlite:testdb.db"; // SQLite database file
try (Connection connection = DriverManager.getConnection(url)) {
System.out.println("Connected to the SQLite database successfully!");
} catch (SQLException e) {
System.out.println("Connection failed: " + e.getMessage());
}
}
}
4. Performing CRUD Operations
A. Insert Data (Create)
Code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class InsertData {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/testdb";
String user = "root";
String password = "password";
String query = "INSERT INTO users (name, email, age) VALUES (?, ?, ?)";
try (Connection connection = DriverManager.getConnection(url, user, password);
PreparedStatement statement = connection.prepareStatement(query)) {
statement.setString(1, "Alice");
statement.setString(2, "[email protected]");
statement.setInt(3, 25);
int rowsInserted = statement.executeUpdate();
System.out.println(rowsInserted + " row(s) inserted.");
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
B. Retrieve Data (Read)
Code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class RetrieveData {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/testdb";
String user = "root";
String password = "password";
String query = "SELECT * FROM users";
try (Connection connection = DriverManager.getConnection(url, user, password);
PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
System.out.println("ID: " + resultSet.getInt("id"));
System.out.println("Name: " + resultSet.getString("name"));
System.out.println("Email: " + resultSet.getString("email"));
System.out.println("Age: " + resultSet.getInt("age"));
System.out.println("-------------------");
}
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
C. Update Data
Code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class UpdateData {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/testdb";
String user = "root";
String password = "password";
String query = "UPDATE users SET age = ? WHERE name = ?";
try (Connection connection = DriverManager.getConnection(url, user, password);
PreparedStatement statement = connection.prepareStatement(query)) {
statement.setInt(1, 30);
statement.setString(2, "Alice");
int rowsUpdated = statement.executeUpdate();
System.out.println(rowsUpdated + " row(s) updated.");
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
D. Delete Data
Code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class DeleteData {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/testdb";
String user = "root";
String password = "password";
String query = "DELETE FROM users WHERE name = ?";
try (Connection connection = DriverManager.getConnection(url, user, password);
PreparedStatement statement = connection.prepareStatement(query)) {
statement.setString(1, "Alice");
int rowsDeleted = statement.executeUpdate();
System.out.println(rowsDeleted + " row(s) deleted.");
} catch (SQLException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
5. Prepared Statements and Parameterized Queries
- Use Prepared Statements for:
- Preventing SQL Injection.
- Improved performance for repetitive queries.
Example:
String query = "SELECT * FROM users WHERE age > ?";
PreparedStatement statement = connection.prepareStatement(query);
statement.setInt(1, 20);
6. Practical Exercises
Exercise 1: User Registration
Create a program where users can register their name, email, and age in a database.
Exercise 2: Search by Email
Create a program to search for a user by their email address and display their details.
Exercise 3: CRUD Application
Build a Java console application that allows users to perform all CRUD operations on a database table.
7. Summary
Key Takeaways:
- JDBC Basics:
- Use
DriverManager
to connect to a database. - Use
PreparedStatement
for secure and parameterized queries.
- Use
- CRUD Operations:
- Perform insert, retrieve, update, and delete operations with SQL queries.
- Best Practices:
- Use try-with-resources to manage connections and statements.
- Always validate user inputs to prevent errors.
Module 12: Java Networking
Objective: Learn how to build networked applications in Java, including using sockets, writing client-server programs, handling HTTP requests and responses, and working with REST APIs.
1. Introduction to Sockets
- A socket is an endpoint for communication between two machines.
- Sockets use the TCP/IP protocol to establish connections and exchange data.
- Java provides the following classes for networking:
Socket
: Used for client-side connections.ServerSocket
: Used for server-side connections.
2. Writing a Simple Client-Server Program
A. Server Program
The server listens for incoming connections on a specific port and responds to the client.
Code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleServer {
public static void main(String[] args) {
int port = 1234;
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server is listening on port " + port);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("New client connected");
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
writer.println("Hello, client!");
socket.close();
}
} catch (IOException e) {
System.out.println("Server error: " + e.getMessage());
}
}
}
B. Client Program
The client connects to the server and reads the response.
Code:
import java.io.*;
import java.net.Socket;
public class SimpleClient {
public static void main(String[] args) {
String hostname = "localhost";
int port = 1234;
try (Socket socket = new Socket(hostname, port)) {
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String serverMessage = reader.readLine();
System.out.println("Server says: " + serverMessage);
} catch (IOException e) {
System.out.println("Client error: " + e.getMessage());
}
}
}
3. HTTP Requests and Responses
To handle HTTP requests, Java provides the HttpURLConnection
class in the java.net
package. This class is used to send GET and POST requests.
A. Sending a GET Request
Code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpGetExample {
public static void main(String[] args) {
String urlString = "https://jsonplaceholder.typicode.com/posts/1";
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}
} catch (Exception e) {
System.out.println("HTTP GET error: " + e.getMessage());
}
}
}
B. Sending a POST Request
Code:
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpPostExample {
public static void main(String[] args) {
String urlString = "https://jsonplaceholder.typicode.com/posts";
String jsonData = "{ \"title\": \"foo\", \"body\": \"bar\", \"userId\": 1 }";
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; utf-8");
connection.setRequestProperty("Accept", "application/json");
connection.setDoOutput(true);
try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonData.getBytes("utf-8");
os.write(input, 0, input.length);
}
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
} catch (Exception e) {
System.out.println("HTTP POST error: " + e.getMessage());
}
}
}
4. Working with REST APIs
REST APIs allow interaction with external services or applications over HTTP. Use the HttpClient
class introduced in Java 11 for modern and efficient HTTP communication.
A. Fetching Data from a REST API
Code:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class RestApiExample {
public static void main(String[] args) {
String url = "https://jsonplaceholder.typicode.com/posts/1";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.GET()
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Response Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
B. Sending Data to a REST API
Code:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest.BodyPublishers;
public class RestApiPostExample {
public static void main(String[] args) {
String url = "https://jsonplaceholder.typicode.com/posts";
String jsonData = "{ \"title\": \"foo\", \"body\": \"bar\", \"userId\": 1 }";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.POST(BodyPublishers.ofString(jsonData))
.header("Content-Type", "application/json")
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Response Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
5. Practical Exercises
Exercise 1: Chat Application
Build a simple chat application using sockets, where a server can handle messages from multiple clients.
Exercise 2: Fetch Weather Data
Create a Java program that fetches weather data from a public REST API and displays it.
Exercise 3: Task Manager
Create a client-server program where clients can add, view, and delete tasks stored on the server.
6. Summary
Key Takeaways:
- Sockets:
- Use
ServerSocket
for the server andSocket
for the client.
- Use
- HTTP Communication:
- Use
HttpURLConnection
for HTTP requests and responses. - Use
HttpClient
for modern REST API communication.
- Use
- REST APIs:
- Work with external services by sending GET/POST requests and parsing responses.
Module 13: Functional Programming in Java
Objective: Explore functional programming features in Java, including lambda expressions, functional interfaces, the Streams API, and method references.
1. Introduction to Functional Programming in Java
Functional programming is a programming paradigm where you build software by composing pure functions, avoiding shared state and mutable data. Java introduced functional programming features in Java 8, allowing for a more concise and declarative coding style.
Key Concepts:
- Lambda Expressions: Anonymous functions that can be treated as objects.
- Functional Interfaces: Interfaces with a single abstract method, which can be implemented using lambda expressions.
- Streams API: Provides a high-level abstraction for processing sequences of elements.
- Method References: Shortcuts for writing lambda expressions by referring to existing methods.
2. Lambda Expressions
A. What is a Lambda Expression?
A lambda expression is a concise way to represent an anonymous function (a function without a name) that can be passed around as an object.
B. Syntax
(parameters) -> expression
// Or with multiple statements:
(parameters) -> { statements; }
C. Examples
1. No Parameters
Runnable r = () -> System.out.println("Hello, Lambda!");
r.run(); // Outputs: Hello, Lambda!
2. Single Parameter
Consumer<String> printer = message -> System.out.println(message);
printer.accept("Hello, World!"); // Outputs: Hello, World!
3. Multiple Parameters
BiFunction<Integer, Integer, Integer> adder = (a, b) -> a + b;
int result = adder.apply(5, 3); // result = 8
4. With Type Declarations
BiFunction<Integer, Integer, Integer> multiplier = (Integer a, Integer b) -> a * b;
int product = multiplier.apply(4, 6); // product = 24
3. Functional Interfaces
A. What is a Functional Interface?
- An interface with exactly one abstract method.
- Used as the assignment target for lambda expressions or method references.
- Annotated with
@FunctionalInterface
(optional but recommended).
B. Common Functional Interfaces
Located in java.util.function
package.
1. Predicate<T>
Represents a boolean-valued function of one argument.
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Example:
Predicate<Integer> isEven = n -> n % 2 == 0;
boolean check = isEven.test(4); // true
2. Consumer<T>
Represents an operation that accepts a single input argument and returns no result.
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
Example:
Consumer<String> greeter = name -> System.out.println("Hello, " + name);
greeter.accept("Alice"); // Outputs: Hello, Alice
3. Supplier<T>
Represents a supplier of results; takes no arguments but returns a result.
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Example:
Supplier<Double> randomValue = () -> Math.random();
double value = randomValue.get(); // Generates a random number
4. Function<T, R>
Represents a function that accepts one argument and produces a result.
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
Example:
Function<String, Integer> stringLength = s -> s.length();
int length = stringLength.apply("Lambda"); // length = 6
4. Streams API
A. What is the Streams API?
- Introduced in Java 8.
- Provides a declarative way to process sequences of elements.
- Supports operations like filtering, mapping, and reducing.
B. Stream Operations
- Intermediate Operations: Return a new stream (e.g.,
filter()
,map()
,sorted()
). - Terminal Operations: Produce a result or side-effect (e.g.,
collect()
,forEach()
,reduce()
).
C. Example Data
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
D. Filtering
Use filter()
to select elements based on a condition.
Example:
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
System.out.println(filteredNames); // Outputs: [Alice]
E. Mapping
Use map()
to transform each element.
Example:
List<Integer> nameLengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println(nameLengths); // Outputs: [5, 3, 7, 5, 3]
F. Reducing
Use reduce()
to combine elements into a single result.
Example:
Optional<String> longestName = names.stream()
.reduce((name1, name2) -> name1.length() > name2.length() ? name1 : name2);
longestName.ifPresent(System.out::println); // Outputs: Charlie
G. Combining Operations
Example:
List<String> sortedNames = names.stream()
.filter(name -> name.length() > 3)
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNames); // Outputs: [ALICE, CHARLIE, DAVID]
5. Method References
A. What is a Method Reference?
- A shorthand notation of a lambda expression to call a method.
- Uses the
::
operator.
B. Types of Method References
Reference to a Static Method
ClassName::staticMethodName
Example:
Consumer<String> printer = System.out::println; printer.accept("Hello, Method Reference!"); // Outputs: Hello, Method Reference!
Reference to an Instance Method of a Particular Object
instance::instanceMethodName
Example:
String prefix = "Hello, "; Function<String, String> greeter = prefix::concat; System.out.println(greeter.apply("World")); // Outputs: Hello, World
Reference to an Instance Method of an Arbitrary Object of a Particular Type
ClassName::instanceMethodName
Example:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); names.forEach(System.out::println);
Reference to a Constructor
ClassName::new
Example:
Supplier<List<String>> listSupplier = ArrayList::new; List<String> newList = listSupplier.get();
6. Practical Exercises
Exercise 1: Filtering and Printing Even Numbers
Given a list of integers, use the Streams API to filter out the even numbers and print them.
Solution:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println); // Outputs: 2, 4, 6
Exercise 2: Mapping to Uppercase
Given a list of strings, convert all strings to uppercase using the Streams API.
Solution:
List<String> words = Arrays.asList("java", "lambda", "stream");
List<String> uppercaseWords = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(uppercaseWords); // Outputs: [JAVA, LAMBDA, STREAM]
Exercise 3: Calculating the Sum of Squares
Given a list of integers, calculate the sum of their squares using map()
and reduce()
.
Solution:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sumOfSquares = numbers.stream()
.map(n -> n * n)
.reduce(0, Integer::sum);
System.out.println("Sum of squares: " + sumOfSquares); // Outputs: Sum of squares: 30
Exercise 4: Using Custom Functional Interface
Create a custom functional interface TriFunction
that takes three arguments and returns a result. Use a lambda expression to implement it.
Solution:
@FunctionalInterface
interface TriFunction<A, B, C, R> {
R apply(A a, B b, C c);
}
// Usage
TriFunction<Integer, Integer, Integer, Integer> addThreeNumbers = (a, b, c) -> a + b + c;
int result = addThreeNumbers.apply(10, 20, 30); // result = 60
System.out.println("Result: " + result);
7. Summary
Key Takeaways:
Lambda Expressions:
- Provide a concise way to implement functional interfaces.
- Syntax:
(parameters) -> expression
or(parameters) -> { statements; }
.
Functional Interfaces:
- Interfaces with a single abstract method.
- Common ones include
Predicate
,Consumer
,Supplier
,Function
.
Streams API:
- Offers a powerful way to process collections.
- Supports operations like
filter()
,map()
,reduce()
.
Method References:
- Shorthand for lambda expressions that call existing methods.
- Types include references to static methods, instance methods, and constructors.
Module 14: Advanced Topics
Objective: Explore advanced Java concepts, including generics, annotations, the reflection API, and an introduction to JVM internals.
1. Generics
Generics allow you to write type-safe code by enabling classes, interfaces, and methods to operate on types specified by the programmer.
A. Generic Classes
A generic class allows you to specify a data type when the class is instantiated.
Syntax:
class GenericClass<T> {
private T data;
public GenericClass(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
Example:
public class GenericsExample {
public static void main(String[] args) {
GenericClass<String> stringBox = new GenericClass<>("Hello, Generics");
System.out.println(stringBox.getData()); // Outputs: Hello, Generics
GenericClass<Integer> intBox = new GenericClass<>(123);
System.out.println(intBox.getData()); // Outputs: 123
}
}
B. Generic Methods
A generic method allows you to define a method with a type parameter.
Syntax:
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
Example:
public class GenericMethodExample {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
public static void main(String[] args) {
String[] words = {"Java", "Generics", "Example"};
Integer[] numbers = {1, 2, 3, 4};
printArray(words);
printArray(numbers);
}
}
C. Wildcards
?
: Represents an unknown type.- Use cases:
- Unbounded Wildcards (
?
): Accepts any type. - Bounded Wildcards (
? extends Type
): Accepts a specific type or its subtypes. - Lower Bounded Wildcards (
? super Type
): Accepts a specific type or its supertypes.
- Unbounded Wildcards (
Example:
public class WildcardExample {
public static void printList(List<?> list) {
for (Object element : list) {
System.out.println(element);
}
}
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3);
printList(numbers);
}
}
2. Annotations and Metadata
Annotations provide metadata about your code to the compiler or runtime.
A. Built-in Annotations
Annotation | Description |
---|---|
@Override | Ensures a method is overriding a superclass method. |
@Deprecated | Marks a method or class as deprecated. |
@SuppressWarnings | Suppresses compiler warnings. |
@FunctionalInterface | Marks an interface as a functional interface (Java 8+). |
Example:
class Parent {
@Deprecated
public void oldMethod() {
System.out.println("This is a deprecated method.");
}
}
public class AnnotationsExample {
@Override
public String toString() {
return "Annotations Example";
}
public static void main(String[] args) {
Parent parent = new Parent();
parent.oldMethod(); // Warning: This method is deprecated
}
}
B. Custom Annotations
Syntax:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface CustomAnnotation {
String value();
}
Usage:
public class CustomAnnotationExample {
@CustomAnnotation("This is a custom annotation")
public void myMethod() {
System.out.println("Method with custom annotation.");
}
public static void main(String[] args) throws Exception {
CustomAnnotationExample example = new CustomAnnotationExample();
example.myMethod();
}
}
3. Reflection API
Reflection allows you to inspect or modify classes, methods, and fields at runtime.
A. Common Use Cases
- Inspecting class information (methods, fields, constructors).
- Invoking methods dynamically.
- Modifying private fields.
Example:
import java.lang.reflect.Method;
public class ReflectionExample {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("java.lang.String");
System.out.println("Methods in String class:");
for (Method method : clazz.getDeclaredMethods()) {
System.out.println(method.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
B. Accessing and Modifying Private Fields
Example:
import java.lang.reflect.Field;
class Person {
private String name = "John";
}
public class ModifyPrivateField {
public static void main(String[] args) throws Exception {
Person person = new Person();
Field field = person.getClass().getDeclaredField("name");
field.setAccessible(true);
System.out.println("Before: " + field.get(person));
field.set(person, "Alice");
System.out.println("After: " + field.get(person));
}
}
4. Introduction to JVM Internals
The Java Virtual Machine (JVM) is the engine that runs Java bytecode. Understanding its internals helps optimize code.
A. JVM Memory Model
- Heap: Stores objects and class instances.
- Stack: Stores method calls and local variables.
- Method Area: Stores class metadata and static variables.
- Program Counter (PC): Keeps track of the current instruction.
- Native Method Stack: Used for native method execution.
B. Garbage Collection
What is Garbage Collection?
- Automatic memory management in Java.
- Removes unused objects from memory.
Garbage Collectors:
- Serial GC.
- Parallel GC.
- G1 GC (default since Java 9).
Example: Requesting Garbage Collection:
public class GarbageCollectionExample {
public static void main(String[] args) {
GarbageCollectionExample obj = new GarbageCollectionExample();
obj = null; // Make the object eligible for GC
System.gc(); // Request garbage collection
}
@Override
protected void finalize() {
System.out.println("Garbage Collector called!");
}
}
5. Practical Exercises
Exercise 1: Generic Pair Class
Write a generic class Pair
that holds two values of the same type.
Solution:
class Pair<T> {
private T first;
private T second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public T getSecond() {
return second;
}
}
Exercise 2: Using Reflection
Create a program that dynamically invokes a method from a class using reflection.
Exercise 3: Custom Annotation
Create a custom annotation to log the execution time of a method.
6. Summary
Key Takeaways:
Generics:
- Provide type safety and reusability for classes and methods.
- Use wildcards for flexible type constraints.
Annotations:
- Provide metadata for classes, methods, or fields.
- Can define and use custom annotations for specific use cases.
Reflection:
- Enables runtime inspection and modification of classes, methods, and fields.
JVM Internals:
- Understanding the memory model helps in optimizing applications.
- Garbage collection automates memory management.
Module 15: Building a Real-World Project
Objective: Apply your knowledge of Java to build a complete, functional application. This module focuses on modular coding, error handling, and best practices for professional Java development.
1. Choosing a Real-World Project
Here are three example projects to consider. Choose one based on your interests or requirements:
A. Inventory Management System
- Tracks products, stock levels, and suppliers.
- Features include adding, updating, and viewing inventory.
B. Chat Application (Client-Server)
- A real-time communication app with a server and multiple clients.
- Implements networking concepts using sockets.
C. Library Management System
- Manages books, borrowers, and due dates.
- Includes features like issuing books, returning books, and generating reports.
2. Key Concepts to Focus On
Modular Coding:
- Use packages to organize your code into logical modules.
- Separate concerns (e.g., database layer, service layer, UI layer).
Error Handling:
- Implement robust error-handling mechanisms using
try-catch-finally
. - Use custom exceptions for specific error scenarios.
- Implement robust error-handling mechanisms using
Best Practices:
- Use meaningful variable and method names.
- Write modular and reusable code.
- Follow design patterns like MVC (Model-View-Controller) where applicable.
3. Example: Inventory Management System
A. Overview of the System
Features:
- Add new products.
- View product details.
- Update stock levels.
- Search for products by name or ID.
- Save and load inventory data to/from a file or database.
Modules:
Product
: Represents individual products.Inventory
: Manages the collection of products.Database
: Handles data storage and retrieval.UI
: Provides a user interface for interaction.
B. System Design
Class Diagram
Product Class:
- Fields:
id
,name
,price
,quantity
. - Methods:
getters
,setters
,toString()
.
- Fields:
Inventory Class:
- Fields:
List<Product>
. - Methods:
addProduct()
,updateStock()
,viewProduct()
,searchProduct()
.
- Fields:
Main Class:
- Contains the
main()
method to run the application.
- Contains the
C. Implementation
1. Product Class
public class Product {
private int id;
private String name;
private double price;
private int quantity;
public Product(int id, String name, double price, int quantity) {
this.id = id;
this.name = name;
this.price = price;
this.quantity = quantity;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
@Override
public String toString() {
return "Product [ID=" + id + ", Name=" + name + ", Price=" + price + ", Quantity=" + quantity + "]";
}
}
2. Inventory Class
import java.util.ArrayList;
import java.util.List;
public class Inventory {
private List<Product> products;
public Inventory() {
products = new ArrayList<>();
}
public void addProduct(Product product) {
products.add(product);
}
public void updateStock(int id, int newQuantity) {
for (Product product : products) {
if (product.getId() == id) {
product.setQuantity(newQuantity);
return;
}
}
System.out.println("Product not found!");
}
public void viewProducts() {
for (Product product : products) {
System.out.println(product);
}
}
public Product searchProduct(int id) {
for (Product product : products) {
if (product.getId() == id) {
return product;
}
}
return null;
}
}
3. Main Class
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Inventory inventory = new Inventory();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("\nInventory Management System");
System.out.println("1. Add Product");
System.out.println("2. Update Stock");
System.out.println("3. View Products");
System.out.println("4. Search Product");
System.out.println("5. Exit");
System.out.print("Choose an option: ");
int choice = scanner.nextInt();
switch (choice) {
case 1:
System.out.print("Enter Product ID: ");
int id = scanner.nextInt();
System.out.print("Enter Product Name: ");
String name = scanner.next();
System.out.print("Enter Product Price: ");
double price = scanner.nextDouble();
System.out.print("Enter Product Quantity: ");
int quantity = scanner.nextInt();
Product product = new Product(id, name, price, quantity);
inventory.addProduct(product);
System.out.println("Product added successfully!");
break;
case 2:
System.out.print("Enter Product ID to update: ");
int updateId = scanner.nextInt();
System.out.print("Enter new quantity: ");
int newQuantity = scanner.nextInt();
inventory.updateStock(updateId, newQuantity);
break;
case 3:
inventory.viewProducts();
break;
case 4:
System.out.print("Enter Product ID to search: ");
int searchId = scanner.nextInt();
Product foundProduct = inventory.searchProduct(searchId);
if (foundProduct != null) {
System.out.println(foundProduct);
} else {
System.out.println("Product not found!");
}
break;
case 5:
System.out.println("Exiting...");
scanner.close();
return;
default:
System.out.println("Invalid choice! Please try again.");
}
}
}
}
4. Best Practices for Real-World Projects
Follow Clean Code Principles:
- Write readable, maintainable, and modular code.
Handle Errors Gracefully:
- Use proper error handling with try-catch blocks.
- Validate user inputs to avoid runtime exceptions.
Use Design Patterns:
- Apply design patterns like MVC (Model-View-Controller) for larger projects.
Document Code:
- Use comments and Javadoc to explain complex parts of the code.
Test Your Application:
- Write unit tests to ensure functionality.
- Use tools like JUnit for testing.
5. Practical Exercises
Exercise 1: Extend the Inventory System
- Add features like:
- Sorting products by name or price.
- Exporting inventory data to a CSV file.
Exercise 2: Build a Library Management System
- Track books, members, and loan records.
- Add features like:
- Issuing and returning books.
- Generating overdue reports.
Exercise 3: Chat Application
- Implement a chat system where multiple clients can connect to a server and exchange messages in real-time.
6. Summary
Key Takeaways:
- Building real-world applications involves combining multiple Java concepts into a cohesive system.
- Modularize your code by separating concerns into different classes and packages.
- Implement robust error handling and follow best coding practices.
- Focus on building reusable and maintainable code structures.