Methods & Scope
Method Overloading
Same Name, Different Parameters
You want print() to work with strings, integers, and doubles. Instead of
printString(), printInt(), printDouble(), overloading lets you use one
name with multiple parameter types.
Overload for different types
Create methods with the same name but different parameter types.
public class AddOverload {
public static void main(String[] args) {
System.out.println("=== Method Overloading: add() ===\n");
// Integer addition
int left = ;
int right = ;
int intResult = add(left, right);
System.out.println("add(" + left + ", " + right + ") = " + intResult);
// Double addition
double doubleResult = add(5.5, 3.2);
System.out.println("add(5.5, 3.2) = " + doubleResult);
// Three integers
int tripleResult = add(10, 20, 30);
System.out.println("add(10, 20, 30) = " + tripleResult);
// More types
long longResult = add(1000000000L, 2000000000L);
System.out.println("add(1000000000L, 2000000000L) = " + longResult);
// Compiler chooses the right method!
System.out.println("\n=== Compiler Decision ===");
System.out.println("add(1, 2) → int version");
System.out.println("add(1.0, 2.0) → double version");
System.out.println("add(1, 2, 3) → three-param version");
}
// Overload 1: Two integers
static int add(int a, int b) {
System.out.println(" [Called: add(int, int)]");
return a + b;
}
// Overload 2: Two doubles
static double add(double a, double b) {
System.out.println(" [Called: add(double, double)]");
return a + b;
}
// Overload 3: Three integers
static int add(int a, int b, int c) {
System.out.println(" [Called: add(int, int, int)]");
return a + b + c;
}
// Overload 4: Two longs
static long add(long a, long b) {
System.out.println(" [Called: add(long, long)]");
return a + b;
}
}
public class AddOverload {
public static void main(String[] args) {
System.out.println("=== Method Overloading: add() ===\n");
// Integer addition
int left = ;
int right = ;
int intResult = add(left, right);
System.out.println("add(" + left + ", " + right + ") = " + intResult);
// Double addition
double doubleResult = add(5.5, 3.2);
System.out.println("add(5.5, 3.2) = " + doubleResult);
// Three integers
int tripleResult = add(10, 20, 30);
System.out.println("add(10, 20, 30) = " + tripleResult);
// More types
long longResult = add(1000000000L, 2000000000L);
System.out.println("add(1000000000L, 2000000000L) = " + longResult);
// Compiler chooses the right method!
System.out.println("\n=== Compiler Decision ===");
System.out.println("add(1, 2) → int version");
System.out.println("add(1.0, 2.0) → double version");
System.out.println("add(1, 2, 3) → three-param version");
}
// Overload 1: Two integers
static int add(int a, int b) {
System.out.println(" [Called: add(int, int)]");
return a + b;
}
// Overload 2: Two doubles
static double add(double a, double b) {
System.out.println(" [Called: add(double, double)]");
return a + b;
}
// Overload 3: Three integers
static int add(int a, int b, int c) {
System.out.println(" [Called: add(int, int, int)]");
return a + b + c;
}
// Overload 4: Two longs
static long add(long a, long b) {
System.out.println(" [Called: add(long, long)]");
return a + b;
}
}
public class AddOverload {
public static void main(String[] args) {
System.out.println("=== Method Overloading: add() ===\n");
// Integer addition
int left = ;
int right = ;
int intResult = add(left, right);
System.out.println("add(" + left + ", " + right + ") = " + intResult);
// Double addition
double doubleResult = add(5.5, 3.2);
System.out.println("add(5.5, 3.2) = " + doubleResult);
// Three integers
int tripleResult = add(10, 20, 30);
System.out.println("add(10, 20, 30) = " + tripleResult);
// More types
long longResult = add(1000000000L, 2000000000L);
System.out.println("add(1000000000L, 2000000000L) = " + longResult);
// Compiler chooses the right method!
System.out.println("\n=== Compiler Decision ===");
System.out.println("add(1, 2) → int version");
System.out.println("add(1.0, 2.0) → double version");
System.out.println("add(1, 2, 3) → three-param version");
}
// Overload 1: Two integers
static int add(int a, int b) {
System.out.println(" [Called: add(int, int)]");
return a + b;
}
// Overload 2: Two doubles
static double add(double a, double b) {
System.out.println(" [Called: add(double, double)]");
return a + b;
}
// Overload 3: Three integers
static int add(int a, int b, int c) {
System.out.println(" [Called: add(int, int, int)]");
return a + b + c;
}
// Overload 4: Two longs
static long add(long a, long b) {
System.out.println(" [Called: add(long, long)]");
return a + b;
}
}
public class AddOverload {
public static void main(String[] args) {
System.out.println("=== Method Overloading: add() ===\n");
// Integer addition
int left = ;
int right = ;
int intResult = add(left, right);
System.out.println("add(" + left + ", " + right + ") = " + intResult);
// Double addition
double doubleResult = add(5.5, 3.2);
System.out.println("add(5.5, 3.2) = " + doubleResult);
// Three integers
int tripleResult = add(10, 20, 30);
System.out.println("add(10, 20, 30) = " + tripleResult);
// More types
long longResult = add(1000000000L, 2000000000L);
System.out.println("add(1000000000L, 2000000000L) = " + longResult);
// Compiler chooses the right method!
System.out.println("\n=== Compiler Decision ===");
System.out.println("add(1, 2) → int version");
System.out.println("add(1.0, 2.0) → double version");
System.out.println("add(1, 2, 3) → three-param version");
}
// Overload 1: Two integers
static int add(int a, int b) {
System.out.println(" [Called: add(int, int)]");
return a + b;
}
// Overload 2: Two doubles
static double add(double a, double b) {
System.out.println(" [Called: add(double, double)]");
return a + b;
}
// Overload 3: Three integers
static int add(int a, int b, int c) {
System.out.println(" [Called: add(int, int, int)]");
return a + b + c;
}
// Overload 4: Two longs
static long add(long a, long b) {
System.out.println(" [Called: add(long, long)]");
return a + b;
}
}
public class AddOverload {
public static void main(String[] args) {
System.out.println("=== Method Overloading: add() ===\n");
// Integer addition
int left = ;
int right = ;
int intResult = add(left, right);
System.out.println("add(" + left + ", " + right + ") = " + intResult);
// Double addition
double doubleResult = add(5.5, 3.2);
System.out.println("add(5.5, 3.2) = " + doubleResult);
// Three integers
int tripleResult = add(10, 20, 30);
System.out.println("add(10, 20, 30) = " + tripleResult);
// More types
long longResult = add(1000000000L, 2000000000L);
System.out.println("add(1000000000L, 2000000000L) = " + longResult);
// Compiler chooses the right method!
System.out.println("\n=== Compiler Decision ===");
System.out.println("add(1, 2) → int version");
System.out.println("add(1.0, 2.0) → double version");
System.out.println("add(1, 2, 3) → three-param version");
}
// Overload 1: Two integers
static int add(int a, int b) {
System.out.println(" [Called: add(int, int)]");
return a + b;
}
// Overload 2: Two doubles
static double add(double a, double b) {
System.out.println(" [Called: add(double, double)]");
return a + b;
}
// Overload 3: Three integers
static int add(int a, int b, int c) {
System.out.println(" [Called: add(int, int, int)]");
return a + b + c;
}
// Overload 4: Two longs
static long add(long a, long b) {
System.out.println(" [Called: add(long, long)]");
return a + b;
}
}
public class AddOverload {
public static void main(String[] args) {
System.out.println("=== Method Overloading: add() ===\n");
// Integer addition
int left = ;
int right = ;
int intResult = add(left, right);
System.out.println("add(" + left + ", " + right + ") = " + intResult);
// Double addition
double doubleResult = add(5.5, 3.2);
System.out.println("add(5.5, 3.2) = " + doubleResult);
// Three integers
int tripleResult = add(10, 20, 30);
System.out.println("add(10, 20, 30) = " + tripleResult);
// More types
long longResult = add(1000000000L, 2000000000L);
System.out.println("add(1000000000L, 2000000000L) = " + longResult);
// Compiler chooses the right method!
System.out.println("\n=== Compiler Decision ===");
System.out.println("add(1, 2) → int version");
System.out.println("add(1.0, 2.0) → double version");
System.out.println("add(1, 2, 3) → three-param version");
}
// Overload 1: Two integers
static int add(int a, int b) {
System.out.println(" [Called: add(int, int)]");
return a + b;
}
// Overload 2: Two doubles
static double add(double a, double b) {
System.out.println(" [Called: add(double, double)]");
return a + b;
}
// Overload 3: Three integers
static int add(int a, int b, int c) {
System.out.println(" [Called: add(int, int, int)]");
return a + b + c;
}
// Overload 4: Two longs
static long add(long a, long b) {
System.out.println(" [Called: add(long, long)]");
return a + b;
}
}
public class AddOverload {
public static void main(String[] args) {
System.out.println("=== Method Overloading: add() ===\n");
// Integer addition
int left = ;
int right = ;
int intResult = add(left, right);
System.out.println("add(" + left + ", " + right + ") = " + intResult);
// Double addition
double doubleResult = add(5.5, 3.2);
System.out.println("add(5.5, 3.2) = " + doubleResult);
// Three integers
int tripleResult = add(10, 20, 30);
System.out.println("add(10, 20, 30) = " + tripleResult);
// More types
long longResult = add(1000000000L, 2000000000L);
System.out.println("add(1000000000L, 2000000000L) = " + longResult);
// Compiler chooses the right method!
System.out.println("\n=== Compiler Decision ===");
System.out.println("add(1, 2) → int version");
System.out.println("add(1.0, 2.0) → double version");
System.out.println("add(1, 2, 3) → three-param version");
}
// Overload 1: Two integers
static int add(int a, int b) {
System.out.println(" [Called: add(int, int)]");
return a + b;
}
// Overload 2: Two doubles
static double add(double a, double b) {
System.out.println(" [Called: add(double, double)]");
return a + b;
}
// Overload 3: Three integers
static int add(int a, int b, int c) {
System.out.println(" [Called: add(int, int, int)]");
return a + b + c;
}
// Overload 4: Two longs
static long add(long a, long b) {
System.out.println(" [Called: add(long, long)]");
return a + b;
}
}
public class AddOverload {
public static void main(String[] args) {
System.out.println("=== Method Overloading: add() ===\n");
// Integer addition
int left = ;
int right = ;
int intResult = add(left, right);
System.out.println("add(" + left + ", " + right + ") = " + intResult);
// Double addition
double doubleResult = add(5.5, 3.2);
System.out.println("add(5.5, 3.2) = " + doubleResult);
// Three integers
int tripleResult = add(10, 20, 30);
System.out.println("add(10, 20, 30) = " + tripleResult);
// More types
long longResult = add(1000000000L, 2000000000L);
System.out.println("add(1000000000L, 2000000000L) = " + longResult);
// Compiler chooses the right method!
System.out.println("\n=== Compiler Decision ===");
System.out.println("add(1, 2) → int version");
System.out.println("add(1.0, 2.0) → double version");
System.out.println("add(1, 2, 3) → three-param version");
}
// Overload 1: Two integers
static int add(int a, int b) {
System.out.println(" [Called: add(int, int)]");
return a + b;
}
// Overload 2: Two doubles
static double add(double a, double b) {
System.out.println(" [Called: add(double, double)]");
return a + b;
}
// Overload 3: Three integers
static int add(int a, int b, int c) {
System.out.println(" [Called: add(int, int, int)]");
return a + b + c;
}
// Overload 4: Two longs
static long add(long a, long b) {
System.out.println(" [Called: add(long, long)]");
return a + b;
}
}
public class AddOverload {
public static void main(String[] args) {
System.out.println("=== Method Overloading: add() ===\n");
// Integer addition
int left = ;
int right = ;
int intResult = add(left, right);
System.out.println("add(" + left + ", " + right + ") = " + intResult);
// Double addition
double doubleResult = add(5.5, 3.2);
System.out.println("add(5.5, 3.2) = " + doubleResult);
// Three integers
int tripleResult = add(10, 20, 30);
System.out.println("add(10, 20, 30) = " + tripleResult);
// More types
long longResult = add(1000000000L, 2000000000L);
System.out.println("add(1000000000L, 2000000000L) = " + longResult);
// Compiler chooses the right method!
System.out.println("\n=== Compiler Decision ===");
System.out.println("add(1, 2) → int version");
System.out.println("add(1.0, 2.0) → double version");
System.out.println("add(1, 2, 3) → three-param version");
}
// Overload 1: Two integers
static int add(int a, int b) {
System.out.println(" [Called: add(int, int)]");
return a + b;
}
// Overload 2: Two doubles
static double add(double a, double b) {
System.out.println(" [Called: add(double, double)]");
return a + b;
}
// Overload 3: Three integers
static int add(int a, int b, int c) {
System.out.println(" [Called: add(int, int, int)]");
return a + b + c;
}
// Overload 4: Two longs
static long add(long a, long b) {
System.out.println(" [Called: add(long, long)]");
return a + b;
}
}
Same name, different types: add(int, int) vs add(double, double).
Overload for multiple data types
Handle different input types with the same method name.
public class PrintOverload {
public static void main(String[] args) {
System.out.println("=== Overloaded print() ===\n");
// Different types, same method name
print(42); // int
print(3.14159); // double
print("Hello World"); // String
print(true); // boolean
// Arrays
print(new int[]{1, 2, 3, 4, 5}); // int array
print(new String[]{"a", "b", "c"}); // String array
System.out.println("\n=== How Java's System.out Works ===");
System.out.println("System.out has 10+ overloaded println() methods!");
System.out.println("println(int), println(double), println(String), etc.");
}
// Overload for int
static void print(int value) {
System.out.println("Integer: " + value);
}
// Overload for double
static void print(double value) {
System.out.println("Double: " + value);
}
// Overload for String
static void print(String value) {
System.out.println("String: \"" + value + "\"");
}
// Overload for boolean
static void print(boolean value) {
System.out.println("Boolean: " + value);
}
// Overload for int array
static void print(int[] arr) {
System.out.print("Int Array: [");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if (i < arr.length - 1) System.out.print(", ");
}
System.out.println("]");
}
// Overload for String array
static void print(String[] arr) {
System.out.print("String Array: [");
for (int i = 0; i < arr.length; i++) {
System.out.print("\"" + arr[i] + "\"");
if (i < arr.length - 1) System.out.print(", ");
}
System.out.println("]");
}
}
The compiler picks the right version based on argument types.
Overload for different argument counts
Provide flexible APIs with varying parameter counts.
public class MaxOverload {
public static void main(String[] args) {
System.out.println("=== Overloaded max() ===\n");
// Two arguments
System.out.println("max(10, 20) = " + max(10, 20));
System.out.println("max(3.5, 2.8) = " + max(3.5, 2.8));
// Three arguments
System.out.println("max(5, 12, 8) = " + max(5, 12, 8));
System.out.println("max(1.1, 2.2, 3.3) = " + max(1.1, 2.2, 3.3));
// Four arguments
System.out.println("max(4, 7, 2, 9) = " + max(4, 7, 2, 9));
// Compare with Java's Math.max
System.out.println("\n=== Java's Math.max ===");
System.out.println("Math.max(10, 20) = " + Math.max(10, 20));
System.out.println("Math.max only takes 2 args - chain for more:");
System.out.println("Math.max(Math.max(5, 12), 8) = " +
Math.max(Math.max(5, 12), 8));
// Min versions
System.out.println("\n=== Overloaded min() ===");
System.out.println("min(10, 20) = " + min(10, 20));
System.out.println("min(5, 12, 8) = " + min(5, 12, 8));
}
// Two ints
static int max(int a, int b) {
return (a > b) ? a : b;
}
// Two doubles
static double max(double a, double b) {
return (a > b) ? a : b;
}
// Three ints
static int max(int a, int b, int c) {
return max(max(a, b), c); // Reuse two-arg version!
}
// Three doubles
static double max(double a, double b, double c) {
return max(max(a, b), c);
}
// Four ints
static int max(int a, int b, int c, int d) {
return max(max(a, b), max(c, d));
}
// Min versions
static int min(int a, int b) {
return (a < b) ? a : b;
}
static int min(int a, int b, int c) {
return min(min(a, b), c);
}
}
max(a, b) and max(a, b, c) - same concept, different arity.
Constructor overloading
Create objects in multiple ways using overloaded constructors.
public class ConstructorOverload {
public static void main(String[] args) {
System.out.println("=== Constructor Overloading ===\n");
// Different ways to create a Book
Book book1 = new Book();
System.out.println("Default: " + book1);
Book book2 = new Book("1984");
System.out.println("Title only: " + book2);
Book book3 = new Book("1984", "George Orwell");
System.out.println("Title + Author: " + book3);
Book book4 = new Book("1984", "George Orwell", 328);
System.out.println("All params: " + book4);
// Copy constructor
Book book5 = new Book(book4);
System.out.println("Copy: " + book5);
System.out.println("\n=== Flexibility of Overloading ===");
System.out.println("Same class, 5 ways to create objects!");
}
}
class Book {
String title;
String author;
int pages;
// Constructor 1: No arguments (defaults)
Book() {
this("Unknown Title", "Unknown Author", 0); // Calls another constructor
}
// Constructor 2: Title only
Book(String title) {
this(title, "Unknown Author", 0);
}
// Constructor 3: Title and author
Book(String title, String author) {
this(title, author, 0);
}
// Constructor 4: All parameters (primary)
Book(String title, String author, int pages) {
this.title = title;
this.author = author;
this.pages = pages;
}
// Constructor 5: Copy constructor
Book(Book other) {
this(other.title, other.author, other.pages);
}
@Override
public String toString() {
return "\"" + title + "\" by " + author +
(pages > 0 ? " (" + pages + " pages)" : "");
}
}
Constructors can be overloaded just like regular methods.
Avoid ambiguity
Understand when overloading becomes confusing.
public class Ambiguity {
public static void main(String[] args) {
System.out.println("=== Overloading Ambiguity ===\n");
// Clear cases - no ambiguity
System.out.println("=== Clear Cases ===");
process(10); // Clearly int
process("Hello"); // Clearly String
process(10, 20); // Clearly two ints
// Ambiguous case with null
System.out.println("\n=== Null Ambiguity ===");
// process(null); // Error! Both String and int[] match null
// Solution: explicit cast
process((String) null); // Explicit: String version
process((int[]) null); // Explicit: int[] version
// Type promotion ambiguity
System.out.println("\n=== Type Promotion ===");
demo(10); // int → could go to long or double?
demo(10L); // Explicitly long
demo(10.0); // Explicitly double
System.out.println("\n=== Rules ===");
System.out.println("1. Exact match is preferred");
System.out.println("2. Widening (int→long→double) preferred over boxing");
System.out.println("3. null can match any reference type - be explicit!");
}
// Overload 1: int
static void process(int x) {
System.out.println("process(int): " + x);
}
// Overload 2: String
static void process(String s) {
System.out.println("process(String): " + s);
}
// Overload 3: two ints
static void process(int x, int y) {
System.out.println("process(int, int): " + x + ", " + y);
}
// Overload 4: int array
static void process(int[] arr) {
System.out.println("process(int[]): array");
}
// Demo type promotion
static void demo(int x) {
System.out.println("demo(int): " + x);
}
static void demo(long x) {
System.out.println("demo(long): " + x);
}
static void demo(double x) {
System.out.println("demo(double): " + x);
}
}
Some combinations create ambiguous calls. Know the rules to avoid compiler errors.
Exercise: TypePromotion.java
Explore how Java's type promotion affects overload resolution