Classes & Objects
Defining a Class
A class is declared with the class keyword, followed by a name and a body enclosed in curly braces. Inside that body you declare fields (the data the class holds) and methods (the behavior it exposes).
class ClassName { /* fields and methods */ }A minimal class
public class Car {
// Fields — the data every Car object holds
String model;
int year;
double speed;
// Methods — the behavior every Car object exposes
void accelerate(double amount) {
speed += amount;
}
void printStatus() {
System.out.println(model + " (" + year + ") is going " + speed + " km/h");
}
}Creating Objects with new
A class by itself is just a description — no memory is allocated for its fields until you create an object from it. You do that with the new keyword, which allocates memory for a new instance and returns a reference to it.
Instantiating Car
public class Main {
public static void main(String[] args) {
Car myCar = new Car(); // creates a new Car object
myCar.model = "Model 3";
myCar.year = 2024;
myCar.speed = 0;
myCar.accelerate(60);
myCar.printStatus();
}
}Model 3 (2024) is going 60.0 km/h
A Complete Worked Example: BankAccount
Let's build something a bit more realistic — a BankAccount class that keeps its balance private and only exposes controlled methods to change it.
BankAccount.java
public class BankAccount {
private String owner;
private double balance;
void open(String owner, double initialDeposit) {
this.owner = owner;
this.balance = initialDeposit;
}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
} else {
System.out.println("Withdrawal denied: insufficient funds");
}
}
void printBalance() {
System.out.println(owner + "'s balance: " + balance);
}
public static void main(String[] args) {
BankAccount account1 = new BankAccount();
account1.open("Amara", 1000.0);
account1.deposit(250.0);
account1.withdraw(3000.0); // denied
account1.printBalance();
BankAccount account2 = new BankAccount(); // an independent object
account2.open("Diego", 500.0);
account2.printBalance();
}
}Withdrawal denied: insufficient funds Amara's balance: 1250.0 Diego's balance: 500.0
Class vs. Object, Made Concrete
BankAccount is one class — it exists exactly once in your compiled program. account1 and account2 are two separate objects created from that class; each has its own owner and balance stored independently. Changing account1's balance has no effect whatsoever on account2, because they occupy different memory and are two distinct instances of the same blueprint.
Concept | Class | Object |
What it is | A blueprint / template | A concrete instance built from the blueprint |
How many exist | One, in the compiled code | As many as you create with new |
Has actual data? | No — only describes what data looks like | Yes — holds real field values |
Example | BankAccount | account1, account2 |
One Public Class Per File
Field names should be nouns describing the data (owner, balance)
Method names should be verbs describing the behavior (deposit, withdraw, printBalance)
Keep fields private and expose behavior through methods — this is the encapsulation pillar of OOP, covered on its own page
Give a class a single, clear responsibility rather than letting it grow into a catch-all