Java All Unit
Java All Unit
Listeners:
Class Listener:
Adapters:
Action Event Methods:
UNIT 1
Focus Event Methods:
Overview of Java:
Key Event Methods:
Characteristics of Java:
Mouse Events:
JVM, JRE, JDK
Window Events:
Parameters used in First Java Program
UNIT - 4
Basic Java Program Understanding
Input/Output Streams:
Java program Compilation and Execution Process
Stream Filters:
JVM as an interpreter and emulator
Data Input and Output Stream:
Instruction Set
Print Stream:
class File Format
Random Access File:
Security Promises of the JVM
JDBC (Database connectivity with MS-Access, Oracle, MS-SQL Server)
Class loaders and security aspects
Object Serialization
Sandbox model
Sockets
UNIT 2
Development of client Server applications
Java Fundamentals: Data Types, Literals, and Variables
Design of multithreaded server
Operators
Remote Method invocation
Control of Flow
Java Native interfaces and Development of a JNI based application
Classes and Instances
Java Collection API Interfaces
Inheritance
Throw and Throws clauses
User defined Exceptions
Applets
UNIT - 3 UNIT 1
Threads
Runnable Interface Overview of Java:
Thread Communication
AWT Components
Component Class and Container Class:
Java is a widely-used programming language that was developed by Sun
Layout Manager Interface and Default Layouts: Microsystems (now owned by Oracle) in the mid-1990s. It is known for its
Insets and Dimensions: platform independence, object-oriented programming (OOP) features, and
Border Layout: robustness. Java is used for building a variety of applications, including desktop
Flow Layout: software, mobile apps, web applications, and enterprise systems.
Card Layout:
Grid Bag Layout:
Characteristics of Java:
AWT Events:
Event Models:
JAVA 1 JAVA 2
1. Platform Independence: One of the key features of Java is its ability to run 8. Community and Ecosystem: Java has a large and active developer
on any platform that supports Java Virtual Machine (JVM). This platform community, which contributes to its rich ecosystem. There are numerous
independence is achieved by compiling Java source code into bytecode, frameworks, libraries, and tools available for Java development, making it
which can be executed on any system with a compatible JVM. easier to build complex applications quickly.
2. Object-Oriented Programming (OOP): Java is designed around the Overall, Java is a powerful and versatile programming language known for its
principles of object-oriented programming, which allows developers to model platform independence, object-oriented approach, and robustness. It is widely
real-world entities as objects and organize code into reusable and modular used in various domains and provides a solid foundation for building reliable and
components. Concepts like classes, objects, inheritance, and polymorphism scalable applications.
are integral to Java's OOP paradigm.
3. Simple and Readable Syntax: Java has a straightforward syntax that is easy
to learn and read. It borrows many syntax conventions from languages like JVM, JRE, JDK
C and C++, making it familiar to programmers from those backgrounds. The 1. JVM: The JVM (Java Virtual Machine) is a crucial component of the Java
language promotes clean and organized code through its syntax rules. platform. It provides a runtime environment for executing Java bytecode.
4. Robustness and Memory Management: Java's robustness is achieved The JVM interprets or compiles Java bytecode into machine code and
through features like exception handling, automatic memory management handles memory management, security, and other runtime functionalities. It
(garbage collection), and strong type checking. Exceptions help in dealing ensures that Java programs are platform-independent, as bytecode can be
with errors and exceptions that may occur during program execution, while executed on any system with a compatible JVM.
garbage collection relieves developers from manually managing memory 2. JRE: The JRE (Java Runtime Environment) is a software package that
allocation and deallocation. includes the JVM, libraries, and other components necessary for running
5. Rich Standard Library: Java comes with a vast standard library that provides Java applications. It is a subset of the Java Development Kit (JDK) and is
a wide range of pre-built classes and functions for common programming primarily used by end-users who only need to run Java programs, not
tasks. This library includes utilities for input/output operations, data develop them.
structures, networking, multithreading, and more. Utilizing the standard 3. JDK: The JDK (Java Development Kit) is a software development kit that
library saves development time and effort. includes tools, libraries, and the JRE. It is used by developers to create,
6. Security: Java emphasizes security and provides built-in mechanisms for compile, and debug Java applications. The JDK contains the necessary
secure programming. It includes features like bytecode verification, components for both development and execution of Java programs.
sandboxing, and security managers, which help in creating secure and
trusted applications.
7. Scalability and Performance: Java's scalability and performance have Parameters used in First Java Program
improved over the years. The Just-In-Time (JIT) compiler optimizes Let's see what is the meaning of class, public, static, void, main, String[],
bytecode at runtime, translating it into machine code for efficient execution. System.out.println().
Additionally, Java supports multi-threading, enabling developers to write
concurrent and efficient programs. class keyword is used to declare a class in Java.
JAVA 3 JAVA 4
public keyword is an access modifier that represents visibility. It means it is
visible to all. Let's break down the different components of the program:
static is a keyword. If we declare any method as static, it is known as the 1. Import Statements:
static method. The core advantage of the static method is that there is no The program begins with import statements that specify the classes from
need to create an object to invoke the static method. The main() method is the Java standard library that will be used in the program.
executed by the JVM, so it doesn't require creating an object to invoke the
In this example, we import the Scanner class from the java.util package
main() method. So, it saves memory.
to facilitate user input.
void is the return type of the method. It means it doesn't return any value.
2. Public Class:
main represents the starting point of the program.
Next, we declare a public class called BasicJavaProgram .
String[] args or String args[] is used for command line argument. We will
The class name should match the filename (excluding the .java
discuss it in coming section.
extension) and follow Java naming conventions.
System.out.println() is used to print statement. Here, System is a class, out
3. Main Method:
is an object of the PrintStream class, println() is a method of the PrintStream
class. We will discuss the internal working of System.out.println() statement Inside the BasicJavaProgram class, we have the main method, which
in the coming section. serves as the entry point of the program.
The main method is declared as public , static , and void , with a single
Basic Java Program Understanding
parameter of type String array ( String[] args ).
// Importing necessary classes from Java standard library public indicates that the method can be accessed from outside the
import java.util.Scanner; class.
// Main class declaration static means the method belongs to the class itself, rather than an
public class BasicJavaProgram {
instance of the class.
// Main method, the entry point of the program
public static void main(String[] args) { void specifies that the method does not return any value.
// Create a Scanner object to read input from the user
Scanner scanner = new Scanner(System.in); 4. Method Body:
// Prompt the user to enter their name The method body is enclosed within curly braces {} .
System.out.print("Enter your name: ");
Inside the main method, we create a Scanner object to read input from
// Read the input from the user
String name = scanner.nextLine(); the user.
JAVA 5 JAVA 6
Then we use the Scanner object's nextLine() method to read the user's
javac YourProgram.java
input and store it in the name variable of type String .
6. Output:
If there are no errors in your code, the compiler will generate a bytecode
We use the System.out.println() method to print a welcome message file with a .class extension. This file contains the compiled version of
along with the entered name. your program.
The println() method adds a newline character after printing the 3. Java Virtual Machine (JVM):
message.
The JVM is responsible for executing Java bytecode. It acts as an
7. Scanner Closing: interpreter for the bytecode and provides a runtime environment for your
We close the Scanner object using the close() method to release program.
system resources. When you run a Java program, you need to have a JVM installed on
This program demonstrates the basic structure of a Java program, including your machine. The JVM takes care of loading and executing the
import statements, class declaration, the main method, user input with Scanner , bytecode.
and output with System.out.println() . You can run this program to prompt the 4. Running Java Bytecode:
user for their name and display a welcome message.
To run the compiled bytecode, you use the java command followed by
the name of the class containing the main method (the entry point of
your program).
Java program Compilation and Execution Process
In the command prompt or terminal, navigate to the directory where your
The compilation and execution process in Java involves several steps. Let's
.class file is located and execute the following command:
break it down:
To begin, you need to write your Java program's source code. This is
done in a plain text file with a .java extension. You can use any text The JVM will start executing the bytecode, and your program will run
editor or integrated development environment (IDE) for this purpose. accordingly.
2. Compiling Java Source Code:
The next step is to compile the Java source code into bytecode. The Java Virtual Machine (JVM) is the cornerstone of the Java platform. It
Bytecode is a platform-independent representation of your program that provides a runtime environment for executing Java bytecode and plays a crucial
can be executed by the Java Virtual Machine (JVM). role in the platform's platform independence and security. Let's explore the
organization of the JVM:
To compile the source code, you use the Java compiler (javac) that
comes with the Java Development Kit (JDK). In the command prompt or 1. Class Loader:
terminal, navigate to the directory where your source code file is located
When a Java program is executed, the JVM's class loader subsystem is
and execute the following command:
responsible for loading classes into the memory. It performs tasks such
JAVA 7 JAVA 8
as locating and loading the necessary class files from the file system, performance. It optimizes the execution of the bytecode by
network, or other sources. analyzing and translating it into efficient machine instructions.
The class loader is divided into three main components: the bootstrap Interpreter: The interpreter reads and executes bytecode
class loader, extension class loader, and application class loader. These instructions one by one. It is responsible for executing less
loaders work together to load classes based on the class's visibility and frequently executed code and acts as a fallback when the JIT
dependency requirements. compiler has not yet compiled certain bytecode.
The JVM defines several runtime data areas that are used during Memory management is an essential aspect of the JVM. The garbage
program execution: collector automatically manages memory by reclaiming unused objects
and deallocating memory that is no longer needed.
Method Area: The method area stores class-level structures such as
method bytecode, field information, constant pool, and static The garbage collector identifies objects that are no longer reachable and
variables. frees the memory occupied by them, ensuring efficient memory usage
and preventing memory leaks.
Heap: The heap is a runtime data area where objects are allocated.
It is divided into different regions and is the memory area managed 5. Native Method Interface (JNI):
by the garbage collector for dynamic memory allocation and
The Native Method Interface (JNI) allows Java code to interact with code
deallocation.
written in other programming languages, such as C or C++. It provides a
Java Stack: Each thread in the JVM has its own Java stack, which is way to call native methods and exchange data between Java and native
used for method execution and storing local variables, method code.
parameters, and partial results. It also keeps track of method
6. Security Manager and Sandbox:
invocations and returns.
The JVM incorporates a security manager that enforces security policies
PC (Program Counter) Register: The PC register keeps track of the
to protect the system and prevent unauthorized actions. It ensures that
currently executing JVM instruction. It holds the address of the next
Java code runs within a controlled environment called the sandbox,
bytecode instruction to be executed.
which restricts potentially harmful operations.
Native Method Stack: The native method stack is used for executing
The organization of the JVM provides a runtime environment that enables
native code (code written in languages other than Java) and
platform independence, memory management, dynamic class loading, bytecode
handling interactions with the underlying operating system.
execution, and security measures for Java applications.
3. Execution Engine:
JAVA 9 JAVA 10
1. JVM as an Interpreter: Instruction Set
The JVM interprets Java bytecode instructions one by one and executes The instruction set in the context of Java refers to the set of bytecode
them. It reads the bytecode, understands the instruction, and performs instructions that the Java Virtual Machine (JVM) can execute. These instructions
the corresponding operation. This interpretation happens at runtime. are specified by the Java Virtual Machine Specification and are used to perform
various operations and control flow within a Java program.
When the JVM is in the interpreting mode, it executes the bytecode
without converting it into machine code. This allows for platform Here are some common bytecode instructions found in the Java instruction set:
independence, as the bytecode is designed to be executed on any 1. Load and Store Instructions:
system with a compatible JVM.
iload , fload , aload : Load an integer, float, or reference from a local
The interpreter is responsible for executing less frequently executed variable onto the stack.
code or code segments that are not yet compiled by the Just-In-Time
istore , fstore , astore : Store an integer, float, or reference from the
(JIT) compiler.
stack into a local variable.
2. JVM as an Emulator:
2. Arithmetic and Logical Instructions:
The JVM can also be considered an emulator in the sense that it
iadd , fadd : Add two integers or floats.
emulates a virtual computing environment in which the Java program
runs. It creates a virtual representation of the underlying hardware and isub , fsub : Subtract two integers or floats.
provides a runtime environment for executing Java programs.
imul , fmul : Multiply two integers or floats.
The JVM abstracts the low-level hardware details and provides a
idiv , fdiv : Divide two integers or floats.
consistent platform for Java programs to run on. It emulates features like
memory management, stack management, thread management, and irem , frem : Compute the remainder of two integers or floats.
input/output operations. iand , ior , ixor : Perform bitwise AND, OR, XOR on two integers.
By providing this emulation layer, the JVM ensures that Java programs ishl , ishr , iushr : Perform shift operations on integers.
can run consistently across different platforms without being directly
3. Control Flow Instructions:
dependent on the underlying hardware and operating system.
if<cond> <label> : Perform a conditional jump to the specified label based
It's important to note that the JVM combines interpretation and emulation with
on a condition (e.g., ifeq , ifne , iflt ).
the Just-In-Time (JIT) compilation technique to improve performance. The JIT
compiler dynamically compiles frequently executed bytecode into native machine goto <label> : Unconditionally jump to the specified label.
code, which can be directly executed by the CPU. This compilation process
tableswitch , lookupswitch : Perform a switch statement based on a table
optimizes the execution speed of the Java program by eliminating the
or lookup.
interpretation overhead.
4. Object-oriented Instructions:
So, while the JVM primarily operates as an interpreter, it also incorporates
emulation techniques to provide a consistent runtime environment and platform new : Create a new instance of a class.
independence for Java programs. getfield , putfield : Get or set the value of a field in an object.
JAVA 11 JAVA 12
invokevirtual , invokestatic , invokeinterface : Invoke methods on objects The constant pool is an array-like structure, and each entry has a tag
or classes. indicating its type and the actual value.
newarray , anewarray : Create a new array of primitive types or objects. The access flags represent the access level and properties of the class
(e.g., public, final, abstract).
arraylength : Get the length of an array.
The class information includes the fully qualified name of the class, the
iaload , faload , aaload : Load an element from an array onto the stack.
name of its superclass, and interfaces it implements.
iastore , fastore , aastore : Store an element from the stack into an
4. Fields and Methods:
array.
The fields section lists the fields (variables) defined within the class,
These are just a few examples of the instructions available in the Java bytecode
along with their access flags, names, types, and any initial values.
instruction set. The JVM executes these instructions in a stack-based manner,
where operands are pushed onto a stack and operations are performed on the The methods section contains information about the methods defined in
top elements of the stack. the class, including access flags, names, return types, parameter types,
and bytecode instructions.
It's worth noting that Java bytecode instructions are designed to be platform-
independent and are executed by the JVM, which is responsible for translating 5. Attributes:
them into machine code specific to the underlying hardware architecture.
Attributes provide additional metadata about the class, fields, and
methods.
They can include information such as source file name, line number
class File Format
tables, exceptions thrown, annotations, and more.
The class file format is a binary file format used by the Java Virtual Machine
(JVM) to represent compiled Java bytecode. It defines the structure and The class file format follows a specific structure and is designed to be platform-
organization of the data stored in a class file. Here's an overview of the class file independent. It allows the JVM to interpret and execute the bytecode on any
format: system that has a compatible JVM implementation.
1. Magic Number and Version: It's important to note that the class file format is defined in the Java Virtual
Machine Specification and is subject to updates and revisions as new versions
The class file starts with a fixed 4-byte magic number ( 0xCAFEBABE ) that of the JVM are released.
identifies it as a valid class file.
The version numbers (minor and major) indicate the version of the class
file format being used.
Verification is an important process performed by the JVM to ensure the
2. Constant Pool: integrity and safety of Java bytecode before it is executed. The verification
The constant pool section stores various constant values used by the process checks the bytecode for various security and structural constraints to
class, such as strings, class names, field names, method names, and prevent potentially malicious or erroneous code from being executed. Here are
more. some key aspects of bytecode verification
JAVA 13 JAVA 14
1. Bytecode Structure: The verification process ensures that the bytecode 4. Static Variables: The Class Area also includes memory space for static
conforms to the structural rules defined by the JVM specification. It checks variables, which are shared among all instances of a class. Static variables
for valid instructions, correct operand types, proper control flow, and are initialized when the class is loaded and can be accessed without
exception handling. creating an instance of the class.
2. Type Safety: Verification verifies the type safety of the bytecode by The Class Area provides a centralized location for class-level information and
examining the data types used in the bytecode instructions. It ensures that allows efficient sharing of data among multiple instances of the same class. It is
operations are performed on appropriate data types and that type managed by the JVM's garbage collector, which handles the allocation and
conversions are valid. deallocation of memory within the Class Area.
Class Area (Method Area): 2. Last-In-First-Out (LIFO): The Java Stack follows the Last-In-First-Out
The Class Area, also known as the Method Area, is a runtime data area within principle, meaning that the most recently pushed item onto the stack is the
the JVM where class-level structures and metadata are stored. It is shared first to be popped off when a method call completes.
among all threads and is created when the JVM starts up. Here are some key 3. Memory Management: The Java Stack is managed automatically by the
features of the Class Area: JVM. Memory for stack frames is allocated and deallocated as method calls
1. Class Structures: The Class Area stores information about classes and are made and completed. The stack memory is typically smaller in size
interfaces loaded by the JVM. This includes the fully qualified names of the compared to the heap memory.
classes, superclass and interface references, field information, method 4. Thread-Specific: Each thread in a Java program has its own stack. This
bytecode, constant pool, and static variables. allows multiple threads to execute methods concurrently without interfering
2. Runtime Constant Pool: The Class Area contains a runtime representation with each other's stack frames.
of the constant pool, which is a table of symbolic references used by the The Java Stack is efficient for managing method calls and local variables
class. It stores strings, numeric constants, class and method references, and because of its simple and predictable nature. However, it has limited memory
more. compared to the Java Heap.
3. Method Bytecode: The Class Area holds the bytecode instructions for Java Heap:
methods defined in the loaded classes. These instructions are interpreted or The Java Heap is a region of memory used for dynamic memory allocation,
compiled to machine code for execution.
JAVA 15 JAVA 16
specifically for objects and arrays. Here are some key points about the Java based on object lifetimes. This allows for more efficient garbage collection by
Heap: focusing on short-lived objects in the young generation.
1. Object Storage: The Java Heap is where objects are allocated and Garbage Collection automates memory management, relieving developers from
deallocated during the program's execution. Objects are created using the manual memory deallocation. It helps prevent memory leaks and ensures
"new" keyword and reside in the heap until they are no longer referenced. efficient memory utilization.
3. Stop-The-World: Garbage Collection typically involves a "stop-the-world" Attempts to use a null reference as the receiver of a method invocation or
event where normal program execution is temporarily paused while garbage source of a field cause a NullPointerException to be thrown.
collection takes place. During this time, the JVM examines and collects
garbage objects, and other threads are halted.
Security Architecture:
4. Generational Collection: Many modern JVMs use generational garbage The security architecture of the JVM encompasses the design principles,
collection, where the heap is divided into different generations (young, old) mechanisms, and features that ensure the security of Java applications. It
JAVA 17 JAVA 18
provides a layered approach to protect the integrity, confidentiality, and security policy is typically defined in a security policy file, which is loaded by the
availability of resources within the JVM. Here are key aspects of the JVM's JVM during application startup.
security architecture:
5. Secure Communication: The JVM supports secure communication protocols Class loaders play a role in enforcing security constraints by managing
and APIs, such as HTTPS, SSL/TLS, and cryptographic libraries. These the loading and access of classes and resources.
enable secure client-server communication, data encryption, and The Java Security Manager, along with the security policy, defines the
authentication to protect sensitive information during transmission. permissions and restrictions for different code sources. Class loaders
Security Policy: are responsible for implementing these security policies by loading
The security policy in the JVM defines the permissions and access controls for classes in accordance with the defined constraints.
Java applications. It specifies the rules and restrictions that determine what 4. Security Manager and Class Loaders:
operations an application can perform and what resources it can access. The
JAVA 19 JAVA 20
The Security Manager, as part of the JVM's security architecture, 2. Access Control: The sandbox model enforces access control policies to
interacts with class loaders to enforce security policies and permissions. regulate the interactions between the untrusted code and the system
resources. It specifies what resources the code can access, such as the file
When a class is loaded, the Security Manager is consulted to determine
system, network, or system properties. By controlling these access rights,
whether the class is granted the necessary permissions to perform
the sandbox model limits the potential damage that untrusted code can
certain operations or access specific resources.
cause.
Class loaders assist in this process by ensuring that classes and code
3. Security Manager: The Security Manager, a component of the JVM's
sources adhere to the security policies defined by the Security Manager.
security architecture, plays a central role in implementing the sandbox
5. Custom Class Loaders: model. It acts as a gatekeeper, enforcing the security policies and
Java allows the creation of custom class loaders that can be used to permissions defined for the untrusted code. The Security Manager checks
extend or modify the default class loading behavior. each operation performed by the code against the defined security policies
and determines whether it is allowed or denied.
Custom class loaders can introduce additional security measures. For
example, they can implement bytecode verification or perform extra 4. Security Policies: The security policies in the sandbox model define the
security checks before loading classes from untrusted sources. permissions and restrictions for untrusted code. These policies are typically
specified in a security policy file, which is loaded by the JVM. The policies
By controlling the loading and initialization of classes, class loaders contribute to
can specify the allowable actions, such as reading or writing files, creating
the security of Java applications. They provide isolation, enable the enforcement
network connections, or accessing certain system properties. The Security
of security policies, and allow for customizations to enhance security measures.
Manager uses these policies to determine whether the requested actions are
It's important to note that proper configuration and implementation of class permitted.
loaders, along with adherence to secure coding practices, are essential for
5. Code Verification: To ensure the safety of the sandboxed environment,
maintaining a secure runtime environment.
untrusted code undergoes bytecode verification before execution. Bytecode
verification checks the code for adherence to specified rules and constraints,
including type safety, proper stack manipulation, and method invocations.
Sandbox model This verification step helps prevent the execution of potentially malicious or
The sandbox model is a security mechanism implemented in the Java Virtual malformed code.
Machine (JVM) to restrict untrusted code from accessing sensitive resources 6. Limited Permissions: The sandbox model grants only limited permissions to
and performing potentially harmful operations. It creates a controlled execution untrusted code. It typically allows access to a restricted subset of the Java
environment for untrusted code, ensuring that it operates within predefined API, preventing the code from invoking sensitive operations or accessing
boundaries. Here are the key aspects of the sandbox model: critical system resources. This limitation helps contain any potential damage
1. Isolation: The sandbox model achieves isolation by restricting the caused by the code and prevents unauthorized access to sensitive
capabilities of untrusted code and preventing it from accessing certain information.
resources or performing privileged operations. This isolation ensures that
7. Controlled Execution Environment: The sandbox model ensures that
the untrusted code cannot interfere with or compromise the integrity of the
untrusted code runs in a controlled execution environment. It sets up
underlying system or other applications.
boundaries that prevent the code from modifying system configurations,
JAVA 21 JAVA 22
accessing protected resources, or executing native code. By confining the 2. Reference Types:
code within the sandbox, the model provides a layer of protection against
Classes: Objects of user-defined classes.
malicious actions.
Arrays: Ordered collections of elements.
The sandbox model is particularly useful when executing untrusted code, such
as applets in web browsers or code from unknown sources. It allows for the Interfaces: Reference types that define a contract for classes
execution of potentially risky code while mitigating the risks and maintaining the implementing them.
overall security of the system. Strings: Represents sequences of characters.
It's worth noting that the effectiveness of the sandbox model relies on proper Literals:
configuration, adherence to security best practices, and regular updates to Literals are constant values that are directly written into your code. They
address potential vulnerabilities in the JVM. represent specific values of different data types.
For example:
Java Fundamentals: Data Types, Literals, and Variables Character literals: 'A', '\n', '\u0065'
Java is a statically-typed programming language, which means that you need to String literals: "Hello, World!"
declare the type of a variable before using it. Java provides several built-in data Variables:
types to store different kinds of values. Let's explore the fundamentals of data Variables are named memory locations used to store data. Before using a
types, literals, and variables in Java: variable, you must declare it with its data type. Here's the syntax to declare a
Data Types: variable:
Java has two categories of data types: primitive types and reference types.
JAVA 23 JAVA 24
For example: objects. They provide a way to encapsulate primitive values and provide
additional functionality through methods defined in the wrapper class. The
int age = 25; wrapper classes are part of the java.lang package and include the following:
double salary = 5000.0;
boolean isStudent = true; 1. Boolean: Represents the boolean primitive type.
age = 30;
8. Character: Represents the char primitive type.
salary = 5500.0;
isStudent = false;
Wrapper classes are commonly used when you need to perform operations such
as converting a primitive type to a string, parsing a string to a primitive type, or
using collections that require objects rather than primitives.
Java supports type inference with the introduction of the var keyword in Java
10. It allows the compiler to infer the data type based on the assigned value. For example, to convert an int to a String, you can use the Integer wrapper
class:
For example:
Arrays:
Variables can be used in expressions and can be reassigned with new values
Arrays in Java are used to store multiple elements of the same type. They
throughout the program.
provide a way to work with collections of values in a structured manner. Here are
Remember to follow the naming conventions for variables, such as starting with some key points about arrays in Java:
a lowercase letter and using camel case (e.g., myVariable).
1. Declaration and Initialization:
Understanding data types, literals, and variables is crucial for writing Java
Arrays are declared using square brackets ([]).
programs. It enables you to store and manipulate different kinds of data in your
applications. You specify the data type followed by the variable name and square
brackets indicating the array dimensions.
JAVA 25 JAVA 26
// Declaration and initialization for (int number : numbers) {
int[] numbers = {1, 2, 3, 4, 5}; System.out.println(number);
}
// Declaration and later initialization
int[] numbers;
numbers = new int[] {1, 2, 3, 4, 5};
Arrays provide a convenient way to work with collections of values in Java. They
allow efficient storage and retrieval of data and are extensively used in various
1. Accessing Array Elements: programming scenarios.
You can retrieve or modify the value at a specific index using the array
Operators
variable and the index in square brackets.
1. Arithmetic Operators:
int thirdNumber = numbers[2]; // Accessing the third element Addition (+): Adds two operands.
numbers[0] = 10; // Modifying the first element
The length of an array is determined by the number of elements it can Subtraction (-): Subtracts the second operand from the first.
hold.
The length of an array can be obtained using the length property. int difference = 7 - 2; // difference is 5
int arrayLength = numbers.length; // Retrieves the length of the array Multiplication (*): Multiplies two operands.
JAVA 27 JAVA 28
int count = 5; boolean result = (true && false); // result is false
count++; // count is now 6
count--; // count is now 5
2. Assignment Operators:
boolean result = (true || false); // result is true
Assignment (=): Assigns the value of the right operand to the left
operand.
Logical NOT (!): Negates the value of an operand.
Compound Assignment Operators (e.g., +=, -=, *=, /=): Performs the
operation and assigns the result to the left operand. 5. Bitwise Operators: (Note: Examples below use integer values)
3. Comparison Operators:
Bitwise OR (|): Performs a bitwise OR operation.
Equality (==): Tests if two operands are equal.
int result = 5 | 3; // result is 7
boolean isEqual = (10 == 5); // isEqual is false
Logical AND (&&): Returns true if both operands are true. int result = 5 << 2; // result is 20
JAVA 29 JAVA 30
Right Shift (>>): Shifts the bits of the left operand to the right by a specified
switch (expression) {
number of positions. case value1:
// code to be executed if expression matches value1
break;
int result = 20 >> 2; // result is 5 case value2:
// code to be executed if expression matches value2
break;
default:
1. Conditional (Ternary) Operator:
// code to be executed if expression doesn't match any case
}
Conditional Operator (condition ? expression1 : expression2): Evaluates
a condition and returns one of two expressions based on the result of
the condition. 2. Looping Statements:
while (condition) {
// code to be executed as long as the condition is true
Control of Flow }
Control Flow in Java refers to the order in which statements are executed in a
program. It allows you to make decisions, repeat statements, and break the Do-while loop: Similar to the while loop, but the condition is evaluated
normal flow of execution. There are several constructs in Java that help you after executing the block of code, so it always executes at least once.
control the flow of your program. Here are the main control flow constructs:
do {
1. Conditional Statements: // code to be executed
} while (condition);
If statement: Executes a block of code if a given condition is true.
JAVA 31 JAVA 32
Break statement: Terminates the execution of a loop or switch statement Classes and Instances
and transfers control to the next statement after the loop or switch. In Java, classes and instances are fundamental concepts of object-oriented
programming. Let's understand what they mean:
break;
1. Classes:
It provides the definition of how objects of that class should behave and
return value; interact with each other.
Classes are declared using the class keyword followed by the class
4. Branching Statements: name.
If-else if-else ladder: Allows you to check multiple conditions and Here's an example of a simple class named Person :
execute different blocks of code based on the first matching condition.
It is created from a class using the new keyword, and each instance has
These control flow constructs give you the ability to make decisions, repeat
its own set of attributes (instance variables) and can perform actions
code, and alter the flow of execution in your Java programs. By using these
(invoke methods) defined in the class.
constructs effectively, you can create programs that perform different actions
based on various conditions and iterate over data structures efficiently. Multiple instances of the same class can exist, each with its own state
(values of attributes).
JAVA 33 JAVA 34
Instances are created dynamically at runtime when the program needs final : The member's value cannot be changed.
them.
abstract : The member does not have an implementation and must
Here's an example of creating instances of the Person class: be overridden in subclasses.
person2.name = "Jane"; It is typically used when you need to create a class that implements an
person2.age = 30;
interface or extends a class in a concise manner.
// Invoking methods on instances
person1.sayHello(); // Output: Hello, my name is John Anonymous inner classes are often used for event handling or defining
person2.sayHello(); // Output: Hello, my name is Jane small, one-time-use classes.
By defining classes and creating instances, you can model and represent real- Runnable runnable = new Runnable() {
public void run() {
world entities or concepts in your Java programs. Classes provide the structure, // implementation of the run() method
and instances allow you to work with individual objects based on that structure. }
};
1. Class Member Modifiers: In the example above, an anonymous inner class is created that
Class member modifiers are keywords used to specify the accessibility implements the Runnable interface and provides an implementation for
and behavior of class members (fields, methods, nested classes, and the run() method.
constructors). 3. Interfaces:
Some commonly used modifiers include: An interface in Java defines a contract or a set of methods that a class
public : The member can be accessed from any other class. must implement.
private : The member can only be accessed within the same class. It is a collection of abstract methods, constants, and default methods
(methods with a default implementation).
protected : The member can be accessed within the same class,
subclasses, and same package. Interfaces are used to achieve abstraction and provide a way to define
common behavior that can be implemented by multiple classes.
static : The member belongs to the class itself rather than an
instance of the class.
JAVA 35 JAVA 36
A class implements an interface using the implements keyword and In the example above, the Animal class is declared as abstract with an
provides implementations for all the methods declared in the interface. abstract method sound() . The Cat class extends the Animal class and
provides an implementation for the sound() method.
Here's an example of an interface and its implementation:
These concepts - class member modifiers, anonymous inner classes, interfaces,
interface Shape { and abstract classes - are important elements in Java that allow you to define
void draw(); // Abstract method declaration and structure your code effectively. They provide flexibility, reusability, and
}
abstraction in your
class Circle implements Shape {
public void draw() {
// Implementation of the draw() method for Circle
}
}
Inheritance
Inheritance is a fundamental concept in object-oriented programming that allows
you to create new classes based on existing classes. It enables code reuse and
In the example above, the Shape interface declares an abstract method
the establishment of hierarchical relationships between classes. Inheritance is
draw() , and the Circle class implements that interface by providing an
achieved through the process of deriving new classes from existing classes,
implementation for the draw() method.
where the new classes inherit the properties and behavior of the existing
4. Abstract Classes: classes. Let's delve into the details of inheritance:
An abstract class is a class that cannot be instantiated and is meant to 1. Superclass and Subclass:
be subclassed.
Inheritance involves two main classes: the superclass (also known as
It can contain abstract methods (methods without an implementation) the base class or parent class) and the subclass (also known as the
and may also have concrete methods. derived class or child class).
Abstract classes provide a way to define common behavior and enforce The superclass is the existing class from which the subclass is derived.
certain methods to be implemented by subclasses.
The subclass inherits all the non-private fields and methods from the
To declare an abstract class, use the abstract keyword. superclass and can add its own unique fields and methods.
Here's an example of an abstract class and its subclass: The subclass can also override or extend the functionality of the
superclass methods.
abstract class Animal {
abstract void sound(); // Abstract method declaration 2. Inheritance Syntax:
}
To establish an inheritance relationship, the extends keyword is used in
class Cat extends Animal {
Java.
void sound() {
// Implementation of the sound() method for Cat
The subclass is declared with the extends keyword followed by the
}
} name of the superclass.
Here's an example:
JAVA 37 JAVA 38
5. Access Modifiers in Inheritance:
class Superclass {
// superclass members The access modifiers ( public , private , protected , and default) play a
}
role in controlling the visibility of inherited members in the subclass.
class Subclass extends Superclass {
// subclass members In general, inherited fields and methods with public or protected access
} modifiers are accessible in the subclass.
JAVA 39 JAVA 40
class Superclass { class Superclass {
// superclass members // superclass members
} }
JAVA 41 JAVA 42
class Superclass { throw exception;
// superclass members
}
Example:
interface Interface1 {
// interface1 members
}
void divide(int dividend, int divisor) {
interface Interface2 { if (divisor == 0) {
// interface2 members throw new ArithmeticException("Division by zero");
} }
// Perform the division operation
class Subclass extends Superclass implements Interface1, Interface2 { }
// subclass members
}
2. throws Clause:
It's important to note that Java does not support direct multiple inheritance for The throws clause is used in the method declaration to indicate that the
classes, but it allows for implementing multiple interfaces, achieving a similar method may throw one or more types of exceptions.
effect. The choice of inheritance type depends on the specific requirements and It specifies the types of exceptions that can be thrown by the method,
design of your program. but it doesn't actually throw the exceptions itself.
Throw and Throws clauses When a method with a throws clause calls another method that throws a
checked exception, the calling method must handle or declare the
In Java, the throw and throws clauses are used to handle and propagate
exception using its own throws clause.
exceptions in a program. They play a crucial role in exception handling. Let's
understand these clauses in detail: Syntax:
1. throw Clause:
returnType methodName(parameters) throws exceptionType1, exceptionType2,
The throw clause is used to explicitly throw an exception from a method ... {
// Method body
or a block of code. }
Syntax: In the example above, the readFile method declares that it may throw
an IOException . Any method calling readFile must either handle the
JAVA 43 JAVA 44
IOException or declare it in its own throws clause. Use the throw keyword followed by an instance of your custom
exception class to throw the exception.
The throw clause is used to raise exceptions explicitly, while the throws clause
is used to declare the exceptions that a method can throw. Together, they Example:
facilitate exception handling and ensure that exceptions are appropriately caught
and handled in the program. void someMethod() throws CustomException {
if (/* some condition */) {
It's worth noting that checked exceptions (exceptions that are subclasses of throw new CustomException("Custom exception message");
Exception but not subclasses of RuntimeException ) must be declared using the }
}
throws clause or caught using a try-catch block, whereas unchecked exceptions
Once you have defined your custom exception class, you can throw
By creating your own exception classes, you can handle specific exceptional
instances of that exception when necessary.
situations in a more tailored and meaningful way. Custom exceptions allow you
JAVA 45 JAVA 46
to communicate and handle exceptional conditions specific to your application
StringBuffer sb = new StringBuffer("Hello");
domain. sb.append(" World"); // "Hello World"
sb.insert(5, ","); // "Hello, World"
Remember to follow Java naming conventions for custom exception class sb.delete(5, 7); // "Hello World"
names, and make sure to choose appropriate exception class hierarchy (e.g., sb.replace(6, 11, "Java"); // "Hello Java"
1. Creating a StringBuffer:
You can create a StringBuffer object using its empty constructor or by 4. Thread Safety:
passing an initial value to the constructor. StringBuffer is designed to be thread-safe, meaning it can be safely
StringBuffer sb1 = new StringBuffer(); // Empty StringBuffer However, this thread safety comes at the cost of performance due to the
StringBuffer sb2 = new StringBuffer("Hello"); // StringBuffer with initia
synchronization overhead.
l value
If you don't require thread safety, you can use the non-thread-safe
2. Modifying the StringBuffer: alternative, StringBuilder , which provides similar functionality but without
the synchronization.
StringBuffer provides methods to append, insert, delete, and replace
The append() method is used to add characters at the end of the existing While StringBuffer allows for efficient string manipulation, it can be less
content. performant compared to StringBuilder when used in a single-threaded
environment.
The insert() method is used to insert characters at a specific position.
The synchronization overhead in StringBuffer can impact performance,
The delete() method is used to remove characters from a specific especially when performing a large number of string modifications.
range.
If you're working in a single-threaded environment, consider using
The replace() method is used to replace characters in a specific range StringBuilder for better performance.
with new characters.
The StringBuffer class provides a convenient and efficient way to manipulate
Example: mutable strings in Java. It offers various methods for modifying the content of the
JAVA 47 JAVA 48
string and can be used in both single-threaded and multi-threaded scenarios.
String input = "Hello-World-Java";
StringTokenizer tokenizer = new StringTokenizer(input, "-");
Tokenizer
4. Counting Tokens:
The StringTokenizer class in Java is used to break a string into smaller tokens or
parts, based on a specified delimiter. It provides a simple and convenient way to You can use the countTokens() method to get the total number of tokens
tokenize strings. Here's an overview of the StringTokenizer class: remaining in the tokenizer.
To create a StringTokenizer object, you need to pass the input string and
the delimiter to its constructor. int count = tokenizer.countTokens();
String input = "Hello,World,Java"; You can specify a second parameter in the constructor as true to
StringTokenizer tokenizer = new StringTokenizer(input, ",");
enable empty token skipping.
Example:
2. Retrieving Tokens:
You can use the hasMoreTokens() method to check if there are more String input = "Hello,,World,,Java";
StringTokenizer tokenizer = new StringTokenizer(input, ",", true);
tokens available in the input string.
The nextToken() method is used to retrieve the next token from the input
6. Retrieving Delimiters:
string.
Example: You can use the nextDelimiter() method to retrieve the delimiters as
tokens.
You can change the delimiter by using the overloaded constructor or the
setDelimiter() method.
The StringTokenizer class provides a straightforward way to split a string into
Example: tokens using a specified delimiter. It is particularly useful when you need to
JAVA 49 JAVA 50
process delimited data or extract specific parts from a string. another page or closes the browser window.
However, note that the StringTokenizer class is considered legacy and has been Destroy: The applet's destroy() method is called when the applet is
largely replaced by the String.split() method and regular expressions ( Pattern no longer needed. It allows the applet to clean up resources and
and Matcher classes) for more advanced string parsing and splitting release any held references.
requirements.
The lifecycle methods can be overridden in the applet's code to perform
specific actions at each stage.
3. Security Concerns:
Applets
Applets are small Java programs that are designed to run within a web browser. Applets raised significant security concerns due to their ability to access
They were a popular way to add interactive content to web pages in the past, but system resources and execute potentially malicious code.
their usage has significantly decreased due to security concerns and the Security restrictions were imposed to prevent untrusted applets from
emergence of alternative technologies. Nevertheless, understanding applets and performing harmful actions on the user's machine.
their lifecycle can provide insights into the history of web development. Let's
Sandboxing: Applets run in a restricted environment known as the
delve into the details of applets, their lifecycle, and security concerns:
"sandbox" to prevent unauthorized access to system resources. They
1. Applets: have limited permissions and are prevented from performing potentially
Applets are Java programs that are embedded in HTML web pages and dangerous operations.
run in a sandboxed environment within a web browser. Security Manager: The Java security model introduced the concept of a
They were initially introduced as a way to provide dynamic and "security manager" that enforces security policies for applets. It controls
interactive content on the web. applet permissions and determines what applets can and cannot do.
Applets were rendered using the Java Applet Viewer or a web browser Permissions: Applets can be granted specific permissions to access
with Java plugin support. certain resources or perform restricted operations. These permissions
need to be explicitly granted by the user or the browser.
2. Applet Lifecycle:
4. Deprecation and Alternatives:
An applet goes through several stages during its lifecycle:
Due to security concerns, browser compatibility issues, and the rise of
Initialization: The applet is loaded by the browser, and its init()
alternative technologies like JavaScript, the usage of applets has
method is called. This method is used to perform initialization tasks
significantly declined.
such as setting up the user interface.
Modern web development favors HTML5, CSS, and JavaScript for
Start: The applet's start() method is called, indicating that the
creating interactive web content.
applet is about to start running.
Java Web Start: As an alternative to applets, Java Web Start was
Running: The applet is in the running state. Its paint() method is
introduced. It allows the delivery of full-fledged Java applications over
called to render the applet's visual output on the web page.
the web, eliminating the security restrictions imposed on applets.
Stop: The applet's stop() method is called when the applet is no
longer visible on the web page, such as when the user switches to
JAVA 51 JAVA 52
addMouseListener(this);
It's important to note that as of Java 11, the Java Plugin and Applet API have
}
been deprecated and removed from the Java Development Kit (JDK). Therefore,
public void start() {
applets are no longer supported in modern browsers.
// Start code
}
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
In Example 1, we have a simple applet that displays the message "Hello,
import java.awt.event.MouseListener; Applet!" using the paint() method. The init() , start() , stop() , and destroy()
public class InteractiveApplet extends Applet implements MouseListener {
methods are present to handle the applet lifecycle.
JAVA 53 JAVA 54
handle mouse events. The mouseClicked() method is overridden to change the Alternatively, you can create a thread by implementing the Runnable
background color and trigger a repaint of the applet. interface and passing an instance of it to the Thread constructor.
Here's an example:
Threads enable concurrent execution, where multiple parts of a program can then call the start() method on the Thread object.
execute independently and concurrently. Thread Priority:
By default, Java programs have at least one thread, known as the main Threads in Java can have different priorities, ranging from 1 (lowest) to 10
thread, which is created automatically when the program starts. (highest). The default priority is 5. Here are some points to know about thread
priority:
Threads can be used to perform tasks in the background, handle multiple
client requests, or improve the responsiveness of a user interface. Thread priorities are used by the thread scheduler to determine the order of
execution when multiple threads are ready to run.
Creating Threads:
In Java, there are two main ways to create threads: You can set the priority of a thread using the setPriority() method, passing
the desired priority as an argument.
Extending the Thread class:
Higher priority threads have a greater chance of being scheduled for
You can create a thread by extending the Thread class and overriding its
execution, but it is not guaranteed.
run() method, which contains the code to be executed by the thread.
Thread priority should be used with caution and should not be solely relied
Here's an example:
upon for critical operations.
JAVA 55 JAVA 56
Extending the Thread Class: Create a class that implements the Runnable interface.
As mentioned earlier, one way to create threads is by extending the Thread
Implement the run() method within the class, which contains the code to be
class. Here are some points to understand:
executed by the thread.
When extending the Thread class, you override the run() method to define
Instantiate a Thread object, passing an instance of your class as a
the behavior of the thread.
constructor argument.
By extending the Thread class, your class becomes a thread itself and can
Call the start() method on the Thread object to start the execution of the
be instantiated and started like any other thread.
thread.
However, this approach limits the flexibility of your class, as it does not allow
Here's an example to illustrate the usage of the Runnable interface:
for extending other classes.
If you've created a thread by extending the Thread class, you can simply class MyRunnable implements Runnable {
create an instance of your class and call the start() method on it. public void run() {
// Code to be executed by the thread
}
Example:
}
of MyRunnable and pass it to the Thread constructor. Finally, we start the thread by
calling the start() method.
Runnable Interface Benefits of Using the Runnable Interface:
The Runnable interface in Java provides an alternative way to create threads by Using the Runnable interface has several advantages over extending the Thread
encapsulating the code to be executed within a separate object. Here's an class directly:
overview of the Runnable interface:
Flexibility: Implementing the Runnable interface allows you to separate the
1. Definition and Purpose: thread's behavior from the class hierarchy. You can still extend other classes
The Runnable interface is defined in the java.lang package and contains a and implement multiple interfaces while defining the thread's behavior in a
single method called run() . Its purpose is to represent a task or unit of work separate Runnable object.
that can be executed by a thread.
Code Reusability: Since the thread's behavior is encapsulated in a Runnable
2. Implementing the Runnable Interface: object, you can reuse the object and share it among multiple threads if
To create a thread using the Runnable interface, follow these steps: needed.
JAVA 57 JAVA 58
Enhanced Thread Pooling: When utilizing thread pooling techniques, such Synchronize Threads:
as the Executor framework, using Runnable objects allows for more efficient To synchronize threads and ensure proper coordination, you can use methods
utilization of thread resources. like wait() , notify() , and notifyAll() . These methods must be called from
within a synchronized context (synchronized method or synchronized block).
By utilizing the Runnable interface, you can design your code to be more flexible,
Here's an overview:
modular, and scalable when dealing with multi-threaded scenarios.
wait() : Causes the current thread to release the lock and enter a waiting
state until another thread calls notify() or notifyAll() on the same object. It
Thread Synchronization:
should be used within a loop to check the condition that caused the thread to
In multi-threaded programming, thread synchronization is important to ensure
wait.
proper coordination and order of execution between threads. It helps prevent
notify() : Wakes up one of the threads that are waiting on the same object.
data inconsistency and race conditions. Java provides synchronization
mechanisms to achieve thread synchronization: The awakened thread can then compete for the lock and continue execution.
1. Synchronized Methods: notifyAll() : Wakes up all the threads that are waiting on the same object.
By using the synchronized keyword, you can declare a method as By using synchronization and the methods mentioned above, you can control the
synchronized. execution order and synchronization between threads, ensuring proper
concurrency and data consistency.
When a thread enters a synchronized method, it acquires the lock on the
object, and other threads must wait until the lock is released.
Sync Code Block:
Example:
In addition to synchronizing entire methods, Java also allows you to synchronize
specific blocks of code using synchronized code blocks. This gives you more
public synchronized void synchronizedMethod() {
// Synchronized method code
fine-grained control over synchronization. Here's how you can use sync code
} blocks:
1. Syntax:
2. Synchronized Blocks:
You can also synchronize specific blocks of code using the synchronized synchronized (object) {
// Synchronized code block
keyword with an object as a lock. }
The lock ensures that only one thread can execute the synchronized
block at a time. 2. Object Lock:
Example: The synchronized code block requires an object as a lock to coordinate
the execution of threads.
synchronized (lockObject) {
// Synchronized block code
The lock can be any object, but it is commonly a shared object that the
} threads need to synchronize on.
JAVA 59 JAVA 60
Only one thread can hold the lock at a time, and other threads will wait to ensure that only one thread can modify the count variable at a time.
until the lock is released. Overriding Synchronized Methods:
3. Benefits: When dealing with inheritance and overriding methods in Java, there are a few
things to consider when it comes to synchronized methods:
Sync code blocks allow you to synchronize only the critical section of
code that needs synchronization, rather than the entire method. 1. Overriding a Synchronized Method:
This approach can lead to improved performance by reducing the If a superclass has a synchronized method, and a subclass overrides
amount of time other threads spend waiting for the lock. that method, the subclass's method is not automatically synchronized.
Here's an example to illustrate the usage of sync code blocks: The subclass can choose to synchronize the method explicitly if
synchronization is required.
public class SyncCodeBlockExample { 2. Adding Synchronization to Overridden Methods:
private static int count = 0;
private static final Object lock = new Object();
If a subclass wants to synchronize an overridden method, it can do so
public static void increment() { by using the synchronized keyword in the method declaration.
synchronized (lock) {
count++; Example:
}
}
class SuperClass {
public static void main(String[] args) { public synchronized void synchronizedMethod() {
Runnable runnable = () -> { // Superclass synchronized method
for (int i = 0; i < 1000; i++) { }
increment(); }
}
}; class SubClass extends SuperClass {
@Override
Thread thread1 = new Thread(runnable); public synchronized void synchronizedMethod() {
Thread thread2 = new Thread(runnable); // Subclass synchronized method
}
thread1.start(); }
thread2.start();
try {
thread1.join(); In the example above, the SuperClass has a synchronized method. The SubClass
thread2.join(); overrides the method and adds the synchronized keyword to synchronize it
} catch (InterruptedException e) {
e.printStackTrace(); again.
}
In the example above, we have a shared count variable that we want to In Java, threads can communicate with each other using the methods wait() ,
increment concurrently. We use a synchronized code block with the lock object notify() , and notifyAll() . These methods are part of the Object class and can
JAVA 61 JAVA 62
be used to coordinate the execution of threads. Here's an explanation of how Example:
these methods work:
synchronized (sharedObject) {
1. wait():
// Update shared data or perform some task
sharedObject.notifyAll(); // Notifies all waiting threads
The wait() method causes the current thread to release the lock on the
}
object and enter a waiting state until another thread calls notify() or
notifyAll() on the same object.
Thread communication using wait() , notify() , and notifyAll() is typically used
When a thread calls wait() , it relinquishes the lock and allows other in scenarios where one thread needs to wait for a specific condition to be met by
threads to continue execution. The thread remains in a waiting state until another thread before proceeding.
it receives a notification to resume.
To ensure proper usage of these methods, the following guidelines are
Example: recommended:
Call wait() , notify() , and notifyAll() only from within synchronized blocks
synchronized (sharedObject) {
while (condition) { or synchronized methods.
sharedObject.wait(); // Waits until notified
} Use a loop with wait() to check the condition that caused the thread to wait.
// Continue execution after receiving notification This helps prevent spurious wake-ups.
}
Make sure the threads involved are accessing the same shared object for
synchronization.
2. notify():
Thread communication is a powerful mechanism for coordination and
The notify() method wakes up one thread that is waiting on the same
synchronization between threads. It enables efficient and controlled inter-thread
object. It allows that thread to continue execution after it regains the
communication in complex concurrent scenarios.
lock.
If multiple threads are waiting, the thread that gets the notification is
arbitrary and depends on the thread scheduler.
AWT Components
Example: AWT (Abstract Window Toolkit) is a set of classes and components in Java used
for creating graphical user interfaces (GUIs) for desktop applications. AWT
synchronized (sharedObject) { provides a collection of UI components that allow developers to create windows,
// Update shared data or perform some task
sharedObject.notify(); // Notifies one waiting thread buttons, labels, text fields, and other elements to build interactive user
} interfaces. Here are some commonly used AWT components:
1. Frame:
3. notifyAll():
The Frame class represents a top-level window with a title bar and
The notifyAll() method wakes up all threads that are waiting on the borders.
same object. It allows all the waiting threads to continue execution after
It is the main container for building the application window.
they regain the lock.
JAVA 63 JAVA 64
Example: It is used for accepting user input or displaying dynamic text.
Example:
Frame frame = new Frame("My Frame");
The Panel class represents a container that can hold other components. 6. TextArea:
It is used to group and organize components within a window. The TextArea class represents a multi-line text area where users can
enter or view large amounts of text.
Example:
It is used for accepting or displaying longer text content.
Panel panel = new Panel(); Example:
It is used to perform specific actions in response to user interaction. The Checkbox class represents a component that can be checked or
unchecked.
Example:
It is used for presenting options or boolean values.
Button button = new Button("Click me");
Example:
JAVA 65 JAVA 66
1. Component Class: setLayout(LayoutManager manager) : Sets the layout manager for the
container to define how components are arranged.
The Component class is an abstract class that serves as the base class
for all AWT components. validate() : Forces the container to re-layout its components.
It represents a visual entity that can be added to a graphical user getComponent(int index) : Returns the component at the specified
Examples of subclasses of Component include Button, Label, TextField, getComponents() : Returns an array of all the components in the
etc. container.
Key methods and properties of the Component class include: The Component class and the Container class provide the basic functionality for
creating and managing GUI components in AWT. By subclassing these classes
setSize(int width, int height) : Sets the size of the component.
and utilizing their methods and properties, you can build complex and interactive
setLocation(int x, int y) : Sets the position of the component within user interfaces in Java.
its container.
setVisible(boolean visible) : Sets the visibility of the component. Layout Manager Interface and Default Layouts:
In Java's AWT (Abstract Window Toolkit), the Layout Manager interface and its
setEnabled(boolean enabled) : Sets whether the component is enabled
various implementations are used to define how components are arranged and
or disabled.
displayed within containers. The Layout Manager provides automatic positioning
setBackground(Color color) : Sets the background color of the and sizing of components, ensuring that they adapt well to different window
component. sizes and screen resolutions. Let's explore the Layout Manager interface and
setForeground(Color color) : Sets the foreground color (text color) of some of its default layouts:
the component. 1. Layout Manager Interface:
2. Container Class: The LayoutManager interface is the base interface for all layout managers
The Container class is a subclass of Component and serves as a in AWT.
container for other components. It defines the methods that layout managers must implement to arrange
It represents a rectangular area that can hold and organize other components within containers.
components. Key methods of the LayoutManager interface include:
Examples of subclasses of Container include Panel, Frame, and void addLayoutComponent(String name, Component comp) : Adds a named
Window. component to the layout.
Key methods and properties of the Container class include: void removeLayoutComponent(Component comp) : Removes a component
add(Component comp) : Adds a component to the container. from the layout.
remove(Component comp) : Removes a component from the container. Dimension preferredLayoutSize(Container parent) : Returns the preferred
size of the layout.
JAVA 67 JAVA 68
Dimension minimumLayoutSize(Container parent) : Returns the minimum Example:
size of the layout.
Container container = new Container();
void layoutContainer(Container parent) : Arranges the components
container.setLayout(new GridLayout(rows, columns));
within the container.
2. Default Layouts:
GridBagLayout:
AWT provides several default layout managers that implement the
LayoutManager interface. These layouts handle the positioning and sizing of The GridBagLayout provides a flexible and powerful layout
components in different ways. Here are some commonly used default management system.
layouts: It uses constraints to define the positioning and sizing of
FlowLayout: components.
Example: These are just a few examples of default layouts available in AWT. Each
layout manager has its own set of properties and behavior, allowing you to
Container container = new Container(); choose the most appropriate one for your GUI design.
container.setLayout(new FlowLayout());
By utilizing the Layout Manager interface and selecting the appropriate layout
manager, you can create well-structured and responsive user interfaces in Java.
BorderLayout:
The BorderLayout divides the container into five regions: North, Insets and Dimensions:
South, East, West, and Center. In Java's AWT (Abstract Window Toolkit), Insets and Dimensions are classes
Components are placed in these regions, and the layout manages that provide useful functionality for managing the size and positioning of
their sizing and positioning. components within containers. Let's explore these classes in more detail:
Example: 1. Insets:
GridLayout: Insets are often used to control the spacing between components or to
create padding around a container.
The GridLayout arranges components in a grid of rows and columns.
Key methods of the Insets class include:
All components are evenly sized to fit the available space.
JAVA 69 JAVA 70
int top : Represents the top inset (distance from the top edge of the Border Layout:
container).
The BorderLayout is a default layout manager provided by AWT.
int left : Represents the left inset (distance from the left edge of
It divides the container into five regions: North, South, East, West, and
the container).
Center.
int bottom : Represents the bottom inset (distance from the bottom
Each region can hold only one component.
edge of the container).
The components added to the BorderLayout are automatically resized to fit
int right : Represents the right inset (distance from the right edge of
their respective regions.
the container).
Example usage:
Example usage of Insets :
2. Dimensions:
It's worth noting that both Insets and Dimension are immutable classes, Grid Layout:
meaning their values cannot be changed once set. To modify their values, The GridLayout is a default layout manager provided by AWT.
you would typically create new instances with the desired values.
It arranges components in a grid of rows and columns.
These classes are often used in conjunction with layout managers to control the
All components are evenly sized to fit the available space.
size, spacing, and positioning of components within containers. They provide a
convenient way to manage the visual aspects of GUI design. Example usage:
JAVA 71 JAVA 72
Container container = new Container(); Container container = new Container();
container.setLayout(new GridLayout(rows, columns)); container.setLayout(new GridBagLayout());
container.add(component1); GridBagConstraints constraints = new GridBagConstraints();
container.add(component2); constraints.gridx = 0;
constraints.gridy = 0;
container.add(component1, constraints);
constraints.gridx = 1;
These layout managers are commonly used in Java GUI applications to organize constraints.gridy = 0;
components within containers. By selecting the appropriate layout manager and container.add(component2, constraints);
adding components to the specified regions or grid cells, you can create visually
appealing and responsive user interfaces.
AWT Events:
Card Layout: AWT provides a set of event classes and interfaces to handle user
The CardLayout is a default layout manager provided by AWT. interactions with GUI components.
It allows multiple components to be stacked on top of each other, with only Some commonly used AWT events include:
one component visible at a time. ActionEvent: Generated when a button or menu item is clicked.
It is often used to create multi-pane interfaces, such as wizards or tabbed MouseEvent: Generated when the mouse is moved or clicked.
views.
KeyEvent: Generated when a key is pressed or released.
Components are added to the CardLayout using unique names, and you can
WindowEvent: Generated when a window is opened, closed, or resized.
switch between components using methods like next() , previous() , or
show() . To handle AWT events, you need to implement event listener interfaces and
register them with the appropriate components using methods like
Example usage:
addActionListener() , addMouseListener() , or addKeyListener() .
It offers fine-grained control over component placement using constraints Event Models:
such as grid coordinates, weights, and alignments. In Java, there are different event models that define how events are generated,
Example usage: dispatched, and handled in graphical user interfaces (GUIs). The two main event
JAVA 73 JAVA 74
models used in Java are the AWT event model and the Swing event model. Let's EventListenerList: A container class to manage Swing event
explore each of them: listeners.
1. AWT Event Model: SwingUtilities: A utility class for working with Swing components and
threads.
The AWT (Abstract Window Toolkit) event model is the original event
model in Java. Both event models provide a similar set of event classes and interfaces, but the
Swing event model offers more features and flexibility for GUI development.
It is based on the delegation model, where components delegate event
handling to their registered listeners. To handle events in Java, you need to implement event listener interfaces and
register them with the appropriate components. Common event listener
In the AWT event model, events are generated by the operating system
interfaces include ActionListener, MouseListener, KeyListener, etc. The actual
and delivered to the appropriate components.
event handling code is written within the implemented listener methods.
The event handling process involves three main steps: event generation,
Example usage:
event dispatching, and event handling.
The Swing event model introduces the concept of "pluggable look and
feel" (PLAF) and "lightweight" components.
By understanding the event models and utilizing event listeners, you can create
Swing events are dispatched by the Swing event-dispatching thread interactive and responsive GUI applications in Java.
(EDT), which ensures that all GUI events are handled in a single thread.
Listeners:
Key classes in the Swing event model include:
In Java, listeners are interfaces that define callback methods to handle specific
EventObject: The base class for all Swing events.
events. They are used in event-driven programming to capture and respond to
EventListener: The base interface for all Swing event listeners. user actions or system events. Here are the key points about listeners:
JAVA 75 JAVA 76
Listeners are implemented as interfaces in Java. Each listener interface The term "Class Listener" refers to a design pattern where a separate class is
defines one or more methods that need to be implemented to handle created to implement a listener interface. This approach provides better
specific events. modularity and separation of concerns. Instead of using anonymous inner
classes or implementing the listener interface in the same class, you create a
Listeners follow the Observer design pattern, where the listener objects
separate class dedicated to handling events.
register themselves with the event source to receive notifications when the
corresponding events occur. Here's an example of implementing a class listener:
When an event occurs, the event source invokes the appropriate methods 1. Define a listener class that implements the desired listener interface and
on the registered listeners, passing relevant information about the event. overrides the corresponding event handling methods.
Listeners decouple the event source from event handling logic, allowing for
public class MyActionListener implements ActionListener {
flexible and modular design of event-driven systems.
public void actionPerformed(ActionEvent e) {
// Handle the action event here
Here are a few commonly used listeners in Java: }
}
1. ActionListener: Used to handle action events, such as button clicks or menu
item selections.
1. Instantiate the listener class and register it with the event source.
2. MouseListener: Handles mouse-related events, including mouse clicks,
movements, and enters/exits.
MyActionListener listener = new MyActionListener();
3. KeyListener: Deals with keyboard events, such as key presses, releases, button.addActionListener(listener);
and typing.
4. ItemListener: Listens to item events, commonly used with checkboxes or Using class listeners allows for cleaner code organization, improved reusability,
radio buttons. and easier maintenance, especially when multiple components need to share
the same event handling logic.
5. FocusListener: Responds to focus events when a component gains or loses
focus.
Adapters:
6. WindowListener: Handles window-related events, like opening, closing, or In Java, adapters are classes that provide default implementations for listener
resizing of windows. interfaces. They allow you to implement only the methods you need, rather than
Example usage of ActionListener: having to provide empty implementations for all methods in the interface.
Adapters are useful when you want to listen to specific events and avoid writing
unnecessary code. Here are the key points about adapters:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Handle button click event
Adapters are classes that implement a listener interface and provide default
} implementations for all the methods in the interface.
});
The adapter class acts as a bridge between the event source and the
listener, allowing you to override only the methods you are interested in.
Class Listener:
JAVA 77 JAVA 78
By using adapters, you can avoid implementing all methods of the listener
Object source = event.getSource();
interface, which can save time and reduce code clutter.
1. Instantiate the adapter class and register it with the event source.
Using adapters simplifies event handling code, especially when you are
interested in handling a specific subset of events provided by a listener interface. 1. isTemporary(): Returns true if the focus change is temporary, such as when
It allows you to focus on the events that matter to you without having to a popup or dialog receives temporary focus.
implement unnecessary methods.
boolean temporary = event.isTemporary();
Action Event Methods:
The ActionEvent class represents an action event, which is typically generated
by user actions like button clicks or menu item selections. It provides useful Key Event Methods:
methods to retrieve information about the event. Here are some commonly used The KeyEvent class represents keyboard events, including key presses,
methods of the ActionEvent class: releases, and typed characters. It provides methods to retrieve information about
the event. Here are some commonly used methods of the KeyEvent class:
1. getSource(): Returns the object that generated the event. Useful when
multiple components share the same ActionListener. 1. getKeyCode(): Returns the unique code for the key that triggered the event.
JAVA 79 JAVA 80
mouseExited(MouseEvent e): Invoked when the mouse exits a
int keyCode = event.getKeyCode();
component.
mouseEntered(MouseEvent e): Invoked when the mouse enters a public void mouseDragged(MouseEvent e) {
// Handle mouse dragged event
component. }
}
JAVA 81 JAVA 82
}
windowClosing(WindowEvent e): Invoked when the user attempts to close You can then attach the window listener to a window object using the add
the window. WindowListener() method.
windowClosed(WindowEvent e): Invoked when the window has been closed.
frame.addWindowListener(new MyWindowListener());
windowIconified(WindowEvent e): Invoked when the window is minimized
(iconified).
By implementing the appropriate listener interfaces and their methods, you can
windowDeiconified(WindowEvent e): Invoked when the window is restored
respond to user interactions with the mouse and handle various window-related
from a minimized state.
events in your Java programs.
windowActivated(WindowEvent e): Invoked when the window becomes the
active window.
JAVA 83 JAVA 84
e.printStackTrace();
Example of reading from a file using FileInputStream:
}
JAVA 85 JAVA 86
Data Input and Output Stream: Example of using PrintStream to write to console:
DataInputStream and DataOutputStream classes are used for reading and
writing primitive data types from/to a stream. They provide methods to read and import java.io.PrintStream;
write data in a machine-independent format. These classes are particularly public class PrintStreamExample {
useful when you need to exchange data between different platforms or systems. public static void main(String[] args) {
PrintStream ps = System.out;
Example of using DataOutputStream: ps.println("Hello, World!");
ps.printf("The value of pi is %.2f", Math.PI);
ps.close();
}
try (FileOutputStream fos = new FileOutputStream("file.dat");
}
DataOutputStream dos = new DataOutputStream(fos)) {
int intValue = 42;
double doubleValue = 3.14;
dos.writeInt(intValue); In this example, we create a PrintStream object ps which represents the
dos.writeDouble(doubleValue);
} catch (IOException e) {
standard output stream. We use the println method to print a line of text to the
e.printStackTrace(); console, and the printf method to print formatted text, including the value of pi
}
with two decimal places.
import java.io.IOException;
The DataInputStream and DataOutputStream classes allow you to write and import java.io.RandomAccessFile;
read data in a specific format, ensuring consistency across different platforms.
public class RandomAccessFileExample {
These are some of the concepts and classes related to stream filters, buffered public static void main(String[] args) {
try (RandomAccessFile file = new RandomAccessFile("data.txt", "rw")) {
streams, and data input/output streams in Java. They provide additional // Writing data
functionalities and enhancements to the basic input/output stream operations. file.writeInt(42);
file.writeDouble(3.14);
JAVA 87 JAVA 88
} catch (IOException e) {
database vendor provides its own JDBC driver that you need to include
e.printStackTrace();
} in your project.
}
} Establish a connection: Use the DriverManager.getConnection() method to
establish a connection to the database by providing the database URL,
username, and password.
In this example, we create a RandomAccessFile object file with the file name
"data.txt" and mode "rw" (read-write). We write an integer value and a double Execute SQL statements: Create a Statement or PreparedStatement object
value to the file using the writeInt and writeDouble methods. Then, we seek to from the Connection and execute SQL queries or updates using
the beginning of the file using the seek method. Finally, we read the values back executeQuery() or executeUpdate() methods.
from the file using the readInt and readDouble methods.
Process the results: If executing a query, retrieve the results using the
RandomAccessFile provides flexibility in accessing specific parts of a file, ResultSet object and process the data as needed.
making it useful for scenarios where you need to read or modify data at arbitrary
Close the resources: Close the ResultSet, Statement, and Connection
positions within a file.
objects after you have finished working with them.
JDBC (Database connectivity with MS-Access, Oracle, MS- Example of connecting to a database and executing a query using JDBC:
SQL Server)
JDBC (Java Database Connectivity) is a Java API that provides a standard way import java.sql.*;
to interact with relational databases. It enables Java applications to connect to a public class JDBCTest {
database, execute SQL queries, retrieve and manipulate data, and manage public static void main(String[] args) {
String jdbcUrl = "jdbc:mysql://localhost:3306/mydatabase";
database transactions. Here's an overview of JDBC and how it can be used to String username = "myuser";
connect to different databases: String password = "mypassword";
Statement: Used to execute SQL queries or updates in the database. } catch (SQLException e) {
e.printStackTrace();
ResultSet: Represents the result of a query. It allows you to retrieve and }
}
manipulate data returned from the database. }
Load the JDBC driver: Before connecting to a database, you need to 1. Database-specific Drivers:
load the appropriate JDBC driver class using Class.forName() . Each
JAVA 89 JAVA 90
try (FileOutputStream fileOut = new FileOutputStream("person.ser");
MS-Access: To connect to an MS-Access database, you need to use the
ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
JDBC-ODBC Bridge driver. This driver acts as a bridge between the out.writeObject(person);
System.out.println("Object serialized successfully.");
JDBC API and the ODBC API. You'll need to set up the ODBC data
} catch (IOException e) {
source for your MS-Access database and use it in the JDBC URL. e.printStackTrace();
}
Oracle: To connect to an Oracle database, you need to download and
// Deserialize the object from the file
include the Oracle JDBC driver in your project. The JDBC URL typically try (FileInputStream fileIn = new FileInputStream("person.ser");
includes the database host, port, service name, and ObjectInputStream in = new ObjectInputStream(fileIn)) {
Person deserializedPerson = (Person) in.readObject();
username/password. System.out.println("Deserialized object: " + deserializedPerson);
} catch (IOException | ClassNotFoundException e) {
MS-SQL Server: To connect to an MS-SQL Server database, you need e.printStackTrace();
to download and include the SQL Server JDBC driver in your project. }
}
The JDBC URL typically includes the database host, port, database }
name, and username/password.
class Person implements Serializable {
Note: The specific details of connecting to each database may vary, so refer to private String name;
private int age;
the documentation and JDBC driver documentation provided by the respective
database vendor for the exact configurations and usage. public Person(String name, int age) {
this.name = name;
These are some of the concepts and steps involved in using JDBC for database this.age = age;
}
connectivity in Java, including connecting to different databases such as MS-
Access, Oracle, and MS-SQL Server. // Getters and setters
@Override
Object Serialization public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
Object serialization in Java refers to the process of converting an object into a }
}
stream of bytes, which can be written to a file or transmitted over a network.
Serialization allows objects to be saved or transmitted and later deserialized
back into objects. This is useful for scenarios such as persisting object state, In this example, the Person class implements the Serializable interface, which
sending objects over a network, or storing objects in a database. allows instances of the class to be serialized and deserialized. The Person object
To make a class serializable, it needs to implement the Serializable interface, is serialized by writing it to a file using ObjectOutputStream , and then it is
which is a marker interface with no methods. By default, all of the class's non- deserialized by reading from the file using ObjectInputStream . The deserialized
transient instance variables are serialized. Here's an example: object is cast back to the Person type.
Sockets
import java.io.*;
Sockets in Java provide a way to establish communication channels between
public class SerializationExample {
public static void main(String[] args) {
two different programs running on the same machine or over a network. They
// Create an object to serialize facilitate client-server communication by allowing data to be sent and received
Person person = new Person("John Doe", 30);
JAVA 91 JAVA 92
try (Socket socket = new Socket("localhost", 1234);
across network connections. Java provides the Socket and ServerSocket classes
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
to handle network communication using sockets. BufferedReader in = new BufferedReader(new InputStreamReader(socket.g
etInputStream()));
Client Socket: The Socket class represents a client-side socket that initiates BufferedReader stdIn = new BufferedReader(new InputStreamReader(Syste
m.in))) {
a connection to a server. It provides methods to establish a connection, send
data to the server, and receive data from the server. String userInput;
while ((userInput = stdIn.readLine()) != null) {
Server Socket: The ServerSocket class represents a server-side socket that out.println(userInput);
System.out.println("Client: Sent to server: " + userInput);
listens for incoming client connections. It provides methods to accept client String response = in.readLine();
connections and create individual Socket objects for each client connection. System.out.println("Client: Received from server: " + response);
}
The server can then send and receive data with the client using the Socket } catch (UnknownHostException e) {
object. e.printStackTrace();
} catch (IOException e) {
Here's an example of a simple client-server communication using sockets: e.printStackTrace();
}
}
}
// Server code
import java.io.*;
import java.net.*;
In this example, the server listens on port 1234 using a ServerSocket . When a
public class Server {
public static void main(String[] args) {
client connects, it accepts the connection and creates input and output streams
try (ServerSocket serverSocket = new ServerSocket(1234); to communicate with the client. The server receives messages from the client,
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), tru
prints them, and sends a response back.
e);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSo
The client creates a Socket object to connect to the server's IP address and port.
cket.getInputStream()))) { It also creates input and output streams to communicate with the server. The
System.out.println("Server: Client connected");
client reads input from the user, sends it to the server, and displays the response
received from the server.
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Server: Received from client: " + inputLine); Development of client Server applications
out.println
1. Define the Application Protocol:
("Server: Received your message: " + inputLine);
} Decide on the communication protocol, such as TCP/IP, HTTP, or
} catch (IOException e) {
WebSocket, that will be used for client-server communication. This
e.printStackTrace();
} choice will influence the libraries and frameworks you use.
}
} 2. Implement the Server-Side Application:
// Client code Create a Java class to represent the server application.
import java.io.*;
import java.net.*; Use the ServerSocket class from the java.net package to listen for
public class Client { incoming client connections.
public static void main(String[] args) {
JAVA 93 JAVA 94
Accept client connections by calling the accept() method of the Add additional functionality to the client and server applications as
ServerSocket class, which returns a Socket object representing the client needed.
connection.
Consider using higher-level frameworks or libraries, such as Java
Spawn a new thread or use a thread pool to handle each client request Servlets or Spring Boot, to simplify development and provide additional
separately, allowing multiple clients to connect concurrently. features.
Receive and parse requests from clients by reading from the input Optimize the code for performance and scalability, ensuring efficient
stream of the Socket object. resource usage and minimizing response times.
Perform necessary processing or interact with a database or other Implement proper error handling and exception management to handle
external resources to handle the client request. edge cases and ensure robustness.
Generate an appropriate response and send it back to the client by 6. Deploy and Maintain the Application:
writing to the output stream of the Socket object.
Deploy the server-side application on a server or hosting platform that
3. Implement the Client-Side Application: allows for incoming client connections.
Create a Java class to represent the client application. Distribute the client-side application to end-users or provide instructions
for accessing and installing it.
Use the Socket class from the java.net package to establish a
connection with the server by providing the server's IP address and port Monitor the application's performance, handle maintenance tasks, and
number. apply updates or patches as needed.
Send requests to the server by writing to the output stream of the Socket Ensure security by following best practices, such as input validation,
object. authentication, and secure communication protocols.
Wait for the server's response by reading from the input stream of the Java provides built-in classes and libraries for socket-based communication,
Socket object. making it relatively straightforward to develop client-server applications.
However, depending on the complexity of your application and specific
Process the response received from the server and take appropriate
requirements, you may consider using frameworks like Java Servlets, Spring
action based on the application logic.
Boot, or Netty, which offer higher-level abstractions and additional features to
4. Test and Debug: simplify client-server development.
Run both the server-side and client-side applications and verify that they
can communicate properly. Design of multithreaded server
Designing a multithreaded server involves creating a server application that can
Test various scenarios, such as handling multiple client connections,
handle multiple client connections concurrently using threads. Here's a basic
sending different types of requests, and handling error conditions.
outline of the design:
Debug any issues or errors that arise during testing, such as incorrect
1. Create a Server Socket:
data transmission or unexpected behavior.
Use the ServerSocket class from the java.net package to create a server
5. Enhance and Scale the Application:
socket that listens for incoming client connections on a specific port.
JAVA 95 JAVA 96
Choose an appropriate port number for your server. work before exiting.
Create a loop to continuously accept client connections using the Implement proper error handling to handle exceptions that may occur
accept() method of the ServerSocket class. during client communication, such as network errors or invalid client
requests.
For each client connection, create a new thread or use a thread pool to
handle the client's requests separately. Use logging frameworks, such as Log4j or Java's built-in logging
framework, to log important events, errors, and debugging information
3. Handle Client Requests:
for troubleshooting purposes.
For each client connection, create a new thread or task to handle the
7. Scalability and Performance Considerations:
client's requests.
If your server needs to handle a large number of concurrent
Inside the thread or task, use the Socket object representing the client
connections, consider using a thread pool to limit the number of active
connection to communicate with the client.
threads and manage resources efficiently.
Read data from the input stream of the Socket to receive client requests.
Optimize your code and algorithms to minimize response times and
Process the client's requests according to your application's logic. improve overall performance.
Send responses back to the client by writing data to the output stream of Consider using non-blocking I/O and asynchronous programming
the Socket . models, such as Java NIO or frameworks like Netty, to handle a high
4. Manage Thread Safety: number of connections with lower resource usage.
Ensure thread safety when accessing shared resources or data Remember to thoroughly test your multithreaded server application to ensure it
structures by using appropriate synchronization mechanisms, such as handles multiple client connections correctly and performs well under various
locks or synchronized blocks/methods. scenarios. Pay attention to thread safety, synchronization, and error handling to
avoid concurrency issues and provide a reliable server experience.
If multiple client threads need to access shared resources
simultaneously, implement thread-safe data structures or use Note: The implementation details of a multithreaded server can vary depending
concurrency utilities provided by Java, such as ConcurrentHashMap or on your specific requirements, the Java version you're using, and the
Atomic classes.
libraries/frameworks employed. The outline provided above serves as a general
guide to get started with designing a multithreaded server in Java.
5. Graceful Thread Termination:
Handle proper termination of client threads when clients disconnect or Remote Method invocation
the server is shutting down. Remote Method Invocation (RMI) is a mechanism in Java that allows objects in
Implement a mechanism to detect client disconnections and clean up one Java Virtual Machine (JVM) to invoke methods on objects located in another
any resources associated with the disconnected client. JVM. It enables distributed computing by providing a way for Java programs to
communicate and interact across different JVMs, even on different machines.
Provide a way to gracefully stop the server, which includes stopping new
Here's an overview of how RMI works:
client connections and waiting for existing client threads to finish their
JAVA 97 JAVA 98
1. Define Remote Interface: 7. Handle Exceptions:
Create an interface that defines the methods that can be invoked Both the remote interface and the remote object implementation should
remotely. This interface should extend the java.rmi.Remote interface, and throw java.rmi.RemoteException to handle communication-related
each method should throw java.rmi.RemoteException . exceptions that may occur during remote method invocation.
Create a class that implements the remote interface. This class Configure security settings to ensure secure communication between
represents the actual object that will be accessed remotely. the client and server JVMs.
Extend the java.rmi.server.UnicastRemoteObject class to provide the Provide appropriate access control and authentication mechanisms to
necessary remote object functionality. protect the integrity and confidentiality of the remote method invocations.
Implement the methods defined in the remote interface. RMI simplifies distributed computing in Java by abstracting the complexity of
network communication and providing a transparent way to invoke methods on
3. Start RMI Registry:
remote objects. It enables the development of distributed applications where
The RMI registry acts as a lookup service for remote objects. It objects in different JVMs can interact seamlessly.
maintains a registry of remote objects and their associated names.
Note: RMI has been part of the Java platform for many years, but there are
Start the RMI registry using the rmiregistry command or alternative technologies available today for distributed computing in Java, such
programmatically using the LocateRegistry.createRegistry() method. as Java Remote Method Invocation over Internet Inter-ORB Protocol (RMI-IIOP),
4. Register Remote Object: Java Message Service (JMS), and web services.
Register the remote object with the RMI registry using the rebind()
Java Native interfaces and Development of a JNI based
method of the java.rmi.Naming class. application
Associate a unique name with the remote object in the registry. Java Native Interface (JNI) is a programming framework that allows Java code to
5. Create Client Application: call native code written in languages like C or C++. JNI enables developers to
integrate existing native code libraries or take advantage of platform-specific
Create a separate Java application that will act as the client. functionality in their Java applications. Here's an overview of JNI and the
Obtain a reference to the remote object from the RMI registry using the development process of a JNI-based application:
lookup() method of the java.rmi.Naming class.
1. Understanding JNI Basics:
6. Invoke Remote Methods: JNI provides a set of functions and rules for communication between
Use the obtained reference to the remote object to invoke methods as if Java and native code.
it were a local object. Java classes can define native methods, which are declared using the
The RMI framework handles the underlying communication and native keyword and implemented in native code.
marshalling of method arguments and return values between the client The Java Native Interface allows for passing data and invoking native
and server JVMs. functions from Java code and vice versa.
Synchronized (thread-safe).
2. Stack Class: