Java Console Applications with OOP

"Java is a powerful object-oriented programming language that enforces structure from the start. Its strict typing and class-based design make it an excellent language for learning core OOP principles like encapsulation, inheritance, and polymorphism."- Claude 2026

Console Application using OOP Introduction

A console application runs in a terminal or command prompt, taking input and producing output as text. Java is a natural fit for console applications because every Java program is built around classes and objects from the very beginning.

Unlike scripting languages that can run top-to-bottom without any structure, Java requires you to think in terms of classes right away. This makes it an excellent starting point for learning Object-Oriented Programming (OOP).

Java Background

Java was created by James Gosling at Sun Microsystems and released in 1995. It was designed with one major goal: write once, run anywhere. Java programs compile to bytecode that runs on the Java Virtual Machine (JVM), making them platform-independent.

Java is a statically typed language, meaning every variable must have a declared type. This catches many errors at compile time rather than at runtime, which leads to more reliable programs.

Key Java Facts
  • Object-oriented from the ground up
  • Strongly and statically typed
  • Compiled to bytecode, run on the JVM
  • Widely used in enterprise, Android, and web back-ends
  • Syntax is similar to C and C++
Every Java program starts with a class:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
TIP: In Java, the filename must match the class name exactly, including capitalization. A class named HelloWorld must be saved as HelloWorld.java.
Building a Class in Java

A class is a blueprint that defines the attributes (data) and methods (behavior) that its objects will have. Think of a class like a template — it describes what something is and what it can do, but it is not the thing itself. A game character is a natural fit: every character has a name and health, and can perform actions like attacking.

Here is a simple Character class. It has two attributes — name and health — and will serve as the foundation for the examples throughout this page.

public class Character {

    // Attributes (instance variables)
    String name;
    int health;

}

This class definition describes the structure of a Character but contains no actual data yet. To store real data, we need to create objects from this class. We do that in a separate class that contains the main method — this is the entry point Java uses to run your program.

Assigning Values to Attributes and Set Methods

Once a class is defined, you create objects using the new keyword. After creating an object, you can assign values to its attributes directly, or through setter methods — methods whose job is to set the value of an attribute.

Example: Direct Assignment vs. Setter Methods
public class Character {

    String name;
    int health;

    // Setter method for name
    public void setName(String name) {
        this.name = name;
    }

    // Setter method for health
    public void setHealth(int health) {
        this.health = health;
    }

}
Using the setters in your main class:
public class CharacterTest {

    public static void main(String[] args) {

        // Create a Character object
        Character player1 = new Character();

        // Use setter methods to assign values
        player1.setName("Hero");
        player1.setHealth(100);

    }

}
TIP: The keyword this inside a setter refers to the current object. It distinguishes the object's attribute (this.name) from the method's parameter (name) when they share the same name.
Get Methods

A getter method (also called an accessor) retrieves the value of an attribute. Together, getters and setters are the standard Java way to control access to an object's data — this is the OOP principle of encapsulation.

When attributes are marked private, they can only be accessed through these getter and setter methods, keeping the internal state of an object protected from unintended changes.

public class Character {

    // private: only accessible within this class
    private String name;
    private int health;

    // Setter methods
    public void setName(String name) {
        this.name = name;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    // Getter methods
    public String getName() {
        return this.name;
    }

    public int getHealth() {
        return this.health;
    }

}
Using getters to retrieve values:
public class CharacterTest {

    public static void main(String[] args) {

        Character player1 = new Character();
        player1.setName("Hero");
        player1.setHealth(100);

        // Use getter methods to retrieve values
        System.out.println("Name: " + player1.getName());
        System.out.println("Health: " + player1.getHealth());

    }

}
Name: Hero
Health: 100
Putting It All Together
This complete example puts everything together in a single class. The main method acts as our test — it creates two Character objects, assigns values using setters, and has them interact through the attack method.
public class Character {

    private String name;
    private int health;

    public void setName(String name) { this.name = name; }
    public void setHealth(int health) { this.health = health; }
    public String getName() { return this.name; }
    public int getHealth() { return this.health; }

    // Attack method: reduces the target's health
    public void attack(Character target) {
        target.setHealth(target.getHealth() - 10);
        System.out.println(this.name + " attacked " + target.getName() + ".");
        System.out.println(target.getName() + " now has " + target.getHealth() + " health.");
    }

    public static void main(String[] args) {

        Character player1 = new Character();
        player1.setName("Hero");
        player1.setHealth(100);

        Character player2 = new Character();
        player2.setName("Villain");
        player2.setHealth(80);

        System.out.println(player1.getName() + " initialized with " + player1.getHealth() + " health.");
        System.out.println(player2.getName() + " initialized with " + player2.getHealth() + " health.");

        player1.attack(player2);
        player2.attack(player1);

    }

}
Running this program outputs:
Hero initialized with 100 health.
Villain initialized with 80 health.
Hero attacked Villain.
Villain now has 70 health.
Villain attacked Hero.
Hero now has 90 health.
Try it yourself: JDoodle Java Compiler
About the Debugger

Most IDEs include a debugger — a tool that lets you pause your program at any line (called a breakpoint) and inspect the value of every variable at that moment. The best approach is to write clear, well-structured code that doesn't need debugging, but the debugger can be a useful last resort when something isn't behaving as expected.

Debugger steps and keyboard shortcuts vary depending on your IDE — consult your IDE's documentation for specifics. In IntelliJ IDEA for example: click the left margin to set a breakpoint, run in Debug mode, then use Step Over to advance one line at a time and Step Into to follow execution inside a method call like attack().

→ This page was created with help from Gemini and Claude AI.