Skip to Content
Course content

25: Classes and Objects

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I want to start today with a snippet of code that I've seen almost every single junior developer write in their first week of Java. It looks perfectly logical at first glance, but it will make the compiler scream at you.

public class GameCharacter {
    String name = "Hero";
    int health = 100;

    public static void main(String[] args) {
        System.out.println("Character " + name + " has " + health + " HP.");
    }
}

The "Non-Static" Wall

If you try to run this, you'll get a compiler error: non-static variable name cannot be referenced from a static context. It's one of the most frustrating errors when you're starting out because you're thinking, "The variable is right there! Why can't the program see it?"

Here is the deal: the main method is static. In Java, static means "this belongs to the class itself," not to any specific instance of the class. However, name and health are instance variables. They belong to a specific character.

Imagine if you had a blueprint for a house. The blueprint says "every house has a front door color." But you can't walk up to the blueprint and try to open the door. You can't interact with the door until you actually build a house from that blueprint. Right now, you're trying to open the door on the blueprint.

Creating an Instance to Fix the Crash

To fix this, we need to instantiate the class. We use the new keyword to tell Java, "Take this blueprint and actually allocate some memory for a real object."

public class GameCharacter {
    String name = "Hero";
    int health = 100;

    public static void main(String[] args) {
        // We create an 'instance' of GameCharacter called player1
        GameCharacter player1 = new GameCharacter();
        
        // Now we ask player1 specifically for their name and health
        System.out.println("Character " + player1.name + " has " + player1.health + " HP.");
    }
}

Now it works. We aren't talking to the GameCharacter class anymore; we're talking to player1, a concrete object that exists in your computer's memory.

Blueprints versus Objects

This is the core of Object-Oriented Programming (OOP). The class is your blueprint. It defines what data (fields) a thing has and what it can do (methods). The object is the actual thing you create using that blueprint.

The real power here is that you can create as many objects as you want from a single class, and they each maintain their own separate state. I don't want every character in my game to have the same name and health—that would be a very boring game.

GameCharacter player1 = new GameCharacter();
player1.name = "Arthur";
player1.health = 100;

GameCharacter player2 = new GameCharacter();
player2.name = "Morgana";
player2.health = 150;

System.out.println(player1.name); // Prints Arthur
System.out.println(player2.name); // Prints Morgana

Packaging Logic into Methods

Adding variables is great, but classes are meant to encapsulate behavior too. Instead of manually changing health values in the main method, we should give the GameCharacter the ability to take damage itself. This keeps the logic tied to the data.

public class GameCharacter {
    String name;
    int health = 100;

    public void takeDamage(int amount) {
        this.health -= amount;
        System.out.println(name + " took " + amount + " damage! Health is now " + health);
    }

    public static void main(String[] args) {
        GameCharacter hero = new GameCharacter();
        hero.name = "Arthur";
        
        hero.takeDamage(20); // Much cleaner than doing hero.health = hero.health - 20;
    }
}

Notice the this keyword. I use this.health to be explicit: "I am talking about the health variable that belongs to this specific instance of the character." It's not strictly required here, but as you start writing more complex code, it'll save you from a lot of confusion.




📋 Practical Task

Building a Persistent BankAccount Tracker

Your task is to create a system that manages multiple bank accounts. You need to ensure that each account tracks its own balance independently.

  • Create a class named BankAccount.
  • Give it two fields: a String accountHolder and a double balance.
  • Implement a method called deposit(double amount) that adds money to the balance and prints the new total.
  • Implement a method called withdraw(double amount). This method should check if the account has enough money. If it does, subtract the amount; if not, print "Insufficient funds!".
  • In your main method, instantiate two different accounts (e.g., one for "Alice" and one for "Bob").
  • Perform a few deposits and withdrawals on both accounts to prove that Alice's spending doesn't affect Bob's balance.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.