"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
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 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.
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }
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.
Character
name
health
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.
main
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.
new
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; } }
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); } }
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.
private
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; } }
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
attack
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); } }
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.
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().
attack()