What is Java?
Introduction
Java is a high-level, class-based, object-oriented programming language
that is designed to have as few implementation dependencies as possible.
The slogan “Write Once, Run Anywhere” reflects its capability to run on any device that
has a Java Virtual Machine (JVM).
Java was originally developed by Sun Microsystems and later acquired by Oracle Corporation. Over the years, Java became one of the most trusted programming languages for enterprise software, Android development, cloud applications, and large-scale systems.
Today, Java powers millions of applications worldwide — from banking systems and e-commerce platforms to desktop applications and backend APIs.
Why Learn Java?
- Ubiquitous – used in Android, enterprise back-ends, desktop apps and big-data ecosystems.
- Strong static typing helps catch many bugs at compile time.
- Rich standard library and a huge ecosystem of third-party libraries.
- Excellent tooling (IDEA, Eclipse, VS Code, Maven/Gradle, JUnit).
Java is also considered one of the best languages for beginners because its syntax is clean, structured, and widely documented. Learning Java builds a strong programming foundation that makes it easier to learn other languages later.
Where is Java Used?
- Android Development: Many Android applications use Java.
- Web Applications: Large-scale backend systems often use Java frameworks like Spring.
- Desktop Software: Java can build cross-platform desktop applications.
- Enterprise Systems: Banking, insurance, and large corporations rely heavily on Java.
- Cloud & Big Data: Technologies like Hadoop and Apache Kafka are built using Java.
Hello World – Your First Java Program
Save the following as HelloWorld.java and run it from the command line:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }
Compile and run:
javac HelloWorld.java # produces HelloWorld.class
java HelloWorld # prints “Hello, World!”
Understanding the Program
Let us break down the program line by line:
public class HelloWorld→ Defines a class namedHelloWorld.main()→ The entry point where program execution starts.System.out.println()→ Prints output to the console.String[] args→ Stores command-line arguments.
HelloWorld.java.
Install the latest JDK, create the HelloWorld.java file, compile it and run it.
Verify the output in your terminal.
Key Features of Java
- Object-Oriented: Everything in Java revolves around objects and classes.
- Platform Independent: Java code is compiled into bytecode that runs on the JVM.
- Secure: No direct pointer access and includes built-in security features.
- Robust: Strong memory management and exception handling.
- Multithreaded: Supports concurrent execution of two or more threads.
Additional Advantages of Java
- Automatic Garbage Collection: Java automatically manages memory allocation and cleanup.
- Large Community: Millions of developers contribute tutorials, libraries, and tools.
- Backward Compatibility: Older Java applications often continue to work on newer JVM versions.
- Performance: Modern JVM optimizations make Java extremely fast.
How Java Works
Java follows a two-step execution process:
- Compilation: The Java source file (
.java) is compiled into bytecode (.class) using the Java compiler (javac). - Execution: The JVM interprets or compiles the bytecode into machine code that your system can execute.
JDK vs JRE vs JVM
Beginners often confuse these three important Java components. Understanding them early will help you later.
- JVM (Java Virtual Machine) → Runs Java bytecode.
- JRE (Java Runtime Environment) → Contains the JVM and libraries needed to run Java programs.
- JDK (Java Development Kit) → Includes tools required to develop Java applications such as
javac.
JRE = Run Java Programs
JVM = Execute Java Bytecode
Basic Structure of a Java Program
- Class: The main building block of a Java program.
- Main Method: Entry point where execution begins.
- Statements: Instructions executed by the program.
Java Syntax Rules
- Java is case-sensitive.
- Every statement usually ends with a semicolon (
;). - Curly braces
{ }define blocks of code. - Program execution starts from the
main()method.
public class Example { public static void main(String[] args) { System.out.println("Learning Java"); } }
Common Errors Beginners Make
- Forgetting to match the file name with the class name.
- Missing semicolons (
;) at the end of statements. - Incorrect capitalization (Java is case-sensitive).
- Not installing or configuring the JDK properly.
system.out.println() instead of
System.out.println() will produce an error because Java is case-sensitive.
Best Practices for Beginners
- Practice writing code daily instead of only reading theory.
- Use meaningful class and variable names.
- Read compiler error messages carefully.
- Experiment with small programs frequently.
- Focus on understanding concepts instead of memorizing syntax.
Modify the HelloWorld program to print your name instead of "Hello, World!".
Try printing multiple lines using System.out.println() and observe how output is displayed.
Create a program named AboutMe.java that prints:
- Your name
- Your city
- Your favorite programming language
Summary
In this lecture, you learned what Java is, why it is widely used, and how to write and run your first Java program. You also explored its key features, execution process, Java components, and the basic structure of a Java application.
In the next lecture, we will dive deeper into setting up the development environment, installing the JDK correctly, and preparing your system for Java development.
Setting up the JDK
Introduction
Before writing larger Java applications, you need a proper Java development environment. This includes installing the JDK (Java Development Kit), configuring your system, and choosing a suitable code editor or IDE.
In this lecture, you will learn how to install Java correctly, verify the installation, and prepare your machine for Java development.
What is the JDK?
The Java Development Kit (JDK) is the complete package required to create, compile, and run Java applications.
The JDK includes:
- JVM (Java Virtual Machine) → Executes Java bytecode.
- JRE (Java Runtime Environment) → Provides libraries required to run programs.
- Java Compiler (
javac) → Converts Java source code into bytecode. - Development Tools → Debuggers, documentation generators, and more.
Download & Install
Head to Eclipse Adoptium or Oracle JDK and download the appropriate bundle for your operating system.
Choose the installer version that matches your system architecture:
- Windows: Usually
.msior.exe - macOS: Usually
.pkg - Linux: Usually
.tar.gzor package manager installation
Installing on Windows
- Download the JDK installer.
- Run the installer and follow the setup wizard.
- Allow the installer to configure environment variables if prompted.
- Finish installation and restart your terminal.
Installing on macOS
- Download the macOS package.
- Open the installer package.
- Follow the installation instructions.
- Open Terminal and verify the installation.
Installing on Linux
Many Linux distributions provide OpenJDK through package managers.
sudo apt update sudo apt install openjdk-21-jdk
Verify Installation
After installation, open your terminal or command prompt and run:
java -version
javac -version
Both commands should print the version number
(e.g. java 21.0.1) and indicate that the
JDK is correctly configured on your PATH.
Understanding PATH Variables
The PATH environment variable allows your operating system to locate Java commands
such as java and javac from any terminal window.
If the terminal says:
'java' is not recognized as an internal or external command
then Java may not be correctly added to your system PATH.
IDE Recommendation
For a smoother learning experience, choose a Java IDE or code editor:
- IntelliJ IDEA Community – Rich refactoring, smart code completion, debugging, and Maven/Gradle integration.
- Eclipse – A classic Java IDE with extensive plugin support.
-
VS Code –
Lightweight editor with the
Java Extension Pack.
Creating Your First Java Project
Once your IDE is installed:
- Create a new Java project.
- Create a new Java class named
Main. - Add a
main()method. - Run the program using the IDE's Run button.
public class Main { public static void main(String[] args) { System.out.println("Java setup successful!"); } }
Command Line vs IDE
Beginners often wonder whether they should use the terminal or an IDE. Both are useful and important.
- Command Line: Helps understand how Java compilation works internally.
- IDE: Speeds up development with autocomplete, debugging, and project tools.
Common Installation Problems
- Installing only the JRE instead of the full JDK
- Incorrect PATH configuration
- Using an outdated Java version
- Multiple Java versions conflicting on the same system
- Restarting neither the terminal nor the computer after installation
Useful Java Commands
java -version # Shows installed Java version javac -version # Shows Java compiler version java Main # Runs a compiled Java class javac Main.java # Compiles Java source code
Install your favourite IDE, open a new project, create a
Main.java file with a main method,
and run the “Hello World” program inside the IDE.
Open your terminal and run:
java -version
javac -version
Verify that both commands display version information correctly.
Create a Java program named EnvironmentCheck.java
that prints:
- Your Java version
- Your operating system
- Your user name
Research how to access system properties using System.getProperty().
Summary
In this lecture, you learned how to install the Java Development Kit, verify your installation, configure the PATH variable, and choose an IDE for Java development.
You also explored the differences between JDK, JRE, and JVM, along with common installation mistakes beginners encounter.
In the next lecture, we will begin working with variables, data types, and user input in Java.
Variables & Data Types
Introduction
Variables are one of the most fundamental concepts in programming. A variable is simply a named storage location used to hold data in memory.
In Java, every variable must have a specific data type. The data type determines:
- What kind of data can be stored
- How much memory is allocated
- What operations can be performed on the value
Declaring Variables
In Java, variables are declared using the following syntax:
dataType variableName = value;
Example:
int age = 25; double price = 99.99; String name = "Alice";
Primitive Types
Java has 8 primitive data types. Primitive types store simple values directly in memory.
| Type | Size | Example |
|---|---|---|
byte |
8 bit | byte b = 100; |
short |
16 bit | short s = 20000; |
int |
32 bit | int i = 123456; |
long |
64 bit | long l = 123456789L; |
float |
32 bit | float f = 3.14f; |
double |
64 bit | double d = 3.14159; |
char |
16 bit (Unicode) | char c = 'A'; |
boolean |
1 bit (logical) | boolean ok = true; |
Integer Types
Integer types are used to store whole numbers without decimal points.
byte→ Small memory usageshort→ Slightly larger integersint→ Most commonly used integer typelong→ Very large integer values
int for integers unless very large numbers are required.
Floating-Point Types
Floating-point types are used to store decimal numbers.
float→ Less precision, uses less memorydouble→ Higher precision, more commonly used
double by default.
Add f at the end when using a float.
float value = 3.14f; double pi = 3.1415926535;
Character Type
The char type stores a single Unicode character.
char grade = 'A'; char symbol = '#';
Boolean Type
The boolean type stores only two values:
true or false.
boolean isLoggedIn = true; boolean hasPermission = false;
Reference Types
Anything that is not a primitive type is called a reference type.
Reference types store memory addresses that point to objects.
Examples include:
String- Arrays
- Classes and objects
- Collections
Strings in Java
Strings are used to store text.
In Java, strings are objects of the String class.
String city = "London"; String message = "Welcome to Java";
VariablesDemo.java
public class VariablesDemo { public static void main(String[] args) { int age = 30; double price = 19.99; boolean isMember = true; String name = "Alice"; System.out.println(name + ", age " + age); } }
Type Conversion
Sometimes values must be converted from one data type to another.
Implicit Conversion
Java automatically converts smaller types into larger compatible types.
int num = 100; double result = num;
Explicit Conversion (Casting)
Larger types can be manually converted into smaller types using casting.
double value = 9.78; int result = (int) value;
9.78 to int removes the decimal part.
Variable Naming Rules
- Variable names are case-sensitive.
- Names cannot start with numbers.
- Spaces are not allowed.
- Use meaningful names for readability.
int studentAge = 20; double accountBalance = 1500.75;
Common Beginner Mistakes
- Using variables before initialization
- Assigning incorrect data types
- Forgetting quotes around strings
- Using single quotes for strings instead of double quotes
- Confusing
=with==
Create a program that declares one variable of each primitive type, prints them, then swaps two integer values without using a third temporary variable.
Create variables for:
- Your name
- Your age
- Your height
- Whether you are a student
Print all values using System.out.println().
Create a simple billing program that stores:
- Product name
- Price
- Quantity
Then calculate and print the total bill amount.
Summary
In this lecture, you learned about variables, primitive data types, reference types, type conversion, and variable naming rules.
Understanding data types is essential because every Java program relies heavily on storing and manipulating data correctly.
In the next lecture, we will explore operators and expressions in Java.
Control Flow
Introduction
Control flow determines how a program makes decisions and repeats tasks. Without control flow, Java programs would execute statements one after another without any logic or flexibility.
Using conditions and loops, programs can:
- Make decisions
- Repeat actions
- Handle different situations dynamically
- Process large amounts of data efficiently
Conditional Statements
Conditional statements allow programs to execute code only when certain conditions are true.
If / else
The if statement checks a condition.
If the condition evaluates to true, the code block executes.
int score = 85; if (score >= 90) { System.out.println("Grade A"); } else if (score >= 80) { System.out.println("Grade B"); } else { System.out.println("Needs improvement"); }
Understanding the Logic
if→ Executes when the first condition is trueelse if→ Checks additional conditionselse→ Executes if none of the conditions are true
Nested If Statements
An if statement can exist inside another if statement.
This is called nesting.
int age = 20; boolean hasTicket = true; if (age >= 18) { if (hasTicket) { System.out.println("Entry allowed"); } }
Comparison Operators
Conditions usually rely on comparison operators.
| Operator | Meaning |
|---|---|
== |
Equal to |
!= |
Not equal to |
> |
Greater than |
< |
Less than |
>= |
Greater than or equal to |
<= |
Less than or equal to |
Logical Operators
Logical operators combine multiple conditions.
| Operator | Description |
|---|---|
&& |
Logical AND |
|| |
Logical OR |
! |
Logical NOT |
int age = 22; boolean isStudent = true; if (age >= 18 && isStudent) { System.out.println("Eligible for student discount"); }
Switch Statement
The switch statement is useful when comparing one value against multiple possible cases.
Switch (Java 17+ enhanced switch)
String day = "MONDAY"; String result = switch (day) { case "MONDAY", "TUESDAY", "WEDNESDAY" -> "Mid-week"; case "THURSDAY", "FRIDAY" -> "Almost weekend"; case "SATURDAY", "SUNDAY" -> "Weekend"; default -> "Invalid day"; }; System.out.println(result);
Loops
Loops allow code to repeat automatically until a condition becomes false.
- for loop → Best for counting and fixed repetitions
- enhanced for loop → Best for arrays and collections
- while loop → Repeats while a condition is true
- do-while loop → Executes at least once before checking the condition
For Loop
for (int i = 1; i <= 5; i++) { System.out.println(i); }
Enhanced For Loop
Enhanced for loops simplify iteration through arrays and collections.
int[] numbers = { 2, 4, 6, 8 }; int sum = 0; for (int n : numbers) { sum += n; } System.out.println("Sum = " + sum);
While Loop
A while loop executes as long as its condition remains true.
int count = 1; while (count <= 5) { System.out.println(count); count++; }
Do-While Loop
A do-while loop executes the block first,
then checks the condition.
int number = 1; do { System.out.println(number); number++; } while (number <= 3);
Break and Continue
Java provides special statements to control loop execution.
break→ Exits the loop immediatelycontinue→ Skips the current iteration
for (int i = 1; i <= 10; i++) { if (i == 5) { continue; } if (i == 8) { break; } System.out.println(i); }
Common Beginner Mistakes
- Using
=instead of==in conditions - Creating infinite loops accidentally
- Forgetting curly braces in nested conditions
- Using incorrect loop conditions
- Confusing
breakandcontinue
Write a program that prints the first 20 Fibonacci numbers using a
while loop.
Write a program that checks whether a number is even or odd using
an if-else statement.
Create a multiplication table generator using a for loop.
Create a number guessing game where:
- The program stores a secret number
- The user repeatedly guesses the number
- The program prints whether the guess is too high or too low
- The loop ends when the correct number is guessed
Summary
In this lecture, you learned how Java programs make decisions and repeat tasks using conditions and loops.
You explored:
if-elsestatementsswitchexpressionsfor,while, anddo-whileloopsbreakandcontinuestatements
In the next lecture, we will begin working with methods and modular programming in Java.
Methods
Introduction
Methods are reusable blocks of code that perform specific tasks. They help organize programs into smaller, manageable pieces.
Instead of writing the same code repeatedly, developers create methods and call them whenever needed.
Why Methods Matter
- Reduce code duplication
- Improve readability
- Make debugging easier
- Encourage modular programming
- Allow code reuse across projects
Method Syntax
A method in Java consists of:
modifiers returnType name(parameters) { body }
accessModifier returnType methodName(parameters) { // method body }
Understanding Method Components
| Component | Description |
|---|---|
public |
Access modifier |
static |
Belongs to the class instead of an object |
int |
Return type |
add |
Method name |
(int a, int b) |
Parameters |
Creating Methods
public class MathUtils { public static int add(int a, int b) { return a + b; } public static double average(int[] values) { int sum = 0; for (int v : values) { sum += v; } return (double) sum / values.length; } }
Calling Methods
Methods do nothing until they are called.
int result = MathUtils.add(5, 10); System.out.println(result);
Return Values
Methods can return values back to the caller using the
return keyword.
The return type determines what type of value the method sends back.
void return type.
public static void greet() { System.out.println("Welcome!"); }
Method Parameters
Parameters allow methods to receive input values.
public static void displayName(String name) { System.out.println("Hello " + name); }
Method Arguments vs Parameters
| Term | Meaning |
|---|---|
| Parameter | Variable in the method definition |
| Argument | Actual value passed to the method |
Parameter Passing
- Primitives are passed by value — the method receives a copy.
- Objects are passed by reference value — the method receives a copy of the reference, allowing it to modify the object.
Method Overloading
Method overloading allows multiple methods to share the same name but use different parameter lists.
Java identifies overloaded methods based on:
- Number of parameters
- Parameter types
- Order of parameters
public class OverloadDemo { static int max(int a, int b) { return (a > b) ? a : b; } static double max(double a, double b) { return (a > b) ? a : b; } }
Recursive Methods
A recursive method is a method that calls itself.
Recursion is commonly used for mathematical problems, trees, and algorithms.
public static int factorial(int n) { if (n == 1) { return 1; } return n * factorial(n - 1); }
Scope of Variables
Variables declared inside methods are called local variables.
They can only be accessed within that method.
public static void test() { int number = 10; System.out.println(number); }
Main Method
Every Java application starts execution from the
main() method.
public static void main(String[] args) { System.out.println("Program started"); }
Common Beginner Mistakes
- Forgetting the return statement
- Using the wrong return type
- Calling non-static methods incorrectly
- Passing incorrect arguments
- Creating recursive methods without a base case
Write a utility class that provides overloaded
factorial methods for int
and long.
Add a simple main method that demonstrates both.
Create a method called isEven()
that returns true if a number is even,
otherwise returns false.
Write a calculator program that uses separate methods for:
- Addition
- Subtraction
- Multiplication
- Division
Build a menu-driven banking simulation using methods.
Include methods for:
- Deposit
- Withdraw
- Check balance
- Exit program
Summary
In this lecture, you learned how methods help organize and reuse code in Java.
You explored:
- Method syntax
- Parameters and return values
- Method overloading
- Recursion
- Variable scope
Methods are one of the most important building blocks in Java programming. They are heavily used in every real-world application.
In the next lecture, we will begin learning Object-Oriented Programming (OOP) concepts in Java.
Object-Oriented Programming
Introduction
Object-Oriented Programming (OOP) is a programming paradigm based on the concept of objects.
Objects combine both:
- Data → variables and fields
- Behavior → methods and actions
Java is primarily an object-oriented programming language, and most real-world Java applications are built using OOP principles.
Why OOP Matters
- Improves code organization
- Encourages code reuse
- Makes applications easier to maintain
- Supports scalable software development
- Helps teams collaborate efficiently
Core Pillars
- Encapsulation – hide internal state behind private fields and expose behaviour via methods.
-
Inheritance –
reuse code with
extends. - Polymorphism – treat objects of different subclasses uniformly, often via interfaces.
- Abstraction – define contracts with abstract classes or interfaces.
Classes and Objects
A class is a blueprint used to create objects.
An object is an instance of a class.
Class definition
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public void birthday() { age++; } }
Creating Objects
Objects are created using the new keyword.
Person person = new Person("Alice", 25); System.out.println(person.getName());
Encapsulation
Encapsulation means hiding internal data and controlling access through methods.
In Java, this is commonly done using:
privatefields- Getter methods
- Setter methods
Getter and Setter Methods
private double balance; public double getBalance() { return balance; } public void setBalance(double value) { if (value >= 0) { balance = value; } }
Constructors
Constructors are special methods used to initialize objects.
A constructor:
- Has the same name as the class
- Does not have a return type
- Runs automatically when an object is created
Inheritance
Inheritance allows one class to inherit properties and methods from another class.
The child class uses the extends keyword.
Inheritance example
public class Employee extends Person { private String department; public Employee(String name, int age, String dept) { super(name, age); department = dept; } public String getDepartment() { return department; } }
The super Keyword
The super keyword refers to the parent class.
It is commonly used to:
- Call parent constructors
- Access parent methods
- Reuse inherited functionality
Method Overriding
Method overriding allows subclasses to provide their own implementation of inherited methods.
class Animal { void sound() { System.out.println("Animal sound"); } } class Dog extends Animal { @Override void sound() { System.out.println("Bark"); } }
Polymorphism
Polymorphism allows one interface or parent class reference to represent many different object types.
Animal pet = new Dog(); pet.sound();
Abstraction
Abstraction focuses on hiding implementation details and showing only essential behavior.
Java supports abstraction using:
- Abstract classes
- Interfaces
Abstract Class Example
abstract class Shape { abstract double area(); }
Interface Example
interface Vehicle { void start(); }
Access Modifiers
| Modifier | Accessibility |
|---|---|
public |
Accessible everywhere |
private |
Accessible only within the same class |
protected |
Accessible in subclasses and same package |
| default | Accessible only within the same package |
Composition vs Inheritance
Inheritance represents an "is-a" relationship, while composition represents a "has-a" relationship.
Example:
- A Dog is an Animal → inheritance
- A Car has an Engine → composition
Common Beginner Mistakes
- Making everything public
- Confusing classes and objects
- Forgetting constructors
- Using inheritance unnecessarily
- Ignoring encapsulation principles
Model a simple library system:
create a base class Item
(with id, title) and subclasses
Book and Magazine.
Add a method printInfo()
that is overridden in each subclass.
Create a class called BankAccount
with:
- Private balance field
- Deposit method
- Withdraw method
- Getter method for balance
Create an abstract class called Employee
and subclasses:
DeveloperManager
Override a method called work().
Build a mini school management system using OOP concepts.
Include:
- Student class
- Teacher class
- Course class
- Inheritance and polymorphism
- Encapsulation using private fields
Summary
In this lecture, you explored the foundations of Object-Oriented Programming in Java.
You learned about:
- Classes and objects
- Encapsulation
- Inheritance
- Polymorphism
- Abstraction
- Constructors and access modifiers
OOP is one of the most important concepts in modern software development and is heavily used in enterprise Java applications, Android development, and backend systems.
In the next lecture, we will begin working with collections and advanced data handling in Java.
Collections Framework
Introduction to the Collections Framework
The Java Collections Framework is a powerful set of classes and interfaces used to store, organize, and manage groups of objects efficiently. Instead of manually creating arrays and complex data structures, Java provides ready-made implementations for common programming needs.
The framework includes dynamic lists, sets, maps, queues, iterators, sorting utilities, and algorithms that are optimized and widely used in real-world software development.
Why Collections?
They provide well-tested, efficient implementations of common data structures (lists, sets, maps) plus a rich set of utility methods.
- Dynamic sizing unlike fixed-size arrays
- Built-in algorithms for sorting and searching
- Improved code readability
- Reusable and optimized implementations
- Support for generics and type safety
Collection Hierarchy Overview
The Collections Framework is built using interfaces and classes.
Collection
├── List
│ ├── ArrayList
│ └── LinkedList
│
├── Set
│ ├── HashSet
│ └── TreeSet
│
└── Queue
└── PriorityQueue
Map
├── HashMap
└── TreeMap
Different collection types are designed for different use cases.
Generics in Collections
Collections usually use Generics to specify the type of data they store.
ArrayList<String> names = new ArrayList<>();
This ensures type safety and prevents storing incorrect object types.
List – ordered, duplicates allowed
A List stores elements in insertion order and allows duplicate values.
import java.util.*; // List, ArrayList public class ListDemo { public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("Alice"); names.add("Bob"); names.add("Alice"); // duplicate allowed for (String n : names) { System.out.println(n); } } }
Common List Methods
names.add("Charlie");
names.remove("Bob");
names.get(0);
names.size();
names.contains("Alice");
| Method | Purpose |
|---|---|
| add() | Adds an element |
| remove() | Removes an element |
| get() | Accesses an element by index |
| size() | Returns collection size |
| contains() | Checks if an element exists |
ArrayList vs LinkedList
| ArrayList | LinkedList |
|---|---|
| Fast random access | Fast insertions/removals |
| Uses dynamic arrays | Uses linked nodes |
| Better for reading data | Better for modifying data frequently |
Set – unique elements
A Set stores unique elements and automatically removes duplicates.
import java.util.*; // HashSet public class SetDemo { public static void main(String[] args) { Set<Integer> primes = new HashSet<>(); primes.add(2); primes.add(3); primes.add(2); // ignored – duplicate System.out.println(primes); } }
HashSet vs TreeSet
| HashSet | TreeSet |
|---|---|
| Unordered | Sorted automatically |
| Faster operations | Slightly slower |
| Uses hashing | Uses tree structure |
Map – key/value pairs
A Map stores data as key-value pairs.
import java.util.*; // Map, HashMap public class MapDemo { public static void main(String[] args) { Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 90); scores.put("Bob", 85); scores.put("Alice", 95); // overwrites previous System.out.println(scores); } }
Common Map Methods
scores.put("Charlie", 88);
scores.get("Alice");
scores.remove("Bob");
scores.containsKey("Alice");
scores.containsValue(95);
HashMap vs TreeMap
| HashMap | TreeMap |
|---|---|
| Unordered keys | Sorted keys |
| Faster performance | Maintains natural ordering |
| Uses hashing | Uses balanced trees |
Iterating Through Collections
Collections can be traversed using loops or iterators.
for (String name : names) {
System.out.println(name);
}
Enhanced for-loops are cleaner and easier to read.
Sorting Collections
The Collections utility class provides sorting methods.
Collections.sort(names);
You can also sort in reverse order:
Collections.sort(names, Collections.reverseOrder());
Queue Interface
A Queue processes elements in FIFO (First In First Out) order.
Queue<Integer> queue = new LinkedList<>();
queue.add(10);
queue.add(20);
System.out.println(queue.poll());
poll() removes and returns the first element.
Collections Utility Class
The Collections class provides useful helper methods.
Collections.max(numbers);
Collections.min(numbers);
Collections.shuffle(numbers);
Common Beginner Mistakes
- Using raw collections without generics
- Choosing the wrong collection type
- Forgetting that Sets remove duplicates
- Accessing invalid indexes in Lists
- Confusing HashMap ordering behavior
Implement a simple phone-book using a HashMap<String, String> where the key is a
person’s name and the value is a phone number. Add methods to add, lookup and remove entries.
Create an ArrayList<Integer> and write a program that sorts numbers in ascending and
descending order.
Create a HashSet<String> to store usernames and prevent duplicate registrations.
Generics
Introduction to Generics
Generics are one of Java’s most powerful features. They allow classes, interfaces, and methods to work with different data types while maintaining type safety.
Before Generics were introduced in Java 5, developers had to store objects using the Object class,
which required manual casting and increased the chance of runtime errors.
Why Generics?
They let you write type-safe collections and APIs without casting.
- Improves code reusability
- Eliminates unnecessary type casting
- Provides compile-time type checking
- Makes code cleaner and easier to maintain
- Used heavily in the Collections Framework
Problem Without Generics
Before Generics, collections stored data as Object types.
import java.util.*; public class WithoutGenerics { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("Hello"); list.add(100); String text = (String) list.get(0); System.out.println(text); } }
This approach is unsafe because incorrect casting can cause runtime exceptions.
Using Generics Properly
With Generics, you specify the exact type of data allowed.
import java.util.*; public class GenericList { public static void main(String[] args) { ArrayList<String> names = new ArrayList<>(); names.add("Alice"); names.add("Bob"); String first = names.get(0); System.out.println(first); } }
Now Java automatically ensures only String values can be stored.
Generic Type Parameters
Generic classes use placeholder type names inside angle brackets <>.
| Type Parameter | Meaning |
|---|---|
| T | Type |
| E | Element |
| K | Key |
| V | Value |
| N | Number |
Simple generic class
public class Box<T> { private T value; public Box(T value) { this.value = value; } public T get() { return value; } public void set(T value) { this.value = value; } }
Creating Generic Objects
Box<String> textBox = new Box<>("Hello");
Box<Integer> numberBox = new Box<>(100);
System.out.println(textBox.get());
System.out.println(numberBox.get());
The same class works with multiple data types.
Generic Methods
Methods can also use Generics independently of the class.
public class GenericMethod { public static <T> void printData(T value) { System.out.println(value); } public static void main(String[] args) { printData("Java"); printData(500); printData(3.14); } }
Using bounded type parameters
Restrict a type to subclasses of a given class or interface.
public class NumberUtils { public static <T extends Number> double sum(List<T> list) { double total = 0; for (T n : list) { total += n.doubleValue(); } return total; } }
This method only accepts numeric types such as Integer, Double, or
Float.
Wildcards in Generics
Wildcards make Generics more flexible.
List<?> items;
The ? symbol means “unknown type”.
| Wildcard | Description |
|---|---|
| ? | Any type |
| ? extends Number | Number or subclass |
| ? super Integer | Integer or parent class |
Generic Interfaces
Interfaces can also use Generics.
interface Storage<T> {
void save(T item);
T load();
}
Type Erasure
Java implements Generics using a concept called Type Erasure.
During compilation, generic type information is removed and converted into regular Java bytecode. This means Generics provide compile-time safety but do not exist at runtime.
new T() directly inside generic classes.
Common Beginner Mistakes
- Using raw types instead of generic types
- Forgetting angle brackets
<> - Using incorrect type parameters
- Mixing incompatible generic types
- Assuming Generics exist at runtime
Real-World Usage of Generics
Generics are heavily used throughout modern Java development.
- Collections Framework
- Spring Boot applications
- REST APIs
- Database frameworks like Hibernate
- Reusable utility libraries
Create a generic Pair<K,V> class that stores two values. Write a short demo that
creates a Pair<String,Integer> and prints both elements.
Create a generic method called display() that prints arrays of different types such as
integers, strings, and doubles.
Create a generic class called Storage<T> that stores and retrieves one object of any
type.
Streams & Lambdas (Java 8+)
Introduction to Functional Programming in Java
Java 8 introduced one of the biggest upgrades in Java history: Lambda Expressions and the Stream API. These features allow developers to write cleaner, shorter, and more expressive code using a functional programming style.
Instead of manually writing loops and temporary variables, Streams allow operations such as filtering, mapping, sorting, and collecting data in a concise pipeline.
What is a Lambda Expression?
A lambda expression is an anonymous function that can be passed as data.
It allows you to write compact code without creating separate classes for simple operations.
Lambda syntax
A lambda expression is an anonymous function that can be treated as an instance of a functional interface.
import java.util.function.*; public class LambdaDemo { public static void main(String[] args) { Predicate<Integer> isEven = n -> n % 2 == 0; System.out.println( isEven.test(42) ); // true } }
Understanding Lambda Structure
(parameters) -> expression
| Part | Purpose |
|---|---|
| (parameters) | Input values |
| -> | Lambda operator |
| expression | Code to execute |
More Lambda Examples
() -> System.out.println("Hello")
x -> x * x
(a, b) -> a + b
Lambdas become especially powerful when combined with collections and streams.
Functional Interfaces
A lambda expression works with a functional interface, which is an interface containing only one abstract method.
@FunctionalInterface
interface Calculator {
int operate(int a, int b);
}
You can then provide implementations using lambdas:
Calculator add = (a, b) -> a + b;
System.out.println(add.operate(5, 3));
Common Built-in Functional Interfaces
| Interface | Purpose |
|---|---|
| Predicate<T> | Returns true or false |
| Function<T,R> | Transforms data |
| Consumer<T> | Consumes data without returning |
| Supplier<T> | Provides data |
What is the Stream API?
The Stream API processes collections of data in a declarative and functional way.
Streams do not store data themselves — they operate on existing collections like lists and sets.
Stream pipeline
Streams enable functional-style processing of sequences of elements.
import java.util.stream.*; import java.util.*; public class StreamDemo { public static void main(String[] args) { List<Integer> numbers = Arrays.asList( 1, 2, 3, 4, 5 ); int sum = numbers.stream() .filter(n -> n % 2 == 0) .mapToInt(n -> n * n) .sum(); System.out.println( "Result = " + sum ); } }
Understanding Stream Operations
| Operation | Purpose |
|---|---|
| filter() | Select matching elements |
| map() | Transform elements |
| sorted() | Sort elements |
| collect() | Store results |
| forEach() | Iterate through elements |
Filtering Data
List<Integer> nums = Arrays.asList(1,2,3,4,5,6);
nums.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
The filter() method keeps only matching elements.
Mapping Data
The map() method transforms each element.
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
Sorting Streams
numbers.stream()
.sorted()
.forEach(System.out::println);
You can also use custom comparators with lambdas.
numbers.stream()
.sorted((a, b) -> b - a)
.forEach(System.out::println);
Collecting Results
The collect() method converts stream results into collections.
List<String> result = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
Method References
Method references are a shorter form of lambdas.
names.forEach(System.out::println);
This is equivalent to:
names.forEach(name -> System.out.println(name));
Stream Pipeline Stages
A stream pipeline usually has three stages:
- Source → collection or array
- Intermediate operations → filter, map, sorted
- Terminal operation → collect, sum, forEach
Advantages of Streams
- Cleaner and shorter code
- Less manual looping
- Easier data transformations
- Supports parallel processing
- Improved readability
Parallel Streams
Java can process streams in parallel using multiple CPU cores.
numbers.parallelStream()
.forEach(System.out::println);
Common Beginner Mistakes
- Trying to reuse a stream after a terminal operation
- Using streams for extremely simple tasks unnecessarily
- Confusing map() with filter()
- Overusing parallel streams
- Writing overly complex lambda expressions
Real-World Usage
Streams and Lambdas are heavily used in modern Java applications.
- Spring Boot applications
- REST APIs
- Data processing systems
- Backend enterprise software
- Big-data pipelines
Read a list of words from an array, convert them to uppercase, filter those longer than 5 characters, sort them alphabetically and print each on its own line — all using the Stream API.
Create a list of integers and use streams to calculate the sum of all odd numbers.
Create a lambda expression that checks whether a number is positive, negative, or zero.
Exception Handling
Checked vs Unchecked
- Checked – compiler forces you to handle or declare (
IOException,SQLException). - Unchecked – subclasses of
RuntimeException(e.g.NullPointerException) need not be declared.
Try‑catch‑finally
import java.io.*; public class ExceptionDemo { public static void main(String[] args) { try { BufferedReader br = new BufferedReader(new FileReader("missing.txt")); System.out.println(br.readLine()); } catch (FileNotFoundException e) { System.err.println("File not found!"); } catch (IOException e) { e.printStackTrace(); } finally { System.out.println("Cleanup if necessary"); } } }
Custom exception
public class InvalidAgeException extends Exception { public InvalidAgeException(String message) { super(message); } }
Create a BankAccount class with a withdraw(double amount) method.
Throw a custom InsufficientFundsException when the balance would become negative,
and write a driver program that catches and reports the error.
Concurrency
Threads basics
Two ways to create a thread:
- Extend
Threadand overriderun(). - Implement
Runnable(orCallable) and pass it to aThreador anExecutorService.
class MyTask implements Runnable { public void run() { for (int i = 0; i < 5; i++) { System.out.println("Thread " + Thread.currentThread().getName() + ": " + i); try { Thread.sleep(500); } catch (InterruptedException e) { } } } } public class ThreadDemo { public static void main(String[] args) { Thread t1 = new Thread(new MyTask(), "Worker‑1"); Thread t2 = new Thread(new MyTask(), "Worker‑2"); t1.start(); t2.start(); } }
Executor framework
Higher‑level API for managing thread pools.
import java.util.concurrent.*; public class ExecutorDemo { public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { int id = i; pool.submit(() -> { System.out.println("Task " + id + " executed by " + Thread.currentThread().getName()); }); } pool.shutdown(); } }
Implement a simple producer‑consumer pipeline using a BlockingQueue and two threads
(one producing numbers, the other consuming and printing them). Use an ExecutorService
to run both.
Java Swing GUI Development
Swing is Java's built-in GUI (Graphical User Interface) toolkit. It allows developers to create windows, buttons, menus, forms, tables, dialogs, and complete desktop applications.
Swing is part of the javax.swing package and works
on Windows, Linux, and macOS.
Why Use Swing?
- Create desktop applications.
- Build forms and data-entry systems.
- Create calculators and management systems.
- Develop educational software.
- Build database-driven applications.
Common Swing Components
| Component | Purpose |
|---|---|
| JFrame | Main application window |
| JPanel | Container for components |
| JButton | Clickable button |
| JLabel | Display text |
| JTextField | Single-line input |
| JPasswordField | Password input |
| JTextArea | Multi-line input |
| JCheckBox | Selection box |
| JRadioButton | Single-choice option |
| JComboBox | Dropdown menu |
| JTable | Display tabular data |
Your First Swing Program
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("My First Window");
frame.setSize(500, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Understanding JFrame
| Method | Purpose |
|---|---|
| setSize() | Set window size |
| setTitle() | Set title |
| setVisible() | Show window |
| setLocationRelativeTo() | Center window |
| setResizable() | Enable/disable resizing |
| add() | Add component |
Adding a Label
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JLabel label =
new JLabel("Welcome to Swing");
frame.add(label);
frame.setSize(400,200);
frame.setVisible(true);
}
}
Creating a Button
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JButton btn =
new JButton("Click Me");
frame.add(btn);
frame.setSize(400,200);
frame.setVisible(true);
}
}
Event Handling
Event handling allows Swing applications to react when users click buttons, type text, select menu items, or interact with components.
import javax.swing.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JButton btn =
new JButton("Click");
btn.addActionListener(
new ActionListener() {
public void actionPerformed(
ActionEvent e) {
JOptionPane.showMessageDialog(
null,
"Button Clicked!"
);
}
});
frame.add(btn);
frame.setSize(400,200);
frame.setVisible(true);
}
}
JTextField Example
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JTextField txt =
new JTextField();
txt.setBounds(50,50,200,30);
frame.add(txt);
frame.setLayout(null);
frame.setSize(400,300);
frame.setVisible(true);
}
}
Layouts
Layout Managers automatically position components.
| Layout | Purpose |
|---|---|
| FlowLayout | Left to right |
| BorderLayout | North, South, East, West, Center |
| GridLayout | Rows and columns |
| BoxLayout | Vertical or horizontal arrangement |
| null Layout | Manual positioning |
FlowLayout Example
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setLayout(new FlowLayout());
frame.add(new JButton("One"));
frame.add(new JButton("Two"));
frame.add(new JButton("Three"));
frame.setSize(400,200);
frame.setVisible(true);
}
}
JCheckBox Example
JCheckBox java =
new JCheckBox("Java");
JCheckBox python =
new JCheckBox("Python");
frame.add(java);
frame.add(python);
JRadioButton Example
JRadioButton male =
new JRadioButton("Male");
JRadioButton female =
new JRadioButton("Female");
ButtonGroup group =
new ButtonGroup();
group.add(male);
group.add(female);
JComboBox Example
String[] countries = {
"India",
"Zimbabwe",
"South Africa"
};
JComboBox box =
new JComboBox(countries);
frame.add(box);
JTextArea Example
JTextArea area =
new JTextArea();
frame.add(area);
Message Dialogs
JOptionPane.showMessageDialog(
null,
"Operation Successful"
);
Input Dialog
String name =
JOptionPane.showInputDialog(
"Enter Name"
);
Confirm Dialog
int result =
JOptionPane.showConfirmDialog(
null,
"Delete Record?"
);
Menu Bar Example
JMenuBar menuBar =
new JMenuBar();
JMenu file =
new JMenu("File");
JMenuItem exit =
new JMenuItem("Exit");
file.add(exit);
menuBar.add(file);
frame.setJMenuBar(menuBar);
Building a Login Form
JLabel user =
new JLabel("Username");
JTextField txtUser =
new JTextField();
JLabel pass =
new JLabel("Password");
JPasswordField txtPass =
new JPasswordField();
JButton login =
new JButton("Login");
- Calculator
- Student Registration System
- Library Management System
- Inventory System
- Banking Application
- Login System
- Quiz Application
- Know all major Swing components.
- Understand event handling.
- Practice JFrame creation.
- Learn layout managers.
- Understand dialogs and forms.
- Swing is Java's GUI toolkit.
- JFrame is the main window.
- Components are added to containers.
- Layouts organize components.
- Events make applications interactive.
- Swing is commonly used for desktop applications.
Interfaces & Abstract Classes
Interfaces and abstract classes are important concepts in Object-Oriented Programming (OOP). They help create flexible, reusable, and maintainable code by defining common behavior for multiple classes.
What is an Abstract Class?
An abstract class is a class that cannot be instantiated directly. It serves as a blueprint for other classes.
- Declared using the
abstractkeyword. - Cannot create objects directly.
- Can contain abstract and normal methods.
- Can have constructors and variables.
- Used when classes share common functionality.
Abstract Method
An abstract method has no body and must be implemented by subclasses.
abstract class Animal {
abstract void makeSound();
}
Example: Abstract Class
abstract class Animal {
abstract void makeSound();
void sleep() {
System.out.println("Sleeping...");
}
}
class Dog extends Animal {
void makeSound() {
System.out.println("Bark");
}
}
public class Main {
public static void main(String[] args) {
Dog d = new Dog();
d.makeSound();
d.sleep();
}
}
Output
Bark
Sleeping...
What is an Interface?
An interface is a completely abstract blueprint that defines what a class must do without specifying how it does it.
- Declared using the
interfacekeyword. - Contains abstract methods by default.
- Supports multiple inheritance.
- Cannot create objects directly.
- Implemented using the
implementskeyword.
Creating an Interface
interface Vehicle {
void start();
}
Implementing an Interface
interface Vehicle {
void start();
}
class Car implements Vehicle {
public void start() {
System.out.println("Car Started");
}
}
public class Main {
public static void main(String[] args) {
Car c = new Car();
c.start();
}
}
Output
Car Started
Multiple Interface Implementation
A class can implement multiple interfaces, which helps achieve multiple inheritance.
interface Camera {
void takePhoto();
}
interface MusicPlayer {
void playMusic();
}
class Smartphone implements Camera, MusicPlayer {
public void takePhoto() {
System.out.println("Photo Taken");
}
public void playMusic() {
System.out.println("Playing Music");
}
}
Abstract Class vs Interface
| Feature | Abstract Class | Interface |
|---|---|---|
| Methods | Abstract + Concrete | Mainly Abstract |
| Variables | Normal Variables Allowed | Constants Only |
| Constructors | Allowed | Not Allowed |
| Inheritance | Single Inheritance | Multiple Inheritance |
| Keyword | extends | implements |
When to Use an Abstract Class
- When classes share common code.
- When you want partial implementation.
- When subclasses should inherit state and behavior.
When to Use an Interface
- When unrelated classes need common behavior.
- When multiple inheritance is required.
- When defining a contract for classes.
- Abstract Class: Animal, Vehicle, Employee
- Interface: Printable, Runnable, Comparable
- Smartphone: Camera + Music Player + Internet Device
- Abstract classes provide partial implementation.
- Interfaces define contracts for classes.
- Abstract methods must be implemented by subclasses.
- Interfaces support multiple inheritance.
- Both improve flexibility and code reusability.
Enums & Annotations
Content coming soon...
File I/O & NIO
File I/O (Input/Output) allows Java programs to read and write data from files. Java provides two major approaches:
- Classic File I/O (java.io package)
- NIO (New Input/Output - java.nio package)
Why File Handling?
- Store data permanently.
- Read configuration files.
- Save application settings.
- Create logs and reports.
- Process large datasets.
Java File Class
The File class represents files and directories.
import java.io.File;
public class Main {
public static void main(String[] args) {
File file = new File("student.txt");
System.out.println(file.exists());
}
}
Creating a File
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args)
throws IOException {
File file =
new File("data.txt");
if(file.createNewFile()) {
System.out.println("File Created");
} else {
System.out.println("Already Exists");
}
}
}
Writing to a File (FileWriter)
import java.io.FileWriter;
public class Main {
public static void main(String[] args)
throws Exception {
FileWriter writer =
new FileWriter("notes.txt");
writer.write("Hello Java!");
writer.close();
System.out.println("Written Successfully");
}
}
Appending Data
FileWriter writer =
new FileWriter("notes.txt", true);
writer.write("\nNew Line Added");
writer.close();
Reading Files (Scanner)
import java.io.File;
import java.util.Scanner;
public class Main {
public static void main(String[] args)
throws Exception {
File file =
new File("notes.txt");
Scanner sc =
new Scanner(file);
while(sc.hasNextLine()) {
System.out.println(sc.nextLine());
}
sc.close();
}
}
BufferedWriter
BufferedWriter improves performance by reducing disk access.
import java.io.*;
BufferedWriter writer =
new BufferedWriter(
new FileWriter("data.txt")
);
writer.write("Fast Writing");
writer.close();
BufferedReader
import java.io.*;
BufferedReader reader =
new BufferedReader(
new FileReader("data.txt")
);
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
Binary Files
Binary files store raw bytes instead of text.
FileOutputStream
import java.io.*;
FileOutputStream out =
new FileOutputStream("file.bin");
out.write(65);
out.close();
FileInputStream
import java.io.*;
FileInputStream in =
new FileInputStream("file.bin");
int data = in.read();
System.out.println(data);
in.close();
Introduction to NIO
NIO (New Input/Output) was introduced to provide faster, more scalable file operations and better support for large files.
Important NIO Classes
| Class | Purpose |
|---|---|
| Path | Represents a file path |
| Paths | Create Path objects |
| Files | File operations |
| DirectoryStream | Directory traversal |
Creating a Path
import java.nio.file.*;
Path path =
Paths.get("data.txt");
System.out.println(path);
Writing Files with NIO
import java.nio.file.*;
import java.util.*;
Path path =
Paths.get("data.txt");
Files.write(
path,
Arrays.asList(
"Java",
"Python",
"C++"
)
);
Reading Files with NIO
import java.nio.file.*;
import java.util.*;
Path path =
Paths.get("data.txt");
List<String> lines =
Files.readAllLines(path);
for(String line : lines) {
System.out.println(line);
}
Copying Files
Path source =
Paths.get("source.txt");
Path target =
Paths.get("backup.txt");
Files.copy(
source,
target
);
Moving Files
Files.move(
Paths.get("old.txt"),
Paths.get("new.txt")
);
Deleting Files
Files.delete(
Paths.get("temp.txt")
);
Creating Directories
Files.createDirectory(
Paths.get("Students")
);
Exception Handling Example
try {
Files.delete(
Paths.get("data.txt")
);
} catch(IOException e) {
System.out.println(
"Error: " + e.getMessage()
);
}
File I/O vs NIO
| Feature | File I/O | NIO |
|---|---|---|
| Package | java.io | java.nio |
| Performance | Good | Better |
| Large Files | Limited | Excellent |
| Modern API | No | Yes |
- Always close file resources.
- Use try-with-resources when possible.
- Handle exceptions properly.
- Prefer NIO for modern applications.
- Validate file paths before access.
Try-With-Resources Example
try(BufferedReader reader =
new BufferedReader(
new FileReader("data.txt"))) {
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch(IOException e) {
e.printStackTrace();
}
- File I/O enables reading and writing files.
- FileWriter and Scanner are common text-file tools.
- BufferedReader and BufferedWriter improve performance.
- NIO provides modern, efficient file operations.
- Files and Paths simplify file management.
- Always handle exceptions and close resources.
Networking & Sockets
Networking allows Java applications to communicate over a network. Java provides powerful networking APIs for creating client-server applications, chat systems, file transfer applications, and web services.
What is Networking?
Networking is the process of exchanging data between computers or devices.
Java supports networking through the java.net package.
Common Networking Terms
| Term | Description |
|---|---|
| IP Address | Unique address of a device on a network |
| Port | Communication endpoint on a device |
| Protocol | Rules for communication |
| Client | Requests services |
| Server | Provides services |
| Socket | Endpoint for communication |
What is a Socket?
A socket is a communication endpoint that allows two programs to exchange data over a network.
- Server starts and listens on a port.
- Client connects to the server.
- Data is exchanged between client and server.
- Connection is closed.
Important Networking Classes
| Class | Purpose |
|---|---|
| InetAddress | Represents IP addresses |
| Socket | Client-side communication |
| ServerSocket | Server-side communication |
| URL | Represents web resources |
| URLConnection | Connection to URL resources |
Getting Local Host Information
import java.net.*;
public class Main {
public static void main(String[] args)
throws Exception {
InetAddress ip =
InetAddress.getLocalHost();
System.out.println(ip);
System.out.println(ip.getHostName());
System.out.println(ip.getHostAddress());
}
}
Getting Website IP Address
import java.net.*;
public class Main {
public static void main(String[] args)
throws Exception {
InetAddress ip =
InetAddress.getByName("google.com");
System.out.println(ip);
}
}
Client-Server Architecture
The server waits for connections. The client connects to the server. Once connected, both can exchange information.
Creating a Server
import java.net.*;
import java.io.*;
public class Server {
public static void main(String[] args)
throws Exception {
ServerSocket server =
new ServerSocket(5000);
System.out.println("Server Started");
Socket socket =
server.accept();
System.out.println("Client Connected");
server.close();
}
}
Creating a Client
import java.net.*;
public class Client {
public static void main(String[] args)
throws Exception {
Socket socket =
new Socket("localhost", 5000);
System.out.println(
"Connected to Server"
);
socket.close();
}
}
Sending Data from Client
PrintWriter out =
new PrintWriter(
socket.getOutputStream(),
true
);
out.println("Hello Server");
Receiving Data on Server
BufferedReader in =
new BufferedReader(
new InputStreamReader(
socket.getInputStream()
)
);
String message =
in.readLine();
System.out.println(message);
Simple Chat Example
// Client sends
out.println("Hello!");
// Server receives
String msg = in.readLine();
System.out.println(msg);
Reading Data from a URL
import java.net.*;
import java.io.*;
public class Main {
public static void main(String[] args)
throws Exception {
URL url =
new URL(
"https://example.com"
);
BufferedReader reader =
new BufferedReader(
new InputStreamReader(
url.openStream()
)
);
String line;
while((line = reader.readLine())
!= null) {
System.out.println(line);
}
reader.close();
}
}
UDP vs TCP
| Feature | TCP | UDP |
|---|---|---|
| Connection | Required | Not Required |
| Reliability | High | Lower |
| Speed | Slower | Faster |
| Examples | Web, Email, Banking | Gaming, Streaming |
Creating a UDP Socket
import java.net.*;
DatagramSocket socket =
new DatagramSocket();
Sending UDP Data
byte[] data =
"Hello".getBytes();
InetAddress ip =
InetAddress.getByName(
"localhost"
);
DatagramPacket packet =
new DatagramPacket(
data,
data.length,
ip,
6000
);
socket.send(packet);
Exception Handling
try {
Socket socket =
new Socket(
"localhost",
5000
);
} catch(IOException e) {
System.out.println(
"Connection Failed"
);
}
- Always close sockets after use.
- Handle exceptions properly.
- Validate incoming data.
- Use threads for multiple clients.
- Never trust external network input.
Real-World Applications
- Chat Applications
- Online Games
- File Sharing Systems
- Web Browsers
- Email Services
- Video Streaming Platforms
- Banking Systems
- Java networking is provided by the java.net package.
- Sockets enable communication between applications.
- ServerSocket creates servers.
- Socket creates client connections.
- TCP is reliable while UDP is faster.
- Networking powers modern internet applications.
JDBC & Databases
JDBC (Java Database Connectivity) is a Java API that allows Java applications to communicate with databases such as MySQL, PostgreSQL, Oracle, and SQLite. JDBC acts as a bridge between Java programs and relational databases.
Why Use Databases?
- Store data permanently.
- Manage large amounts of information efficiently.
- Perform searches and filtering using SQL.
- Support multi-user applications.
- Provide data security and integrity.
- Java Application
- JDBC API
- JDBC Driver
- Database Server
Steps to Connect Java with MySQL
- Java JDK installed
- MySQL Server installed
- MySQL Connector/J JDBC Driver
- Database created in MySQL
Step 1: Import JDBC Package
import java.sql.*;
Step 2: Establish Connection
String url = "jdbc:mysql://localhost:3306/school";
String username = "root";
String password = "";
Connection con =
DriverManager.getConnection(url, username, password);
Step 3: Create Statement
Statement stmt = con.createStatement();
Step 4: Execute SQL Query
ResultSet rs =
stmt.executeQuery("SELECT * FROM students");
Step 5: Process Results
while(rs.next()) {
System.out.println(
rs.getInt("id") + " " +
rs.getString("name")
);
}
Step 6: Close Resources
rs.close();
stmt.close();
con.close();
Complete Example
import java.sql.*;
public class JDBCExample {
public static void main(String[] args) {
try {
String url =
"jdbc:mysql://localhost:3306/school";
Connection con =
DriverManager.getConnection(
url, "root", ""
);
Statement stmt =
con.createStatement();
ResultSet rs =
stmt.executeQuery(
"SELECT * FROM students"
);
while(rs.next()) {
System.out.println(
rs.getInt("id") + " - " +
rs.getString("name")
);
}
rs.close();
stmt.close();
con.close();
} catch(Exception e) {
System.out.println(e);
}
}
}
CRUD Operations
| Operation | SQL Command |
|---|---|
| Create | INSERT |
| Read | SELECT |
| Update | UPDATE |
| Delete | DELETE |
Insert Example
String sql =
"INSERT INTO students(name) VALUES('John')";
stmt.executeUpdate(sql);
Update Example
String sql =
"UPDATE students SET name='Mike' WHERE id=1";
stmt.executeUpdate(sql);
Delete Example
String sql =
"DELETE FROM students WHERE id=1";
stmt.executeUpdate(sql);
Avoid building SQL queries by directly concatenating user input. This can lead to SQL Injection attacks. Use PreparedStatement instead.
PreparedStatement Example
String sql =
"SELECT * FROM students WHERE id=?";
PreparedStatement ps =
con.prepareStatement(sql);
ps.setInt(1, 5);
ResultSet rs = ps.executeQuery();
- JDBC connects Java applications to databases.
- Connections are created using DriverManager.
- Statements execute SQL commands.
- ResultSet stores query results.
- PreparedStatement improves security and performance.
- Always close database resources after use.
Unit Testing (JUnit)
Content coming soon...
Design Patterns
Content coming soon...
Build Tools (Maven & Gradle)
Content coming soon...
Introduction to Spring Boot
Content coming soon...
Final Project — Enterprise Java App
Content coming soon...