Java Programming
Beginner (Basics) — Foundations of Java
Java is one of the most popular programming languages in the world. Its platform independence, strong object-oriented structure, and vast ecosystem make it a valuable language for anyone aiming to build robust, scalable applications. This guide will help you build a strong foundation in Java, especially if you’re just starting out.
Introduction to Java
What is Java?
Java is a high-level, object-oriented, and general-purpose programming language developed by Sun Microsystems (now owned by Oracle). It is designed to be simple, secure, and platform-independent. One of Java’s biggest strengths is its philosophy: “Write Once, Run Anywhere.” This means Java programs can run on any device equipped with a Java Virtual Machine (JVM), regardless of the underlying hardware or operating system.
History and Features
Java was introduced in 1995 and has since become integral to enterprise systems, Android development, and web applications. Key features include:
-
Platform independence via the JVM
-
Automatic memory management through garbage collection
-
Robust and secure execution model
-
Rich standard library for networking, file I/O, collections, etc.
Java Virtual Machine (JVM), JRE, and JDK
-
JVM (Java Virtual Machine): Executes Java bytecode and enables platform independence.
-
JRE (Java Runtime Environment): Contains JVM and libraries required to run Java applications.
-
JDK (Java Development Kit): Includes the JRE plus compilers and tools needed for development.
Installing and Setting Up an IDE
To begin coding in Java, download the JDK from Oracle’s official site. Then choose an IDE such as Eclipse, IntelliJ IDEA, or VS Code.
Setting up in IntelliJ IDEA:
-
Install IntelliJ and open it.
-
Create a new project.
-
Add a new Java class.
-
Write your first Java program.
Java Syntax and Structure
Main Method Structure: public static void main(String[] args)
Every Java application starts with the main()
method:
-
public
: Accessible from anywhere -
static
: Doesn’t need an object to run -
void
: No return value -
String[] args
: Accepts command-line arguments
Printing Output with System.out.println
Use System.out.println()
to print messages to the console:
Comments
Comments make code easier to understand:
File and Class Naming Conventions
-
Java file names should match the class name exactly.
-
Class names should begin with an uppercase letter.
-
Use CamelCase for class names (e.g.,
StudentRecord
).
Variables and Data Types
Primitive Types
Java provides several built-in primitive types:
Type | Size | Example |
---|---|---|
int |
4 bytes | 100 |
float |
4 bytes | 3.14f |
double |
8 bytes | 3.14159 |
boolean |
1 bit | true / false |
char |
2 bytes | ‘A’ |
Reference Types
Reference types refer to objects and include classes, arrays, and interfaces.
Type Casting and Conversion
You can convert between compatible data types:
Implicit casting (widening):
Explicit casting (narrowing):
Use the final
keyword to declare constants:
Once assigned, a final variable cannot be changed.
Operators in Java
Arithmetic, Logical, Relational, Assignment, Bitwise
Arithmetic Operators:
Relational Operators:
Logical Operators:
Assignment Operators:
Bitwise Operators:
Precedence and Associativity
Operator precedence determines the order of execution. Multiplication has higher precedence than addition:
Associativity defines the direction — most operators are left-to-right, except assignment which is right-to-left.
Control Flow Statements
Conditional Statements: if
, else if
, switch
If-Else Example:
Looping: for
, while
, do-while
For Loop:
While Loop:
Do-While Loop:
Jump Statements: break
, continue
, return
-
break
: Exits the loop early. -
continue
: Skips to the next iteration. -
return
: Exits the current method.
Input and Output
Reading Input Using Scanner
Java uses the Scanner
class to read user input:
-
nextLine()
: Reads entire line -
nextInt()
: Reads an integer -
nextDouble()
: Reads a decimal
Formatting Output with System.out.printf
Use printf
for formatted output:
This is especially useful in financial applications or reports where precision matters.
Intermediate (Core Java) — Object-Oriented and Collections
Now that you’ve mastered the Java basics, it’s time to explore the heart of the language: Object-Oriented Programming (OOP) and collections. These features make Java powerful, scalable, and capable of handling complex applications. Let’s break down these intermediate concepts in depth.
Object-Oriented Programming (OOP)
Classes and Objects
Java is built on the object-oriented paradigm. At its core, this means modeling real-world entities using classes (blueprints) and objects (instances).
Creating and using an object:
Each object holds its own state and behavior, defined by variables and methods in the class.
Methods and Constructors
Methods define actions an object can perform, while constructors initialize new objects.
provides a default constructor if none is defined. However, defining your own allows better control during object creation.
The this
Keyword
this
is a reference to the current object. It’s commonly used when parameter names conflict with instance variables.
Using this
eliminates ambiguity and improves readability.
Access Modifiers
Java provides four levels of access control:
-
private
: Accessible only within the class. -
default
: Accessible within the package. -
protected
: Accessible within the package and subclasses. -
public
: Accessible from anywhere.
Always use the most restrictive access level needed. This promotes data encapsulation and security.
Encapsulation, Inheritance, Polymorphism, Abstraction
These four pillars define OOP in Java:
-
Encapsulation: Wrapping data and methods into a single unit.
-
Inheritance: One class inherits properties of another.
-
Polymorphism: A single interface with multiple implementations.
-
Abstraction: Hiding internal details using abstract classes or interfaces.
OOP makes code reusable, extendable, and easier to maintain.
Arrays and Strings
Single and Multidimensional Arrays
Arrays store fixed-size sequences of values of the same type.
Multidimensional Arrays:
Arrays are great for static data, but collections are better for dynamic storage.
The String
Class and Its Methods
Java strings are immutable and offer many useful methods:
Because strings are objects, they support method chaining and comparison (equals()
, compareTo()
).
StringBuilder
and StringBuffer
Unlike String
, these classes are mutable and ideal for string manipulation.
StringBuffer
is thread-safe but slightly slower than StringBuilder
. Choose according to your need.
Exception Handling
try, catch, finally, throw, throws
Java handles runtime errors through exceptions. This keeps the program from crashing unexpectedly.
-
try
: Wraps the risky code -
catch
: Handles specific exceptions -
finally
: Executes regardless of exception -
throw
: Manually throw an exception -
throws
: Declare an exception in method signature
Checked vs. Unchecked Exceptions
-
Checked exceptions: Checked at compile time (e.g.,
IOException
). -
Unchecked exceptions: Occur at runtime (e.g.,
NullPointerException
).
Use try-catch or throws to handle checked exceptions.
Custom Exceptions
Create your own exceptions for business logic:
This approach enhances code readability and enforces specific rules.
Java Collections Framework
List, Set, Map, Queue
Java Collections handle dynamic data structures. Interfaces like List
, Set
, Map
, and Queue
define behavior, and concrete classes implement them.
-
List: Ordered, allows duplicates
-
Set: Unordered, no duplicates
-
Map: Key-value pairs
-
Queue: FIFO structure
ArrayList, LinkedList, HashSet, TreeSet, HashMap, TreeMap
Each implementation has its strengths:
-
ArrayList
: Fast random access, slower insertions -
LinkedList
: Efficient insertions/deletions -
HashSet
: Fast operations, no order -
TreeSet
: Sorted set -
HashMap
: Unordered key-value storage -
TreeMap
: Sorted key-value pairs
Iterators and for-each Loop
Looping through collections:
Using Iterator:
Iterators offer more control and allow safe removal of elements during traversal.
Static and Final Keywords
Static Methods and Static Blocks
In Java, static members belong to the class itself rather than any individual object.
This means they can be accessed without creating an instance of the class.
Additionally, static blocks are used to initialize static variables and are executed only once when the class is loaded.
Call static methods without creating an object:
Static blocks initialize static data before any constructor.
Final Variables, Methods, and Classes
-
Final variables: Cannot be reassigned.
-
Final methods: Cannot be overridden.
-
Final classes: Cannot be extended.
Use final
for safety, consistency, and optimization.
Wrapper Classes and Autoboxing
Integer, Double, Boolean, etc.
Java provides object equivalents for primitives:
-
int
→Integer
-
double
→Double
-
boolean
→Boolean
Autoboxing and Unboxing
Autoboxing automatically converts primitives to wrapper objects:
This is often used in collections:
Understanding this is key to writing clean, type-safe code.
Inner Classes
Regular Inner Classes
Defined inside another class:
Static Nested Classes
Behaves like a static member:
Anonymous Classes
Defined and instantiated on the fly, often used in event handling:
Local Inner Classes
Defined inside methods and limited to their scope:
Each type of inner class serves a unique purpose, especially in GUI development and encapsulating helper logic.
Advanced Java — Tools, Frameworks, and Concepts
After grasping core Java and object-oriented programming, you’re now ready to explore more advanced features. This section covers essential tools and frameworks that allow Java to power enterprise applications, desktop tools, APIs, and databases. You’ll also dive into Java’s powerful language enhancements introduced from Java 8 onwards.
File Handling and I/O
File Class
The File
class in Java is part of java.io
and is used for file and directory path representations.
The class can also be used to create, delete, and check permissions of files and directories.
Reading and Writing Files
Using FileReader
and BufferedReader
:
Writing with FileWriter
:
Java NIO Package
Introduced in Java 7, the java.nio.file
package offers a more efficient, non-blocking approach.
NIO is preferred for high-performance and scalable file operations.
Threads and Concurrency
Creating Threads
Using the Thread class:
Using the Runnable interface:
Thread Lifecycle
A thread in Java passes through multiple states:
-
New
-
Runnable
-
Running
-
Waiting/Blocked
-
Terminated
These states are managed by the JVM based on scheduling.
Synchronization
Synchronization ensures thread-safe operations, especially when multiple threads access shared resources.
Alternatively, use synchronized blocks for finer control:
wait(), notify(), notifyAll()
These methods allow threads to communicate and coordinate.
Use these methods with caution, as improper usage can lead to deadlocks or missed signals.
Lambda Expressions and Functional Interfaces
What Are Lambdas?
Introduced in Java 8, lambda expressions provide a concise way to implement interfaces with a single abstract method (functional interfaces).
Built-in Functional Interfaces
Located in java.util.function
, these interfaces simplify functional-style programming.
-
Predicate: Evaluates a condition
-
Consumer: Takes a value and returns nothing
-
Function: Takes an input and returns an output
Streams API (Java 8+)
The Streams API simplifies data processing with operations like map()
, filter()
, and reduce()
.
Instead of processing each item manually, streams offer a declarative approach.
They are lazy, meaning operations are only executed when needed.
Moreover, streams can be parallelized, making them efficient for large data sets.
Generics
Generic Classes and Methods
Generics provide type safety and code reusability without casting.
Generic Method Example:
Bounded Types
Bound types restrict the types that can be used with generics.
This ensures only numerical types are used, preventing runtime errors.
Wildcards
-
<?>
: Unknown type -
? extends T
: Accepts T or its subclasses -
? super T
: Accepts T or its superclasses
Wildcards improve flexibility while preserving type safety.
Annotations and Reflection
Built-in Annotations
It provides several annotations that add metadata to code:
-
@Override
: Ensures the method overrides a superclass method -
@Deprecated
: Marks a method as outdated -
@FunctionalInterface
: Ensures only one abstract method
Creating Custom Annotations
You can define your own annotations for frameworks or validations.
Using Reflection
Reflection allows inspection of classes, methods, and fields at runtime.
Reflection is often used in frameworks, but misuse can lead to security issues and performance degradation.
JDBC (Java Database Connectivity)
Connecting to Databases
JDBC enables Java to interact with relational databases.
Executing Queries
PreparedStatement and ResultSet
Use PreparedStatement
to prevent SQL injection:
Transactions and Exception Handling
Transaction management ensures consistency, especially in financial systems.
Packages and Modularization
Creating and Using Packages
Packages help organize code and avoid naming conflicts.
Use the import keyword to access it:
Java Modules (Java 9+)
Modules introduced in Java 9 enhance encapsulation and dependency management.
module-info.java:
Modules allow fine-grained control over what is exposed and what is hidden.