Advanced Methods

This lesson dives deeper into advanced method features, including recursion, static methods, and method references.

Recursion

Recursion is a programming technique where a method calls itself.

Three Elements of Recursion

Element Description
Base case The condition that stops recursion
Recursive call The method calls itself
Problem reduction Each recursive call reduces the problem size

Example: Calculate Factorial

JAVA
public class Factorial {
    public static long factorial(int n) {
        // Base case
        if (n <= 1) {
            return 1;
        }
        // Recursive call
        return n * factorial(n - 1);
    }
    
    public static void main(String[] args) {
        System.out.println("5! = " + factorial(5));  // 120
        System.out.println("10! = " + factorial(10)); // 3628800
    }
}
▶ Try it Yourself

Recursion Process

TEXT
factorial(5)
  = 5 * factorial(4)
  = 5 * 4 * factorial(3)
  = 5 * 4 * 3 * factorial(2)
  = 5 * 4 * 3 * 2 * factorial(1)
  = 5 * 4 * 3 * 2 * 1
  = 120

Example: Fibonacci Sequence

JAVA
public class Fibonacci {
    public static int fibonacci(int n) {
        if (n <= 1) {
            return n;
        }
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
    
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.print(fibonacci(i) + " ");
        }
        // Output: 0 1 1 2 3 5 8 13 21 34
    }
}
▶ Try it Yourself
⚠️ Note: Simple recursion is inefficient. Use memoization to optimize. For Fibonacci, iteration is more efficient.

Example: Recursive Directory Traversal

JAVA
import java.io.File;

public class ListFiles {
    public static void listFiles(File dir, String indent) {
        File[] files = dir.listFiles();
        if (files == null) return;
        
        for (File file : files) {
            System.out.println(indent + file.getName());
            if (file.isDirectory()) {
                listFiles(file, indent + "  ");
            }
        }
    }
    
    public static void main(String[] args) {
        File dir = new File(".");
        listFiles(dir, "");
    }
}
▶ Try it Yourself

Static vs Instance Methods

Static Methods

Methods modified with static belong to the class and can be called without creating an object.

JAVA
public class MathUtils {
    public static int add(int a, int b) {
        return a + b;
    }
}

// Call
int sum = MathUtils.add(3, 5);

Instance Methods

Methods without static belong to objects and require creating an object to call.

JAVA
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

// Call
Calculator calc = new Calculator();
int sum = calc.add(3, 5);

Comparison

Feature Static Method Instance Method
Keyword static None
Calling style ClassName.method() object.method()
Member access Can only access static members Can access all members
this keyword Cannot use Can use

Example: Static vs Instance Methods

JAVA
public class MethodTypeDemo {
    private int count = 0;
    
    // Static method
    public static int add(int a, int b) {
        return a + b;
    }
    
    // Instance method
    public void increment() {
        count++;
    }
    
    public int getCount() {
        return count;
    }
    
    public static void main(String[] args) {
        // Static method called directly
        System.out.println(add(3, 5));  // 8
        
        // Instance method requires object
        MethodTypeDemo demo = new MethodTypeDemo();
        demo.increment();
        demo.increment();
        System.out.println(demo.getCount());  // 2
    }
}
▶ Try it Yourself

Utility Class Design

Utility classes typically only contain static methods and don't require creating objects.

Example: String Utility Class

JAVA
public class StringUtils {
    // Check if empty
    public static boolean isEmpty(String str) {
        return str == null || str.isEmpty();
    }
    
    // Check if blank
    public static boolean isBlank(String str) {
        return str == null || str.trim().isEmpty();
    }
    
    // Reverse string
    public static String reverse(String str) {
        if (str == null) return null;
        return new StringBuilder(str).reverse().toString();
    }
    
    // Capitalize first letter
    public static String capitalize(String str) {
        if (isEmpty(str)) return str;
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }
    
    public static void main(String[] args) {
        System.out.println(isEmpty(""));      // true
        System.out.println(isEmpty("hello")); // false
        System.out.println(reverse("hello")); // olleh
        System.out.println(capitalize("hello")); // Hello
    }
}
▶ Try it Yourself

Method References

Java 8 introduced method references as a shorthand for Lambda expressions.

Four Types of Method References

Type Syntax Example
Static method ClassName::staticMethod Math::abs
Instance method object::instanceMethod System.out::println
Instance method of a class ClassName::instanceMethod String::length
Constructor ClassName::new ArrayList::new

Example: Method References

JAVA
import java.util.Arrays;
import java.util.List;

public class MethodRefDemo {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        
        // Lambda expression
        names.forEach(name -> System.out.println(name));
        
        // Method reference (more concise)
        names.forEach(System.out::println);
        
        // Static method reference
        List<Integer> numbers = Arrays.asList(-3, -1, 0, 2, 5);
        numbers.stream()
               .map(Math::abs)
               .forEach(System.out::println);
        // Output: 3 1 0 2 5
    }
}
▶ Try it Yourself

Example: Constructor Reference

JAVA
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

public class ConstructorRefDemo {
    public static void main(String[] args) {
        // Lambda expression
        Supplier<List<String>> listFactory = () -> new ArrayList<>();
        
        // Constructor reference
        Supplier<List<String>> listFactory2 = ArrayList::new;
        
        List<String> list = listFactory2.get();
        list.add("Hello");
        System.out.println(list);  // [Hello]
    }
}
▶ Try it Yourself

Recursion Optimization

Tail Recursion

Tail recursion is when the recursive call is the last operation in the function.

JAVA
// Regular recursion (not tail recursion)
public static long factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);  // Multiply n after recursion
}

// Tail recursion version
public static long factorialTail(int n, long acc) {
    if (n <= 1) return acc;
    return factorialTail(n - 1, n * acc);  // Recursion is the last step
}

// Call
long result = factorialTail(5, 1);
💡 Note: Java compilers don't automatically optimize tail recursion, but understanding this concept helps when learning other languages.

Memoization

Store computed results in a cache to avoid redundant calculations.

JAVA
import java.util.HashMap;
import java.util.Map;

public class MemoFibonacci {
    private static Map<Integer, Long> cache = new HashMap<>();
    
    public static long fibonacci(int n) {
        if (n <= 1) return n;
        
        // Check cache
        if (cache.containsKey(n)) {
            return cache.get(n);
        }
        
        // Compute and cache
        long result = fibonacci(n - 1) + fibonacci(n - 2);
        cache.put(n, result);
        return result;
    }
    
    public static void main(String[] args) {
        System.out.println(fibonacci(50));  // 12586269025
    }
}

❓ Frequently Asked Questions

Q When should I use recursion vs loops?
A Use loops for simple problems—they're more efficient. Recursion is suitable for naturally recursive problems like tree structures and divide-and-conquer algorithms.
Q When should I use static methods?
A Use static methods for utility methods that don't need to access object state. Use instance methods when you need to access object state.
Q What's the difference between method references and Lambda?
A Method references are a shorthand for Lambda, making code more concise. However, not all Lambdas can be replaced with method references.

📖 Summary

📝 Exercises

  1. Recursion practice: Use recursion to calculate the sum from 1 to n
  2. Recursion practice: Use recursion to reverse a string
  3. Utility class: Write a math utility class with methods for maximum, minimum, average, etc.

Next Lesson

In the next lesson, we'll learn about the String Class — common string operations.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏