Learning Java without building projects is like studying music without ever touching an instrument. You might understand all the theory, but you will not develop real, practical skills that employers look for. The best way to get job-ready is by working on projects that fit your skill level but also challenge you a little.
Beginner projects focus on the basics, like variables, loops, and simple object-oriented programming. Intermediate projects introduce more complexity with databases, graphical user interfaces, and larger codebases. Advanced projects move you closer to professional development with frameworks such as Spring Boot, complex business logic, and real integrations that you can encounter in a Java backend developer course.
Below, you will find 15 Java projects organized by difficulty. Each project aims to help you build practical skills and create a portfolio that shows employers you can do real work.
Here are the projects we’ll cover:

As a beginner, your goal is not to build something huge. You want Java projects that help you practice syntax, conditionals, loops, methods, basic classes and maybe a little file I/O. These Java projects prepare you for the next stage where you begin to learn Java backend development through APIs, databases, and real world project structures.
These first five projects are simple enough to complete in a few days, but rich enough that you can keep improving them over time.
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("First number: ");
double a = scanner.nextDouble();
System.out.print("Operator (+, -, *, /): ");
char op = scanner.next().charAt(0);
System.out.print("Second number: ");
double b = scanner.nextDouble();
double result = switch (op) {
case '+' -> a + b;
case '-' -> a - b;
case '*' -> a * b;
case '/' -> b != 0 ? a / b : Double.NaN;
default -> Double.NaN;
};
System.out.println("Result: " + result);
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.Random;
import Java.util.Scanner;
public class NumberGuessingGame {
public static void main(String[] args) {
Random random = new Random();
int numberToGuess = random.nextInt(100) + 1;
Scanner scanner = new Scanner(System.in);
int guess = 0;
int attempts = 0;
System.out.println("Guess a number between 1 and 100:");
while (guess != numberToGuess) {
System.out.print("Your guess: ");
if(scanner.hasNextInt()){
guess = scanner.nextInt();
attempts++;
if (guess < numberToGuess) {
System.out.println("Too low!");
} else if (guess > numberToGuess) {
System.out.println("Too high!");
} else {
System.out.println("Correct! You guessed it in " + attempts + " tries.");
}
} else {
System.out.println("Please enter a valid number.");
scanner.next(); // clear invalid input
}
}
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.Scanner;
public class TemperatureConverter {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Choose conversion type:");
System.out.println("1: Celsius to Fahrenheit");
System.out.println("2: Fahrenheit to Celsius");
int choice = scanner.nextInt();
System.out.print("Enter the temperature: ");
double temp = scanner.nextDouble();
double converted = 0;
switch (choice) {
case 1 -> converted = (temp * 9/5) + 32;
case 2 -> converted = (temp - 32) * 5/9;
default -> System.out.println("Invalid choice");
}
System.out.println("Converted temperature: " + converted);
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.ArrayList;
import Java.util.Scanner;
public class TodoList {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<String> tasks = new ArrayList<>();
boolean running = true;
while (running) {
System.out.println("\n1. Add Task\n2. List Tasks\n3. Remove Task\n4. Exit");
System.out.print("Choose an option: ");
int choice = scanner.nextInt();
scanner.nextLine(); // Consume newline
switch (choice) {
case 1 -> {
System.out.print("Enter task: ");
tasks.add(scanner.nextLine());
}
case 2 -> {
System.out.println("Tasks:");
for (int i = 0; i < tasks.size(); i++) {
System.out.println((i + 1) + ". " + tasks.get(i));
}
}
case 3 -> {
System.out.print("Enter task number to remove: ");
int taskNum = scanner.nextInt();
if (taskNum > 0 && taskNum <= tasks.size()) {
tasks.remove(taskNum - 1);
} else {
System.out.println("Invalid task number.");
}
}
case 4 -> running = false;
default -> System.out.println("Invalid choice.");
}
}
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.Scanner;
class Account {
private String owner;
private int accountNumber;
private double balance;
public Account(String owner, int accountNumber, double balance) {
this.owner = owner;
this.accountNumber = accountNumber;
this.balance = balance;
}
public void deposit(double amount) {
if (amount > 0) balance += amount;
else System.out.println("Invalid amount.");
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) balance -= amount;
else System.out.println("Insufficient balance or invalid amount.");
}
public void checkBalance() {
System.out.println("Balance: $" + balance);
}
}
public class BankSystem {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Account account = new Account("John Doe", 12345, 500);
boolean running = true;
while (running) {
System.out.println("\n1. Deposit\n2. Withdraw\n3. Check Balance\n4. Exit");
System.out.print("Choose an option: ");
int choice = scanner.nextInt();
switch (choice) {
case 1 -> {
System.out.print("Enter amount to deposit: ");
account.deposit(scanner.nextDouble());
}
case 2 -> {
System.out.print("Enter amount to withdraw: ");
account.withdraw(scanner.nextDouble());
}
case 3 -> account.checkBalance();
case 4 -> running = false;
default -> System.out.println("Invalid choice.");
}
}
}
}
Once you’ve got a good handle on classes, methods, loops, and collections, you’re ready to take on intermediate Java projects. These projects often involve working with databases, creating graphical interfaces, and handling networking. They usually take a bit longer, typically one to three weeks, but they also introduce concepts you would explore in a Java backend course and give you a much clearer sense of how real-world business applications are built.
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.sql.*;
import Java.util.Scanner;
public class LibrarySystem {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/library";
String user = "root";
String password = "password";
try (Connection conn = DriverManager.getConnection(url, user, password);
Scanner scanner = new Scanner(System.in)) {
boolean running = true;
while (running) {
System.out.println("\n1. Add Book\n2. Search Book\n3. Borrow Book\n4. Return Book\n5. Exit");
System.out.print("Choose an option: ");
int choice = scanner.nextInt();
scanner.nextLine(); // Consume newline
switch (choice) {
case 1 -> {
System.out.print("Book Title: ");
String title = scanner.nextLine();
System.out.print("Author: ");
String author = scanner.nextLine();
String sql = "INSERT INTO books (title, author, available) VALUES (?, ?, true)";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, title);
stmt.setString(2, author);
stmt.executeUpdate();
System.out.println("Book added successfully.");
}
}
case 2 -> {
System.out.print("Enter title to search: ");
String search = scanner.nextLine();
String sql = "SELECT * FROM books WHERE title LIKE ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, "%" + search + "%");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("title") + " by " + rs.getString("author"));
}
}
}
case 3 -> System.out.println("Borrow book logic here...");
case 4 -> System.out.println("Return book logic here...");
case 5 -> running = false;
default -> System.out.println("Invalid choice.");
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.*;
public class QuizApp {
static class Question {
String question;
String answer;
Question(String question, String answer) {
this.question = question;
this.answer = answer;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<Question> questions = new ArrayList<>();
questions.add(new Question("What is Java?", "Programming Language"));
questions.add(new Question("Capital of France?", "Paris"));
int score = 0;
for (Question q : questions) {
System.out.println(q.question);
System.out.print("Your answer: ");
String userAnswer = scanner.nextLine();
if (userAnswer.equalsIgnoreCase(q.answer)) {
System.out.println("Correct!");
score++;
} else {
System.out.println("Wrong! Correct answer: " + q.answer);
}
}
System.out.println("Quiz finished! Your score: " + score + "/" + questions.size());
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.io.*;
import Java.net.*;
import Java.util.*;
public class Server {
private static Set<PrintWriter> clientWriters = new HashSet<>();
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("Server started on port 12345...");
while (true) {
Socket client = serverSocket.accept();
new Thread(new ClientHandler(client)).start();
}
}
static class ClientHandler implements Runnable {
private Socket socket;
private PrintWriter out;
ClientHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
out = new PrintWriter(socket.getOutputStream(), true);
clientWriters.add(out);
String message;
while ((message = in.readLine()) != null) {
for (PrintWriter writer : clientWriters) {
writer.println(message);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
public class Product {
private String name;
private int quantity;
private double price;
public Product(String name, int quantity, double price) {
this.name = name;
this.quantity = quantity;
this.price = price;
}
public String getName() { return name; }
public int getQuantity() { return quantity; }
public double getPrice() { return price; }
public void setQuantity(int quantity) { this.quantity = quantity; }
public void setPrice(double price) { this.price = price; }
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.Scanner;
public class Main {
public static void main(String[] args) {
Student s1 = new Student(1, "Alice");
Student s2 = new Student(2, "Bob");
Course c1 = new Course("CS101", "Computer Science Basics");
Course c2 = new Course("MATH101", "Calculus I");
Enrollment enrollment = new Enrollment();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("1. Enroll Student\n2. List Enrollments\nChoose option:");
int option = scanner.nextInt();
scanner.nextLine(); // consume newline
if (option == 1) {
System.out.println("Enter student name (Alice/Bob):");
String name = scanner.nextLine();
Student selectedStudent = name.equalsIgnoreCase("Alice") ? s1 : s2;
System.out.println("Enter course code (CS101/MATH101):");
String code = scanner.nextLine();
Course selectedCourse = code.equalsIgnoreCase("CS101") ? c1 : c2;
enrollment.enroll(selectedStudent, selectedCourse);
} else if (option == 2) {
enrollment.listEnrollments();
}
}
}
}
When you reach the advanced stage, your Java projects begin to look like real products. You will work with frameworks, security, performance optimization, and sometimes explore machine learning or IoT.
Advanced projects are more complex and take more time, but they closely reflect the kind of work you might do in a professional setting. You do not need to rush. Once you feel confident with intermediate projects and core Java, you can choose an advanced project and work on it at your own pace.
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.*;
class Product {
String name;
double price;
Product(String name, double price) {
this.name = name;
this.price = price;
}
}
class User {
String username;
List<Product> cart = new ArrayList<>();
User(String username) {
this.username = username;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Sample products
List<Product> products = new ArrayList<>();
products.add(new Product("Laptop", 1200));
products.add(new Product("Phone", 700));
// Sample user
User user = new User("Alice");
while (true) {
System.out.println("\n1. View Products\n2. Add to Cart\n3. View Cart\n4. Checkout");
System.out.print("Choose option: ");
int option = scanner.nextInt();
scanner.nextLine(); // consume newline
if (option == 1) {
System.out.println("Products available:");
for (int i = 0; i < products.size(); i++) {
System.out.println((i+1) + ". " + products.get(i).name + " - $" + products.get(i).price);
}
} else if (option == 2) {
System.out.print("Enter product number to add to cart: ");
int p = scanner.nextInt() - 1;
if (p >= 0 && p < products.size()) {
user.cart.add(products.get(p));
System.out.println(products.get(p).name + " added to cart.");
} else {
System.out.println("Invalid product number.");
}
} else if (option == 3) {
System.out.println("Cart contents:");
for (Product p : user.cart) {
System.out.println("- " + p.name + " $" + p.price);
}
} else if (option == 4) {
double total = 0;
for (Product p : user.cart) total += p.price;
System.out.println("Order placed. Total: $" + total);
user.cart.clear();
}
}
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.*;
class Device {
String name;
boolean isOn;
Device(String name) {
this.name = name;
this.isOn = false;
}
void turnOn() {
isOn = true;
System.out.println(name + " turned ON.");
}
void turnOff() {
isOn = false;
System.out.println(name + " turned OFF.");
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Simulated devices
Map<String, Device> devices = new HashMap<>();
devices.put("Light", new Device("Light"));
devices.put("Heater", new Device("Heater"));
devices.put("AC", new Device("AC"));
while (true) {
System.out.println("\n1. Toggle Light\n2. Toggle Heater\n3. Toggle AC\n4. Show Status");
System.out.print("Choose option: ");
int choice = scanner.nextInt();
switch (choice) {
case 1:
toggleDevice(devices.get("Light"));
break;
case 2:
toggleDevice(devices.get("Heater"));
break;
case 3:
toggleDevice(devices.get("AC"));
break;
case 4:
showStatus(devices);
break;
default:
System.out.println("Invalid choice.");
}
}
}
static void toggleDevice(Device device) {
if (device.isOn) device.turnOff();
else device.turnOn();
}
static void showStatus(Map<String, Device> devices) {
System.out.println("Device Status:");
for (Device d : devices.values()) {
System.out.println("- " + d.name + ": " + (d.isOn ? "ON" : "OFF"));
}
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.util.*;
class Patient {
String id;
String name;
int age;
Patient(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
public class Main {
static Scanner scanner = new Scanner(System.in);
static Map<String, Patient> patients = new HashMap<>();
public static void main(String[] args) {
while (true) {
System.out.println("\n1. Add Patient\n2. View Patient\n3. Delete Patient\n4. List All Patients");
System.out.print("Choose option: ");
int choice = scanner.nextInt();
scanner.nextLine(); // consume newline
switch (choice) {
case 1: addPatient(); break;
case 2: viewPatient(); break;
case 3: deletePatient(); break;
case 4: listPatients(); break;
default: System.out.println("Invalid choice.");
}
}
}
static void addPatient() {
System.out.print("Enter Patient ID: ");
String id = scanner.nextLine();
System.out.print("Enter Name: ");
String name = scanner.nextLine();
System.out.print("Enter Age: ");
int age = scanner.nextInt();
scanner.nextLine(); // consume newline
patients.put(id, new Patient(id, name, age));
System.out.println("Patient added successfully.");
}
static void viewPatient() {
System.out.print("Enter Patient ID: ");
String id = scanner.nextLine();
Patient p = patients.get(id);
if (p != null) {
System.out.println("Patient ID: " + p.id + ", Name: " + p.name + ", Age: " + p.age);
} else {
System.out.println("Patient not found.");
}
}
static void deletePatient() {
System.out.print("Enter Patient ID: ");
String id = scanner.nextLine();
if (patients.remove(id) != null) {
System.out.println("Patient deleted successfully.");
} else {
System.out.println("Patient not found.");
}
}
static void listPatients() {
if (patients.isEmpty()) {
System.out.println("No patients found.");
} else {
System.out.println("Patient List:");
for (Patient p : patients.values()) {
System.out.println("- " + p.id + ": " + p.name + ", Age " + p.age);
}
}
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.objdetect.CascadeClassifier;
import Java.util.Scanner;
public class Main {
static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter path to image: ");
String imagePath = scanner.nextLine();
CascadeClassifier faceDetector = new CascadeClassifier("haarcascade_frontalface_alt.xml");
Mat image = Imgcodecs.imread(imagePath);
if (image.empty()) {
System.out.println("Image not found!");
return;
}
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(image, faceDetections);
System.out.println("Detected " + faceDetections.toArray().length + " face(s).");
for (Rect rect : faceDetections.toArray()) {
System.out.println("Face at [x=" + rect.x + ", y=" + rect.y + ", width=" + rect.width + ", height=" + rect.height + "]");
}
// Optional: integrate ML model for recognition here
System.out.println("Face recognition can be added using Deeplearning4j or Apache Mahout.");
}
}
Project details
Key features
Learning outcome
Key Tools and Libraries
A simple console version can look like this:
import Java.security.MessageDigest;
import Java.util.ArrayList;
import Java.util.Scanner;
class Block {
public String data;
public String previousHash;
public String hash;
public int nonce;
public Block(String data, String previousHash) {
this.data = data;
this.previousHash = previousHash;
this.nonce = 0;
this.hash = calculateHash();
}
public String calculateHash() {
try {
String input = previousHash + data + nonce;
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = digest.digest(input.getBytes("UTF-8"));
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void mineBlock(int difficulty) {
String target = new String(new char[difficulty]).replace('\0', '0');
while (!hash.substring(0, difficulty).equals(target)) {
nonce++;
hash = calculateHash();
}
System.out.println("Block mined: " + hash);
}
}
public class Main {
public static ArrayList<Block> blockchain = new ArrayList<>();
public static int difficulty = 4;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter data for the first block: ");
String data = scanner.nextLine();
Block genesisBlock = new Block(data, "0");
genesisBlock.mineBlock(difficulty);
blockchain.add(genesisBlock);
System.out.print("Enter data for the next block: ");
data = scanner.nextLine();
Block block2 = new Block(data, blockchain.get(blockchain.size() - 1).hash);
block2.mineBlock(difficulty);
blockchain.add(block2);
System.out.println("\nBlockchain:");
for (Block block : blockchain) {
System.out.println("Data: " + block.data);
System.out.println("Hash: " + block.hash);
System.out.println("Previous: " + block.previousHash + "\n");
}
}
}
Java remains one of the most reliable paths into software development. It is used by Fortune 500 companies, runs on billions of devices, and has a global community of more than 10 million developers. The ecosystem keeps expanding, which makes Java a strong long-term skill for anyone building a tech career.
It is also more approachable than many expect. Most developers say Java is not difficult to learn when you follow a clear plan and practice consistently, especially when pairing hands-on projects with structured study through Java backend courses.
The 15 projects in this guide give you a clear progression from simple console apps to complex systems. Start with a beginner project you can finish quickly, then move to intermediate projects with databases, and finally try advanced projects that match your interests and career goals.
Using a guided platform like Hyperskill can help, providing a structured path, real projects, and feedback. The most important step is to start. Pick a project, open your IDE, and write the first line of code. Each completed project brings you closer to a job-ready portfolio.