Java Intermediate: Objects, Collections and Errors
Classes and Objects
In this lesson you will
- Write a class with fields, a constructor and methods
- Protect data with private fields and public methods
- Explain static members and the toString method
Introduction
Java is an object-oriented language. Instead of loose variables and functions, you describe things from your problem (a student, a bank account, a product) as classes, and then create objects from them. Each object keeps its own data and knows what it can do.
The simple explanation
A class is a blueprint. An object is one thing built from it.
Java
class Dog {
String name;
int age;
Dog(String name, int age) {
this.name = name;
this.age = age;
}
void bark() {
System.out.println(name + " says woof");
}
void haveBirthday() {
age++;
}
}
public class Main {
public static void main(String[] args) {
Dog rex = new Dog("Rex", 3);
Dog bella = new Dog("Bella", 5);
rex.bark();
bella.bark();
rex.haveBirthday();
System.out.println(rex.name + " is " + rex.age);
System.out.println(bella.name + " is " + bella.age);
}
}Rex says woof
Bella says woof
Rex is 4
Bella is 5- Fields (
name,age) are the data each object holds. - The constructor has the same name as the class and no return type. It runs when you write
new Dog(...). thisrefers to the current object.this.name = namemeans "store the parameternamein this object's fieldname".- Methods (
bark,haveBirthday) are what the object can do. rexandbellaare separate objects with their own data.
Quick quiz
What does the keyword new do in new Dog('Rex', 3)?
Encapsulation: protect your data
If every field is open, any code can set an age to -50. Good classes hide their fields with private, and let outside code work through methods that can check the rules. This is called encapsulation.
Java
class BankAccount {
private final String owner;
private double balance;
BankAccount(String owner, double openingBalance) {
this.owner = owner;
this.balance = openingBalance;
}
String getOwner() {
return owner;
}
double getBalance() {
return balance;
}
void deposit(double amount) {
if (amount <= 0) {
System.out.println("Deposit must be positive");
return;
}
balance += amount;
}
boolean withdraw(double amount) {
if (amount > balance) {
return false;
}
balance -= amount;
return true;
}
}
public class Main {
public static void main(String[] args) {
BankAccount account = new BankAccount("Asha", 100.0);
account.deposit(50);
account.deposit(-20);
System.out.println(account.withdraw(500));
System.out.println(account.withdraw(30));
System.out.println(account.getOwner() + ": " + account.getBalance());
}
}Deposit must be positive
false
true
Asha: 120.0Trying account.balance = 1000000; from Main would be a compile error, because balance is private. The only way to change it is deposit and withdraw, which enforce the rules. Methods that read a field are called getters (getBalance), and ones that set a field are setters.
Access modifiers
private: only code inside the same class.- (nothing, "package-private"): classes in the same package.
protected: the package and subclasses.public: everywhere.
As a rule, make fields private and expose only what others need.
toString
If you print an object, you get something unhelpful like Dog@1b6d3586. Override toString() to describe it properly. Every class has this method, and println calls it automatically.
Java
class Point {
private final int x;
private final int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "(" + x + ", " + y + ")";
}
}
public class Main {
public static void main(String[] args) {
Point p = new Point(3, 4);
System.out.println(p);
System.out.println("Point is " + p);
}
}(3, 4)
Point is (3, 4)@Override is an annotation that asks the compiler to check you really are replacing a method from a parent class. It catches typos in method names.
static members
A static field or method belongs to the class, not to any one object. There is only one copy, shared by all.
Java
class Student {
private static int count = 0;
private final String name;
Student(String name) {
this.name = name;
count++;
}
static int getCount() {
return count;
}
String getName() {
return name;
}
}
public class Main {
public static void main(String[] args) {
new Student("Asha");
new Student("Ben");
Student c = new Student("Chloe");
System.out.println(c.getName());
System.out.println(Student.getCount());
}
}Chloe
3main is static for the same reason: Java has to run it before any object exists.
References and null
An object variable holds a reference (like an address) to the object. Two variables can refer to the same object, and a variable can refer to nothing at all (null).
Java
class Counter {
int value = 0;
}
public class Main {
public static void main(String[] args) {
Counter a = new Counter();
Counter b = a; // same object, not a copy
b.value = 10;
System.out.println(a.value);
Counter c = null;
System.out.println(c == null);
}
}10
trueCalling a method on a null reference throws a NullPointerException. Checking for null before using a reference is a necessary habit.
Quick quiz
Why make a field private and provide getter and setter methods?
Try it yourself
On your computer, write a class Rectangle with private width and height, a constructor, methods area() and perimeter(), and a toString() that prints like Rectangle 3x4. Create two rectangles in main and print their areas.
Summary
- A class describes fields and methods. An object is created with
new, which runs the constructor. thisis the current object. Make fieldsprivateand expose behaviour with methods (encapsulation).- Override
toString()so that objects print meaningfully. staticmembers belong to the class. Object variables hold references, andnullmeans no object.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.
Sources and further reading