Java
Introduction to Java
Setting Up Java Development Environment:
Install Java Development Kit (JDK):
The Java Development Kit (JDK) is a software development kit used to develop Java applications.
Visit the official Oracle website to download the latest JDK version compatible with your operating system.
Follow the installation instructions provided by the installer.
Set Up Environment Variables (Optional):
Setting up environment variables is optional but can be helpful for command-line usage and IDE configuration.
JAVA_HOME: Set this variable to the directory where JDK is installed. This helps other applications locate the JDK installation.
PATH: Add the JDK's bin directory to the system's PATH variable. This allows you to execute Java tools and commands from any location in the command prompt or terminal.
Writing Your First Java Program:
The "Hello, World!" program is a traditional starting point for learning a new programming language.
In Java, the public static void main(String[] args) method is the entry point for execution.
The System.out.println() method is used to print the specified string to the standard output (usually the console).
Create a simple "Hello, World!" program to verify your setup:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Compile and run the program using the following commands in your terminal or command prompt:
javac HelloWorld.java
java HelloWorld
You should see the output: Hello, World!
Java Basics:
Variables and Data Types:
Java supports various data types, including primitive types (e.g., int, double, boolean) and reference types (e.g., String, arrays, objects).
Variables are used to store data values, and their type determines the kind of data that can be stored.
int age = 25;
double price = 19.99;
String name = "John";
boolean isStudent = true;
Operators:
Java provides arithmetic, assignment, comparison, logical, and bitwise operators for performing different kinds of operations on variables and values.
int x = 10 + 5;
int y = 10 - 5;
int z = 10 * 5;
int quotient = 10 / 5;
int remainder = 10 % 3;
Control Flow Statements:
Control flow statements, such as if, else, for, while, do-while, control the flow of execution in a program based on specified conditions.
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else if (num < 0) {
System.out.println("Negative");
} else {
System.out.println("Zero");
}
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
while (num > 0) {
System.out.println(num);
num--;
}
Arrays:
Arrays in Java are homogeneous data structures that store elements of the same type in contiguous memory locations.
They are indexed collections, with each element accessed by its numerical index.
int[] numbers = {1, 2, 3, 4, 5};
String[] names = new String[3];
names[0] = "John";
names[1] = "Alice";
names[2] = "Bob";
Object-Oriented Programming (OOP) Concepts:
Classes and Objects:
A class is a blueprint for creating objects, defining their structure and behavior.
Objects are instances of classes that represent real-world entities and encapsulate data and behavior.
public class Car {
String brand;
String model;
int year;
public void drive() {
System.out.println("Driving...");
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.brand = "Toyota";
myCar.model = "Camry";
myCar.year = 2020;
myCar.drive();
}
}
Encapsulation:
Encapsulate fields within a class using access modifiers (private, protected, public) and provide public getter and setter methods to access and modify the fields.
Inheritance:
Inheritance is a mechanism in Java where a new class (subclass) inherits properties and behaviors from an existing class (superclass).
It promotes code reuse and establishes an "is-a" relationship between classes.
Create subclasses that inherit attributes and behaviors from a superclass. Use the extends keyword to establish an inheritance relationship.
public class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
}
Polymorphism:
Polymorphism allows objects of different classes to be treated as objects of a common superclass.
It enables dynamic method dispatch, where the method to be executed is determined at runtime based on the object's actual type.
Implement polymorphic behavior through method overriding and method overloading. Use dynamic method dispatch to invoke overridden methods at runtime.
Animal myDog = new Dog();
myDog.sound(); // Output: Dog barks
Abstraction in Java:
Abstract classes and interfaces allow you to define common behavior without specifying implementation details. Abstract classes may contain abstract methods (without implementation), while interfaces declare method signatures without implementations.
// Abstract class
public abstract class Animal {
// Abstract method (no implementation)
public abstract void sound();
// concrete method
public void sleep() {
System.out.println("The animal is sleeping ZZZZZ....");
}
}
// Concrete subclass
public class Dog extends Animal {
// Implementing abstract method
@Override
public void sound() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
// create an instance of Dog
Dog dog = new Dog();
// call methods
dog.sound()
dog.sleep()
}
}
Interface
// Abstract class
public interface Animal {
// Abstract method (no implementation)
public void sound();
// concrete method
public default void sleep() {
System.out.println("ZZZZZ....");
}
}
// Concrete subclass
public class Dog extends Animal {
// Implementing abstract method
@Override
public void sound() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
// create an instance of Dog
Dog dog = new Dog();
// call methods
dog.sound()
dog.sleep()
}
}
Abstract Class:
Can have both abstract and concrete methods.
Can have fields (variables).
Can extend only one abstract class.
Used for providing a common base implementation.
Interface:
Can only have method declarations (abstract methods) and default methods (with implementation).
Cannot have fields other than static final constants.
Can extend multiple interfaces.
Used for defining a contract for classes and enabling multiple inheritance.
In general:
Use abstract classes when you need to provide a common base implementation for a group of related classes.
Use interfaces when you want to define a contract for a class without providing any implementation details or when you need multiple inheritance.
Advanced to Java
Chapter 1: Advanced Object-Oriented Programming (OOP)
Inheritance:
Example: Creating a class hierarchy for different types of vehicles, such as Vehicle, Car, and Bicycle, demonstrating method overriding and access control.
Polymorphism:
Example: Implementing an Animal interface with speak() method, and then creating classes like Dog and Cat that implement Animal interface to demonstrate dynamic method dispatch.
Encapsulation:
Example: Creating a Person class with private instance variables like name, age, and providing public getter and setter methods to encapsulate the data.
class Vehicle {
void start() {
System.out.println("Vehicle started");
}
}
class Car extends Vehicle {
void start() {
System.out.println("Car started");
}
}
class Bicycle extends Vehicle {
// No need to override start() method
}
public class InheritanceExample {
public static void main(String[] args) {
Vehicle vehicle = new Car();
vehicle.start(); // Output: Car started
}
}
Chapter 2: Generics
Introduction to Generics:
Example: Writing a generic Box<T> class to hold objects of any type, and then demonstrating its usage with different types like Integer, String, etc.
Generic Classes and Methods:
Example: Creating a generic method to find the maximum element in an array of any type, and a generic class to implement a stack that can hold elements of any type.
Type Erasure and Bounded Type Parameters:
Example: Understanding how generics are implemented using type erasure, and demonstrating bounded type parameters with a BoundedList<T extends Comparable<T>> class.
Introduction to Generic
class Box<T> {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
public class GenericsExample {
public static void main(String[] args) {
Box<Integer> integerBox = new Box<>();
integerBox.setItem(10);
System.out.println("Item: " + integerBox.getItem()); // Output: Item: 10
}
}
Generic Classes and Methods
public class Utils {
public static <T> T max(T[] array) {
T max = array[0];
for (T item : array) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
}
public class GenericMethodsExample {
public static void main(String[] args) {
Integer[] numbers = {1, 5, 3, 7, 2};
String[] names = {"John", "Alice", "Bob"};
System.out.println("Max number: " + Utils.max(numbers)); // Output: Max number: 7
System.out.println("Max name: " + Utils.max(names)); // Output: Max name: John
}
}
Type Erasure and Bounded Type Parameters
class BoundedList<T extends Comparable<T>> {
private List<T> list = new ArrayList<>();
public void add(T item) {
list.add(item);
}
public T max() {
return Collections.max(list);
}
}
public class BoundedTypeParametersExample {
public static void main(String[] args) {
BoundedList<Integer> numbers = new BoundedList<>();
numbers.add(10);
numbers.add(5);
System.out.println("Max number: " + numbers.max()); // Output: Max number: 10
}
}
Chapter 3: Collections Framework
Lists, Sets, Maps:
Example: Using ArrayList, HashSet, and HashMap to store and manipulate collections of data, such as a list of students, a set of unique numbers, and a map of employee IDs to names.
Sorting and Searching:
Example: Implementing sorting and searching algorithms using Comparable and Comparator interfaces, and using utility methods from Collections class like sort() and binarySearch().
Collection Utilities:
Example: Using methods from the Collections and Arrays classes to perform common operations like sorting, shuffling, searching, and converting between collections and arrays.
Lists, Sets, Maps
import java.util.*;
public class CollectionsExample {
public static void main(String[] args) {
// List example
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");
// Set example
Set<Integer> set = new HashSet<>();
set.add(10);
set.add(20);
set.add(30);
// Map example
Map<String, Integer> map = new HashMap<>();
map.put("One", 1);
map.put("Two", 2);
map.put("Three", 3);
System.out.println("List: " + list);
System.out.println("Set: " + set);
System.out.println("Map: " + map);
}
}
Sorting and Searching
import java.util.*;
public class SortingSearchingExample {
public static void main(String[] args) {
// Sorting example
List<Integer> numbers = Arrays.asList(3, 1, 5, 2, 4);
Collections.sort(numbers);
System.out.println("Sorted numbers: " + numbers); // Output: Sorted numbers: [1, 2, 3, 4, 5]
// Searching example
int index = Collections.binarySearch(numbers, 3);
System.out.println("Index of 3: " + index); // Output: Index of 3: 2
}
}
Collection Utilities
import java.util.*;
public class CollectionUtilitiesExample {
public static void main(String[] args) {
// Sorting example
List<Integer> numbers = Arrays.asList(3, 1, 5, 2, 4);
Collections.sort(numbers);
System.out.println("Sorted numbers: " + numbers); // Output: Sorted numbers: [1, 2, 3, 4, 5]
// Shuffling example
Collections.shuffle(numbers);
System.out.println("Shuffled numbers: " + numbers);
// Converting array to list
Integer[] array = {1, 2, 3};
List<Integer> list = Arrays.asList(array);
System.out.println("List from array: " + list);
}
}
Chapter 4: Concurrency (Multithreading)
Threads:
Example: Creating and managing multiple threads to perform concurrent tasks, such as calculating Fibonacci series or processing data in parallel.
Synchronization:
Example: Synchronizing access to shared resources using synchronized methods and blocks, and understanding the volatile keyword for visibility guarantees.
Executors Framework:
Example: Using ExecutorService and ThreadPoolExecutor to manage a pool of worker threads and execute tasks asynchronously.
Creating Thread
class MyThread extends Thread {
public void run() {
System.out.println("Thread running");
}
}
public class ConcurrencyExample {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
Synchronization
class Counter {
private int count;
public synchronized void increment() {
count++;
}
public synchronized 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) {
e.printStackTrace();
}
System.out.println("Count: " + counter.getCount()); // Output: Count: 2000
}
}
Thread Pools
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("Task-" + i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("All tasks completed");
}
}
class WorkerThread implements Runnable {
private String taskName;
public WorkerThread(String taskName) {
this.taskName = taskName;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " (Start) taskName = " + taskName);
processTask();
System.out.println(Thread.currentThread().getName() + " (End)");
}
private void processTask() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Chapter 5: I/O Streams
Byte Streams vs Character Streams:
Example: Reading from and writing to files using byte streams (FileInputStream, FileOutputStream) and character streams (FileReader, FileWriter).
File I/O:
Example: Implementing file handling operations such as reading from a text file, writing to a text file, and handling exceptions related to file I/O.
Serialization:
Example: Serializing and deserializing objects using ObjectOutputStream and ObjectInputStream, and understanding the Serializable interface.
Reading and Writing Files
import java.io.*;
public class FileHandlingExample {
public static void main(String[] args) {
try {
// Writing to a file
FileWriter writer = new FileWriter("output.txt");
writer.write("Hello, World!");
writer.close();
// Reading from a file
FileReader reader = new FileReader("output.txt");
int data;
while ((data = reader.read()) != -1) {
System.out.print((char) data);
}
reader.close();
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
File Operations
import java.io.*;
public class FileOperationsExample {
public static void main(String[] args) {
File file = new File("data.txt");
// Check if file exists
if (file.exists()) {
System.out.println("File exists");
// Delete file
if (file.delete()) {
System.out.println("File deleted successfully");
} else {
System.out.println("Failed to delete file");
}
} else {
System.out.println("File does not exist");
}
}
}
Chapter 6: Exceptions and Error Handling
Types of Exceptions:
Example: Handling checked exceptions like IOException, unchecked exceptions like NullPointerException, and errors like OutOfMemoryError.
Handling Exceptions:
Example: Using try-catch blocks and finally block to handle exceptions gracefully, and chaining exceptions using getCause() method.
Custom Exceptions:
Example: Creating custom exception classes by extending Exception or RuntimeException, and throwing and catching custom exceptions.
Handling Exceptions
public class ExceptionHandlingExample {
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
}
}
public static int divide(int num1, int num2) {
return num1 / num2;
}
}
Custom Exceptions
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
public class CustomExceptionExample {
public static void main(String[] args) {
try {
validateAge(15);
} catch (InvalidAgeException e) {
System.out.println("Error: " + e.getMessage());
}
}
public static void validateAge(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("Age must be 18 or above");
}
}
}
Chapter 7: Advanced Language Features
These advanced language features enhance the expressiveness, safety, and productivity of Java programming by providing powerful tools for functional programming, data manipulation, error handling, and metadata management. They enable developers to write cleaner, more concise, and more maintainable code.
Enums:
Enums (enumerations) are a special type in Java used to define a fixed set of constants. Enumerations can contain constructors, methods, and fields like a regular class. They are often used to represent a predefined list of options or states, making the code more readable and maintainable by providing meaningful names to constants.
Example: Defining enums for days of the week, months of the year, and demonstrating their usage in switch statements and collections.
// Enum definition for days of the week
public enum DayOfWeek {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
}
// Using the enum
public class EnumExample {
public static void main(String[] args) {
// Iterating over enum values
for (DayOfWeek day : DayOfWeek.values()) {
System.out.println(day);
}
// Accessing individual enum constants
DayOfWeek firstDay = DayOfWeek.MONDAY;
System.out.println("First day of the week: " + firstDay);
}
}
Reflection:
Reflection is a powerful feature in Java that allows you to inspect and manipulate classes, objects, and methods at runtime. It provides a way to query class metadata, access fields and methods dynamically, and instantiate objects dynamically. Reflection is commonly used in frameworks, libraries, and tools for tasks such as dependency injection, serialization, and testing.
Example: Dynamically inspecting and modifying class metadata at runtime using classes from java.lang.reflect package like Class, Method, and Field
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// Sample class for reflection
class MyClass {
private String name;
public int value;
public MyClass(String name, int value) {
this.name = name;
this.value = value;
}
public void printInfo() {
System.out.println("Name: " + name + ", Value: " + value);
}
}
// Using reflection to inspect class members
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// Getting class information
Class<?> cls = MyClass.class;
// Inspecting fields
System.out.println("Fields:");
for (Field field : cls.getDeclaredFields()) {
System.out.println(field.getName() + " (" + field.getType() + ")");
}
// Inspecting methods
System.out.println("\nMethods:");
for (Method method : cls.getDeclaredMethods()) {
System.out.println(method.getName() + " (" + method.getParameterCount() + " parameters)");
}
// Creating an instance dynamically
MyClass obj = (MyClass) cls.getConstructor(String.class, int.class).newInstance("Example", 123);
obj.printInfo();
}
}
Lambda Expressions
Lambda expressions introduce a concise syntax for writing anonymous functions or closures in Java. They provide a way to represent functional interfaces (interfaces with a single abstract method) more compactly. Lambda expressions are commonly used with functional interfaces in the context of collections, streams, and concurrency.
import java.util.ArrayList;
import java.util.List;
public class LambdaExample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// Using lambda expression to iterate through the list
names.forEach(name -> System.out.println(name));
}
}
Streams
Streams in Java provide a way to process sequences of elements in a functional style. They allow you to perform operations such as filtering, mapping, sorting, and reducing on collections (or other data sources) in a declarative manner. Streams make it easier to write concise and expressive code for data manipulation tasks.
import java.util.Arrays;
import java.util.List;
public class StreamsExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Using streams to filter and sum even numbers
int sum = numbers.stream()
.filter(num -> num % 2 == 0)
.mapToInt(num -> num * 2)
.sum();
System.out.println("Sum of even numbers doubled: " + sum);
}
}
Optional
Optional is a container object that may or may not contain a non-null value. It is designed to address the problem of null references in Java, providing a more explicit and safer way to handle potentially absent values. Optional encourages a clearer and more defensive programming style by forcing developers to handle the presence or absence of values explicitly.
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
String str = "Hello";
// Creating an optional from a nullable value
Optional<String> optionalStr = Optional.ofNullable(str);
// Checking if the value is present and printing it
optionalStr.ifPresent(value -> System.out.println("Value: " + value));
// Getting the value or a default if it's not present
String result = optionalStr.orElse("Default Value");
System.out.println("Result: " + result);
}
}
Annotations
Annotations provide metadata about program elements such as classes, methods, fields, and parameters. They allow you to attach additional information or directives to your code, which can be used by tools, frameworks, or runtime environments. Annotations are commonly used for documentation, code analysis, and runtime behavior customization in Java.
Example: Using built-in annotations like @Override, @Deprecated, and creating custom annotations with meta-annotations like @Retention and @Target.
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodInfo {
String author() default "Unknown";
String date();
int revision() default 1;
String comments();
}
public class AnnotationsExample {
@MethodInfo(author = "John", date = "2024-02-20", comments = "This is a sample method")
public static void myMethod() {
// Method implementation
}
public static void main(String[] args) {
// Retrieving annotation information
MethodInfo methodInfo = AnnotationsExample.class.getMethod("myMethod").getAnnotation(MethodInfo.class);
System.out.println("Author: " + methodInfo.author());
System.out.println("Date: " + methodInfo.date());
System.out.println("Comments: " + methodInfo.comments());
}
}
Functional Interfaces
Functional interfaces serve as the backbone of the functional programming features introduced in Java 8, such as lambda expressions and streams. They enable you to encapsulate behavior in the form of functions and pass them around as parameters or return values. Functional interfaces promote a more concise and expressive coding style, making it easier to work with functions in Java.
// Functional interface with a single abstract method
@FunctionalInterface
interface MathOperation {
int operate(int a, int b);
}
public class FunctionalInterfaceExample {
public static void main(String[] args) {
// Using a lambda expression to implement the functional interface
MathOperation addOperation = (a, b) -> a + b;
System.out.println("Addition result: " + addOperation.operate(5, 3));
// Using a method reference to implement the functional interface
MathOperation subtractOperation = FunctionalInterfaceExample::subtract;
System.out.println("Subtraction result: " + subtractOperation.operate(5, 3));
}
// Method to be used with method reference
public static int subtract(int a, int b) {
return a - b;
}
}
Chapter 8: Java Networking
Socket Programming:
Example: Implementing a simple client-server application using sockets for communication, demonstrating how to establish connections, send and receive data.
URL Handling and HTTP Connections:
Example: Making HTTP requests to external APIs using HttpURLConnection, handling responses, and processing data.
Web Services:
Example: Consuming and providing RESTful web services using libraries like javax.ws.rs or frameworks like Spring Boot, showcasing CRUD operations over HTTP.
import java.net.*;
public class NetworkingExample {
public static void main(String[] args) {
try {
URL url = new URL("https://www.example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Chapter 9: Java Database Connectivity (JDBC)
JDBC Basics:
Example: Connecting to a database, executing SQL queries, retrieving and manipulating data from tables using JDBC API.
Prepared Statements and Transactions:
Example: Using prepared statements for executing parameterized SQL queries, handling transactions for ensuring data integrity.
Batch Updates:
Example: Optimizing database operations by batching multiple SQL statements into a single batch for execution.
Bach updates
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class BatchUpdateExample {
public static void main(String[] args) {
// Database connection parameters
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "username";
String password = "password";
// SQL statements for batch update
String[] sqlStatements = {
"INSERT INTO users (username, email) VALUES (?, ?)",
"UPDATE users SET email = ? WHERE username = ?",
"DELETE FROM users WHERE username = ?"
};
try (
// Establish database connection
Connection connection = DriverManager.getConnection(url, username, password);
// Prepare batch update statement
PreparedStatement preparedStatement = connection.prepareStatement(sqlStatements[0]);
) {
// Insert data into batch
preparedStatement.setString(1, "user1");
preparedStatement.setString(2, "user1@example.com");
preparedStatement.addBatch();
// Update data in batch
preparedStatement.setString(1, "updated@example.com");
preparedStatement.setString(2, "user1");
preparedStatement.addBatch();
// Delete data in batch
preparedStatement.setString(1, "user2");
preparedStatement.addBatch();
// Execute batch update
int[] results = preparedStatement.executeBatch();
// Process batch update results
for (int result : results) {
System.out.println("Update count: " + result);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Chapter 10: JavaFX GUI Programming
Introduction to JavaFX:
Example: Creating a simple JavaFX application with a graphical user interface, understanding the application lifecycle.
Layouts:
Example: Designing user interfaces using different layout managers like VBox, HBox, GridPane, and BorderPane.
Event Handling and Controls:
Example: Handling user events such as button clicks, mouse movements, and keyboard inputs, and using standard controls like buttons, text fields, and labels.
Example 1: Hello World
This example demonstrates a simple JavaFX application that displays a "Hello, World!" message in a window.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class HelloWorld extends Application {
@Override
public void start(Stage primaryStage) {
// Create a label
Label label = new Label("Hello, World!");
// Create a layout pane and add the label
StackPane root = new StackPane();
root.getChildren().add(label);
// Create a scene and set it on the stage
Scene scene = new Scene(root, 300, 200);
primaryStage.setScene(scene);
// Set the stage title and show it
primaryStage.setTitle("Hello World Example");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Example 2: Button Click
This example demonstrates how to create a button and handle its click event.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ButtonClickExample extends Application {
@Override
public void start(Stage primaryStage) {
// Create a button
Button button = new Button("Click Me");
// Handle button click event
button.setOnAction(e -> System.out.println("Button clicked!"));
// Create a layout pane and add the button
StackPane root = new StackPane();
root.getChildren().add(button);
// Create a scene and set it on the stage
Scene scene = new Scene(root, 300, 200);
primaryStage.setScene(scene);
// Set the stage title and show it
primaryStage.setTitle("Button Click Example");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Chapter 11: Advanced Topics
JVM Internals:
Java Virtual Machine (JVM) internals involve understanding how the JVM executes Java bytecode and manages memory, threads, and resources. It includes topics such as:
JVM architecture and components (class loader, runtime data areas, execution engine)
Garbage collection algorithms and tuning
Class loading mechanisms and class verification
JIT compilation and bytecode optimization
Example: Exploring JVM internals using tools like jconsole, jvisualvm, analyzing memory usage, garbage collection behavior.
Java Memory Model (JMM):
The Java Memory Model (JMM) defines the rules and guarantees for the behavior of shared memory in Java multithreaded programs. It specifies how changes made by one thread to shared variables are visible to other threads. Key concepts include:
Happens-before relationship
Volatile variables and their visibility guarantees
Synchronization mechanisms (synchronized blocks, locks)
Atomic operations and classes (e.g., AtomicInteger)
Example: Understanding memory visibility issues, race conditions, and synchronization guarantees provided by the Java Memory Model.
Performance Optimization:
Performance optimization in Java involves identifying and addressing bottlenecks to improve the speed, efficiency, and scalability of Java applications. Techniques include:
Profiling and performance analysis tools (e.g., JProfiler, VisualVM)
Code optimization (e.g., reducing unnecessary object creation, optimizing loops)
JVM tuning (e.g., adjusting garbage collection parameters, heap and stack sizes)
Thread pool tuning and concurrency optimization
Using efficient data structures and algorithms
Caching and memoization strategies
Load testing and benchmarking
Example: Profiling Java applications, identifying performance bottlenecks, tuning JVM parameters, and optimizing code for better performance.
Example: Garbage Collection Tuning
// JVM options for garbage collection tuning
-Xms512m // Initial heap size
-Xmx2048m // Maximum heap size
-XX:NewSize=128m // Initial size of the young generation
-XX:MaxNewSize=256m // Maximum size of the young generation
-XX:SurvivorRatio=8 // Ratio of eden/survivor space size
-XX:MaxTenuringThreshold=15 // Maximum tenuring threshold for objects in the young generation
-XX:+UseConcMarkSweepGC // Use Concurrent Mark Sweep (CMS) garbage collector
-XX:+UseParNewGC // Use parallel young generation collector
-XX:+CMSParallelRemarkEnabled // Enable parallel remark phase in CMS
Example: Synchronization and Volatile Variables
public class Counter {
private volatile int count;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
Example: Concurrent Data Structures
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
System.out.println(map.get("B")); // Output: 2
}
}
Chapter 12: Best Practices and Design Patterns
Design Patterns:
Example: Implementing commonly used design patterns such as Singleton, Factory, Observer, and understanding their usage and benefits.
Code Organization and Readability:
Example: Writing clean, modular, and maintainable code following best practices like SOLID principles, code comments, and naming conventions.
Unit Testing and Continuous Integration:
Example: Writing unit tests using JUnit or TestNG, ensuring code coverage, and integrating with CI/CD pipelines for automated testing and deployment.
Chapter 13: Advanced Java Tools and Libraries
Apache Commons and Guava:
Example: Using utility libraries like Apache Commons and Guava for common tasks such as string manipulation, collection operations, and concurrency.
Build Tools: Maven, Gradle:
Example: Setting up and configuring projects with Maven or Gradle, managing dependencies, building and packaging Java applications.
Logging Frameworks: Log4j, SLF4J:
Example: Configuring logging in Java applications using Log4j or SLF4J, logging messages with different levels of severity and categories.