Crash Courses · Masters
Methods & OOP Fundamentals
Write well-structured methods, understand scope and the call stack, and create your first classes with fields, constructors, and encapsulation.
16 min read+170 XP on completionCert: Java / Kotlin Crash Course
Tap any word in the text below to start reading from there.
Methods & OOP Fundamentals
Method Anatomy
// accessModifier returnType methodName(paramType param1, ...) {
// method body
// return value; // required unless return type is void
// }
public static int add(int a, int b) {
return a + b;
}
// void methods return nothing
public static void printLine(String msg) {
System.out.println(">>> " + msg);
}
// Multiple return points — valid but use sparingly
public static String classify(int n) {
if (n < 0) return "negative";
if (n == 0) return "zero";
return "positive";
}---
Method Overloading
Same method name, different parameter signatures. Java resolves at compile time:
public static double area(double radius) {
return Math.PI * radius * radius; // circle area
}
public static double area(double width, double height) {
return width * height; // rectangle area
}
public static double area(double a, double b, double c) {
// Heron's formula for triangle given 3 sides
double s = (a + b + c) / 2;
return Math.sqrt(s * (s-a) * (s-b) * (s-c));
}
// main:
System.out.println(area(5.0)); // circle: 78.54
System.out.println(area(4.0, 6.0)); // rectangle: 24.0
System.out.println(area(3.0, 4.0, 5.0)); // triangle: 6.0---
Your First Class: BankAccount
A class defines a blueprint. new creates an instance of that blueprint with its own copy of the fields:
public class BankAccount {
// Fields — private: only this class can access them directly
private String owner;
private double balance;
private int transactionCount;
// Constructor — called with: BankAccount acct = new BankAccount("Jordan", 1000.0)
public BankAccount(String owner, double initialBalance) {
this.owner = owner; // 'this.owner' = field; 'owner' alone = parameter
this.balance = initialBalance;
this.transactionCount = 0;
}
// No-arg constructor for an empty account
public BankAccount(String owner) {
this(owner, 0.0); // calls the 2-arg constructor above
}
// Mutator methods (setters with business logic)
public void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("Deposit must be positive");
balance += amount;
transactionCount++;
}
public boolean withdraw(double amount) {
if (amount <= 0) throw new IllegalArgumentException("Withdrawal must be positive");
if (amount > balance) return false; // insufficient funds
balance -= amount;
transactionCount++;
return true;
}
// Accessor methods (getters)
public double getBalance() { return balance; }
public String getOwner() { return owner; }
public int getTransactionCount() { return transactionCount; }
// toString: how this object looks when printed
@Override
public String toString() {
return String.format("BankAccount[%s: $%.2f, %d txns]",
owner, balance, transactionCount);
}
}Using BankAccount:
BankAccount acct = new BankAccount("Jordan", 500.0);
acct.deposit(250.0);
boolean success = acct.withdraw(100.0);
System.out.println(success); // true
System.out.println(acct); // BankAccount[Jordan: $650.00, 2 txns]
System.out.println(acct.getBalance()); // 650.0
boolean failed = acct.withdraw(10000.0);
System.out.println(failed); // false — insufficient funds---
Pass By Value (The Common Gotcha)
Java passes everything by value. For primitives, a copy of the value is passed. For objects, a copy of the reference is passed:
// Primitives: original unchanged
public static void doubleIt(int x) {
x = x * 2; // only changes the local copy
}
int n = 5;
doubleIt(n);
System.out.println(n); // still 5 — original unchanged
// Objects: can mutate through the reference
public static void deposit100(BankAccount acct) {
acct.deposit(100); // mutates the object at the original address
}
BankAccount a = new BankAccount("Test", 500.0);
deposit100(a);
System.out.println(a.getBalance()); // 600.0 — the object was mutated
// But reassigning the reference inside the method has no effect outside
public static void reassign(BankAccount acct) {
acct = new BankAccount("New", 0.0); // only changes local reference copy
}
reassign(a);
System.out.println(a.getOwner()); // still "Test"---
The @Override Annotation
@Override tells the compiler you intend to override a parent class method. If you misspell it, the compiler catches the error:
@Override
public String toString() {
return "My custom string representation";
}Every class in Java implicitly extends Object. Object has toString(), equals(), and hashCode() — you should override all three in well-designed value classes.
Reading progress
0% read
In this module
Encapsulation
Constructor
this keyword
Method Overloading
0%