A Beginner's Journey into Java: Writing Your First Real-World Program

Why Learn Java?
Java stands as one of the most powerful and enduring programming languages, renowned for its simplicity, robustness, and versatility. Over the years, it has carved a niche across diverse domains, ranging from mobile and web applications to enterprise-level systems, scientific computing, and even embedded devices. Its enduring popularity is a testament to its adaptability and relevance, making it an indispensable skill for students and professionals alike.
One of Java's most remarkable traits is its platform independence, encapsulated in the philosophy of "Write Once, Run Anywhere" (WORA). Programs written in Java can seamlessly run on any platform equipped with a Java Virtual Machine (JVM), sparing developers the hassle of dealing with hardware-specific constraints. This feature has not only widened its applicability but also contributed to its dominance in industry and academia.
For students beginning their programming journey, Java offers an approachable yet powerful starting point. It provides the right balance between simplicity and structure, making it ideal for learning foundational programming concepts such as object-oriented design, data structures, and algorithms. As you grow in skill and ambition, Java supports you in transitioning from writing simple console-based programs to developing full-fledged applications used by millions.
The motivation to learn Java lies not just in its capabilities but also in the doors it opens. Mastery of Java equips you with skills to build dynamic websites, responsive mobile applications, robust back-end systems, and scalable enterprise solutions. From writing your first "Hello, World!" program to architecting complex software, Java's ecosystem offers the tools and opportunities to evolve into a skilled developer capable of addressing real-world challenges.
Your journey into Java starts here, and the possibilities are endless. Let’s embark on this path together and see how a simple yet elegant programming language can become the foundation of your future in technology.
The Java Main Method and the Main Class: The Heart of a Java Program
Every Java program begins its journey with the main
method, which serves as the entry point for execution. The main
method's unique signature allows the Java Virtual Machine (JVM) to identify and start your program. The main
method resides within a main class, which is the Java class containing this crucial method.
The Main Class: Home for the Main Method
In Java, all code exists within classes. The main class is the class containing the main
method. This class typically serves as the launching pad for the program. While a Java application can contain many classes, only the main class must include the main
method.
Here’s an example of a simple main class:
public class MainExample {
public static void main(String[] args) {
System.out.println("Welcome to Java Programming!");
// Display command-line arguments if provided
if (args.length > 0) {
System.out.println("Command-line arguments:");
for (String arg : args) {
System.out.println(arg);
}
}
}
}
This class includes:
Class Declaration: The class is named
MainExample
to reflect its purpose.Main Method: This method starts the program and contains instructions for execution.
Compiling and Running Java Code with javac
and java
Compiling Java Code Using
javac
Thejavac
command compiles Java source code (.java
files) into bytecode (.class
files) that the JVM can execute.Steps to compile the above example:
Save the code in a file named
MainExample.java
. The file name must match the class name containing themain
method.Open a terminal or command prompt and navigate to the directory containing the file.
Compile the file with the following command:
javac MainExample.java
If the code has no errors, this creates a file named
MainExample.class
.
Running the Compiled Program Using
java
Once compiled, you can execute the program using thejava
command, specifying the class name without the.class
extension:java MainExample
Example outputs:
If you run:
java MainExample
The output will be:
Welcome to Java Programming!
If you pass arguments:
java MainExample Hello Java
The output will be:
Welcome to Java Programming! Command-line arguments: Hello Java
Understanding Compilation and Execution Process
Compilation with
javac
:Translates human-readable Java code into bytecode.
Creates
.class
files, each representing a compiled class.
Execution with
java
:- The JVM loads the
.class
file and starts executing themain
method.
- The JVM loads the
Key Points
The main class must be public and should match the file name.
The
main
method is where execution begins.Command-line arguments passed during execution are available as elements in the
String[] args
array.
Understanding Packages: Organizing Your Code
In Java, packages are containers used to organize classes and interfaces into a structured hierarchy. They play a crucial role in keeping code modular, readable, and manageable as your projects grow. Much like folders on a computer, packages help group related files, making it easier to locate and work with them.
What is a Package?
A package in Java is a namespace that organizes classes and interfaces. It’s essentially a way to group related classes to:
Avoid naming conflicts.
Enhance code readability and maintainability.
Control access to classes and interfaces using access modifiers.
For example, the java.util
package contains utility classes like ArrayList
and HashMap
, while the java.io
package deals with input and output operations.
The package
Keyword
The package
keyword defines the package to which a class belongs. This declaration must be the first statement in a Java file (except for comments).
Example:
package com.example.library;
public class Book {
private String title;
private String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
public void displayInfo() {
System.out.println("Title: " + title + ", Author: " + author);
}
}
Here:
The class
Book
belongs to the packagecom.example.library
.The package name reflects a hierarchical structure (like nested folders).
Real-World Analogy: Packages as Folders
Think of your computer's file system. Files are stored in folders and subfolders to keep things organized. Similarly:
A package is like a folder.
Classes and interfaces are like files inside the folder.
A fully qualified class name (e.g.,
com.example.library.Book
) includes the package path, just like a file path on your computer.
Benefits of Using Packages
Code Organization: Packages group related classes logically, making your codebase easier to navigate.
Avoiding Naming Conflicts: Packages create unique namespaces. For example, two developers can create a class named
Book
, but as long as they are in different packages, there is no conflict (e.g.,com.library.Book
vs.com.store.Book
).Better Maintainability: Packages encourage modularity, making it easier to manage and modify parts of your program without affecting unrelated components.
Access Control: Using access modifiers (e.g.,
public
,protected
, default), you can restrict or expose access to classes and methods within or outside a package.
Default Package vs. Custom Packages
Default Package:
If you do not specify a package, your class belongs to the default package. While this is fine for small projects or learning, it’s not suitable for larger projects due to a lack of organization and potential naming conflicts.public class DefaultExample { public static void main(String[] args) { System.out.println("This class belongs to the default package."); } }
Compile and run directly:
javac DefaultExample.java java DefaultExample
Custom Packages:
For larger projects, create custom packages to organize classes. For instance, in a library management system:src/ com/ example/ library/ Book.java Library.java
Compilation:
javac -d . src/com/example/library/Book.java src/com/example/library/Library.java
Execution:
java com.example.library.Library
Creating a Multi-Class, Multi-Package Java Program
Let’s build a small library management system in Java, with a focus on organizing the code using multiple classes and packages. This example will illustrate how separating classes into logical packages improves clarity and maintainability.
Scenario Overview
The library management system will include:
A
Library
class to manage operations (core logic).A
Book
class to represent books (data model).A
Member
class to represent library members (data model).
These classes will be divided into the following packages:
library
: Contains the core logic classLibrary
.models
: Contains data model classesBook
andMember
.
Directory Structure
We’ll organize the files into a directory structure like this:
src/
library/
Library.java
models/
Book.java
Member.java
Code Walkthrough
1. Book.java
(models package)
Defines the attributes and behavior of a book.
package models;
public class Book {
private String title;
private String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
@Override
public String toString() {
return "Book{" + "title='" + title + '\'' + ", author='" + author + '\'' + '}';
}
}
2. Member.java
(models package)
Represents a library member.
package models;
public class Member {
private String name;
private int memberId;
public Member(String name, int memberId) {
this.name = name;
this.memberId = memberId;
}
public String getName() {
return name;
}
public int getMemberId() {
return memberId;
}
@Override
public String toString() {
return "Member{" + "name='" + name + '\'' + ", memberId=" + memberId + '}';
}
}
3. Library.java
(library package)
Implements the core library functionality.
package library;
import models.Book;
import models.Member;
import java.util.ArrayList;
import java.util.List;
public class Library {
private List<Book> books = new ArrayList<>();
private List<Member> members = new ArrayList<>();
public void addBook(Book book) {
books.add(book);
System.out.println("Added book: " + book);
}
public void addMember(Member member) {
members.add(member);
System.out.println("Added member: " + member);
}
public void listBooks() {
System.out.println("Books in library:");
for (Book book : books) {
System.out.println(book);
}
}
public void listMembers() {
System.out.println("Library members:");
for (Member member : members) {
System.out.println(member);
}
}
public static void main(String[] args) {
Library library = new Library();
Book book1 = new Book("1984", "George Orwell");
Book book2 = new Book("To Kill a Mockingbird", "Harper Lee");
Member member1 = new Member("Alice", 1);
Member member2 = new Member("Bob", 2);
library.addBook(book1);
library.addBook(book2);
library.addMember(member1);
library.addMember(member2);
library.listBooks();
library.listMembers();
}
}
Compiling and Running the Program
Compile All Classes Use the
javac
command to compile all.java
files, specifying the source directory and the output directory for compiled files:javac -d . src/models/Book.java src/models/Member.java src/library/Library.java
The
-d .
flag ensures that the compiled.class
files are placed in the appropriate package structure.After compilation, your directory structure will look like this:
library/ Library.class models/ Book.class Member.class
Run the Program Run the
Library
class using thejava
command, specifying the fully qualified class name:java library.Library
Output
The program will display:
Added book: Book{title='1984', author='George Orwell'}
Added book: Book{title='To Kill a Mockingbird', author='Harper Lee'}
Added member: Member{name='Alice', memberId=1}
Added member: Member{name='Bob', memberId=2}
Books in library:
Book{title='1984', author='George Orwell'}
Book{title='To Kill a Mockingbird', author='Harper Lee'}
Library members:
Member{name='Alice', memberId=1}
Member{name='Bob', memberId=2}
Why This Organization is Helpful
Code Organization: Logical separation of classes ensures that each part of the program is easy to find and understand.
Scalability: Adding new features, such as
Loan
orCatalog
, is straightforward without disrupting the existing structure.Reusability: Data models like
Book
andMember
can be reused in other systems or applications.Avoiding Conflicts: Using packages prevents naming conflicts across large projects.
Compiling Java Code with javac
The javac
compiler is a fundamental part of the Java Development Kit (JDK). Its primary role is to convert human-readable Java source files (.java
) into bytecode (.class
), a platform-independent intermediate representation that the Java Virtual Machine (JVM) can execute.
How javac
Works
Reads the
.java
file(s) containing Java code.Validates the code against Java’s syntax and semantic rules.
Generates
.class
files containing bytecode, which can be run by the JVM.
Compiling a Multi-Package Program
Consider the library management system with the following structure:
src/
library/
Library.java
models/
Book.java
Member.java
To compile the entire program:
javac -d . src/library/Library.java src/models/Book.java src/models/Member.java
Here’s what the command does:
-d .
: The-d
flag specifies the root directory where compiled.class
files will be placed.If omitted, all
.class
files are created in the current directory, ignoring their package hierarchy.With
-d .
, thejavac
compiler generates subdirectories matching the package structure (library
andmodels
).
src/library/
Library.java
and other arguments: Specify the source files to compile.
After compilation, the directory structure looks like this:
library/
Library.class
models/
Book.class
Member.class
Running Java Programs with java
The java
command invokes the JVM to execute compiled bytecode. The JVM:
Loads the
.class
file into memory.Locates the
main
method in the specified class.Begins executing the instructions defined in the
main
method.
Executing a Multi-Package Program
To run the program:
java library.Library
Here’s what happens:
library.Library
: Specifies the fully qualified class name of theLibrary
class:library
: The package containing the class.Library
: The class name itself.
The JVM looks for the
Library.class
file in thelibrary
directory and executes itsmain
method.
Importance of Package Names
The JVM uses package names to locate classes. If the compiled .class
files are not in the correct directories matching their package structure, the JVM cannot find them.
For example, this will result in an error:
java Library
Output:
Error: Could not find or load main class Library
Troubleshooting Common Errors
ClassNotFoundException
Cause: The JVM cannot locate the
.class
file corresponding to the specified fully qualified class name.Solution: Ensure that:
The
javac
command was run with the-d
flag to create the proper package structure.The
java
command specifies the fully qualified class name.
Incorrect Package Declaration
Cause: The
package
declaration in the.java
file doesn’t match the directory structure.Solution: Verify that the
package
name in the code matches the directory hierarchy.
Missing
main
MethodCause: The specified class doesn’t contain a
main
method with the signature:public static void main(String[] args)
Solution: Ensure the class has the correct
main
method.
Recap: Key Steps for Success
Use
javac -d .
to compile all.java
files while preserving the package structure.Run the program with
java
by specifying the fully qualified class name.Verify the package declarations, directory structure, and class paths to avoid common errors.
Creating a Multi-Class, Multi-Package Java Program with Two-Level Packages: A Banking System Example
For a fresh perspective, let’s build a simple banking system where we organize the project into two-level packages. This will demonstrate how to manage a hierarchical package structure and maintain clarity in large-scale projects.
Scenario Overview
We’ll implement a banking system with:
Banking Operations: Handle transactions such as deposit and withdrawal.
Data Models: Represent entities like
Account
andCustomer
.
Directory Structure with Two-Level Packages
The classes will be organized as follows:
src/
banking/
operations/
Transaction.java
models/
Account.java
Customer.java
Code Walkthrough
1. Account.java
package banking.models;
public class Account {
private String accountNumber;
private double balance;
public Account(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
public String getAccountNumber() {
return accountNumber;
}
public double getBalance() {
return balance;
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: " + amount + ", New Balance: " + balance);
} else {
System.out.println("Invalid deposit amount.");
}
}
public boolean withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrew: " + amount + ", Remaining Balance: " + balance);
return true;
} else {
System.out.println("Invalid withdrawal amount or insufficient funds.");
return false;
}
}
@Override
public String toString() {
return "Account{accountNumber='" + accountNumber + "', balance=" + balance + '}';
}
}
package banking.models;
public class Customer {
private String name;
private String customerId;
public Customer(String name, String customerId) {
this.name = name;
this.customerId = customerId;
}
public String getName() {
return name;
}
public String getCustomerId() {
return customerId;
}
@Override
public String toString() {
return "Customer{name='" + name + "', customerId='" + customerId + "'}";
}
}
package banking.operations;
import banking.models.Account;
import banking.models.Customer;
public class Transaction {
public static void main(String[] args) {
Customer customer = new Customer("John Doe", "C123");
Account account = new Account("A456", 1000.00);
System.out.println("Customer Details: " + customer);
System.out.println("Account Details: " + account);
account.deposit(500.00); // Deposit money
account.withdraw(300.00); // Withdraw money
account.withdraw(1500.00); // Attempt to overdraw
}
}
Step-by-Step Instructions
Step 1: Create the Project Folder Structure
Open a terminal or file explorer.
Create the following directory structure:
src/ banking/ operations/ Transaction.java models/ Account.java Customer.java
Step 2: Write the Code
- Save each class in its respective folder, ensuring the file name matches the class name.
Step 3: Compile the Program
Open the terminal and navigate to the
src
directory.Compile all the classes using the
javac
command:javac -d . banking/models/Account.java banking/models/Customer.java banking/operations/Transaction.java
The
-d .
flag creates the appropriate package structure for the compiled files:banking/ models/ Account.class Customer.class operations/ Transaction.class
Step 4: Run the Program Execute the Transaction
class using the java
command:
java banking.operations.Transaction
Expected Output
Customer Details: Customer{name='John Doe', customerId='C123'}
Account Details: Account{accountNumber='A456', balance=1000.0}
Deposited: 500.0, New Balance: 1500.0
Withdrew: 300.0, Remaining Balance: 1200.0
Invalid withdrawal amount or insufficient funds.
Tips and Best Practices for Beginners
Organize Code Hierarchically: Use multiple levels in packages to reflect the functionality and relationships between components.
Write Meaningful Names: Use clear and descriptive names for classes and packages.
Incremental Compilation: Compile and test one package or class at a time to catch errors early.
Subscribe to my newsletter
Read articles from Jyotiprakash Mishra directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Jyotiprakash Mishra
Jyotiprakash Mishra
I am Jyotiprakash, a deeply driven computer systems engineer, software developer, teacher, and philosopher. With a decade of professional experience, I have contributed to various cutting-edge software products in network security, mobile apps, and healthcare software at renowned companies like Oracle, Yahoo, and Epic. My academic journey has taken me to prestigious institutions such as the University of Wisconsin-Madison and BITS Pilani in India, where I consistently ranked among the top of my class. At my core, I am a computer enthusiast with a profound interest in understanding the intricacies of computer programming. My skills are not limited to application programming in Java; I have also delved deeply into computer hardware, learning about various architectures, low-level assembly programming, Linux kernel implementation, and writing device drivers. The contributions of Linus Torvalds, Ken Thompson, and Dennis Ritchie—who revolutionized the computer industry—inspire me. I believe that real contributions to computer science are made by mastering all levels of abstraction and understanding systems inside out. In addition to my professional pursuits, I am passionate about teaching and sharing knowledge. I have spent two years as a teaching assistant at UW Madison, where I taught complex concepts in operating systems, computer graphics, and data structures to both graduate and undergraduate students. Currently, I am an assistant professor at KIIT, Bhubaneswar, where I continue to teach computer science to undergraduate and graduate students. I am also working on writing a few free books on systems programming, as I believe in freely sharing knowledge to empower others.