Java · Lesson 4 of 6
Classes and Objects
Fields, constructors, methods, and encapsulation with private.
- Intermediate
- 18 min read
- 3 objectives
Before this lessonLesson 3: Control Flow
What you will learn
- Define a class with fields
- Write a constructor
- Add getters/setters
Java is object-oriented from the ground up. A class describes the shape of something (its fields) and what it can do (its methods). An object is a concrete instance created with new. Good classes hide their internal data and expose a small, safe set of operations. That idea is called encapsulation.
Objects model real things
Java is built around object-oriented programming. Rather than a long list of separate variables and functions, you describe a kind of thing once as a class (its data and its abilities) and then create as many objects from it as you need. A BankAccount class describes what every account has (an owner, a balance) and can do (deposit, withdraw). Each customer's account is a separate object with its own numbers.
A class with a constructor
A constructor has the same name as the class and no return type. It runs when you call new and sets the object up. Marking fields private stops outside code from changing them directly.
public class BankAccount {
private final String owner;
private double balance;
public BankAccount(String owner, double balance) {
this.owner = owner;
this.balance = balance;
}
public void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("amount must be positive");
balance += amount;
}
public double getBalance() { return balance; }
public String getOwner() { return owner; }
}this refers to the current object, and is needed here to tell the field this.owner apart from the parameter owner.
Using the class
BankAccount acct = new BankAccount("Amar", 100);
acct.deposit(50);
System.out.println(acct.getOwner() + ": " + acct.getBalance());Amar: 150.0
Static versus instance
Instance members belong to each object; static members belong to the class and are shared. Math.sqrt(9) is a static method: you call it on the class, not on an object.
Inheritance and interfaces
A subclass extends one parent class. An interface is a contract of methods that a class promises to provide, and a class may implements many of them. Prefer interfaces when you want different classes to be used interchangeably.
interface Shape {
double area();
}
class Circle implements Shape {
private final double r;
Circle(double r) { this.r = r; }
public double area() { return Math.PI * r * r; }
}
class Square implements Shape {
private final double s;
Square(double s) { this.s = s; }
public double area() { return s * s; }
}
Shape[] shapes = { new Circle(1), new Square(2) };
for (Shape sh : shapes) {
System.out.printf("%.2f%n", sh.area());
}3.14 4.00
Calling sh.area() runs the right version for each object. That is polymorphism: one call, many behaviors.
A class, an object, and encapsulation
class BankAccount {
private final String owner;
private double balance;
BankAccount(String owner, double balance) {
this.owner = owner;
this.balance = balance;
}
void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("amount must be positive");
balance += amount;
}
double getBalance() { return balance; }
String getOwner() { return owner; }
}
public class Main {
public static void main(String[] args) {
BankAccount a = new BankAccount("Ada", 100);
BankAccount b = new BankAccount("Linus", 50);
a.deposit(25);
System.out.println(a.getOwner() + ": " + a.getBalance());
System.out.println(b.getOwner() + ": " + b.getBalance());
}
}Ada: 125.0 Linus: 50.0
privatefields can only be touched from inside the class. This is encapsulation: outsiders must go through methods, so the class can enforce its rules (no negative deposits).- The constructor has the class name and no return type; it runs when you write
new BankAccount(...). thisrefers to the object being built or used, and disambiguates fields from parameters.- Each
newcreates an independent object: depositing intoanever changesb.
Inheritance and polymorphism
class Animal {
String speak() { return "..."; }
}
class Dog extends Animal {
@Override
String speak() { return "Woof"; }
}
class Cat extends Animal {
@Override
String speak() { return "Meow"; }
}
public class Main {
public static void main(String[] args) {
Animal[] pets = { new Dog(), new Cat(), new Animal() };
for (Animal p : pets) {
System.out.println(p.speak());
}
}
}Woof Meow ...
The loop only knows about Animal, yet each object answers in its own way. That is polymorphism: the same call, different behaviour depending on the real object. It lets you add a new kind of animal without changing the loop.
Interfaces: promises about behaviour
interface Shape {
double area();
}
record Circle(double r) implements Shape {
public double area() { return Math.PI * r * r; }
}
record Rect(double w, double h) implements Shape {
public double area() { return w * h; }
}
public class Main {
public static void main(String[] args) {
Shape[] shapes = { new Circle(1), new Rect(3, 4) };
for (Shape s : shapes) {
System.out.printf("%.2f%n", s.area());
}
}
}3.14 12.00
Key takeaways
- A class is a blueprint;
newmakes independent objects from it. - Keep fields
privateand expose behaviour through methods (encapsulation). - Subclasses
extendand@Override; interfaces declare what a class can do. - Polymorphism lets code work with the general type while objects behave as their real type.
// Write your solution here
