Method References
Using :: operator (Java 8+)
6 min read
Method References in Java
Method references (::) are a shorthand for lambdas that just call an existing method. They make code cleaner and more readable.
Four Types of Method References
| Type | Syntax | Lambda Equivalent |
|---|---|---|
| Static | Class::staticMethod |
x -> Class.staticMethod(x) |
| Instance (bound) | object::instanceMethod |
x -> object.method(x) |
| Instance (unbound) | Class::instanceMethod |
obj -> obj.method() |
| Constructor | Class::new |
() -> new Class() |
✓ Benefits: More readable than lambdas, clearly shows intent, promotes code reuse.
💡 Rule: Method reference can replace lambda only when lambda just calls a method with its parameters.
Code Examples
Static method references
java
1// 1. Static Method Reference - ClassName::staticMethod
2List<String> names = Arrays.asList("Bob", "Alice", "Charlie");
3
4// Lambda
5names.forEach(s -> System.out.println(s));
6
7// Method reference (cleaner!)
8names.forEach(System.out::println);
9
10// More examples
11// Lambda: x -> Math.abs(x)
12Function<Integer, Integer> abs = Math::abs;
13
14// Lambda: x -> Integer.parseInt(x)
15Function<String, Integer> parser = Integer::parseInt;
16
17// Lambda: (a, b) -> Integer.compare(a, b)
18Comparator<Integer> comparator = Integer::compare;
19
20List<String> numbers = Arrays.asList("1", "2", "3");
21numbers.stream()
22 .map(Integer::parseInt) // Static method reference
23 .forEach(System.out::println);Bound instance method references
java
1// 2. Instance Method (Bound) - object::instanceMethod
2String prefix = "Hello, ";
3
4// Lambda
5Function<String, String> greeterLambda = s -> prefix.concat(s);
6
7// Method reference (bound to 'prefix' object)
8Function<String, String> greeterRef = prefix::concat;
9
10System.out.println(greeterRef.apply("World")); // Hello, World
11
12// Practical example
13List<String> items = new ArrayList<>();
14
15// Lambda: x -> items.add(x)
16Consumer<String> adder = items::add;
17adder.accept("Apple");
18adder.accept("Banana");
19
20// Using with streams
21PrintStream out = System.out;
22List<Integer> nums = Arrays.asList(1, 2, 3);
23nums.forEach(out::println); // Bound to 'out' objectUnbound instance method references
java
1// 3. Instance Method (Unbound) - ClassName::instanceMethod
2List<String> names = Arrays.asList("Bob", "alice", "CHARLIE");
3
4// Lambda: (s) -> s.toUpperCase()
5names.stream()
6 .map(String::toUpperCase)
7 .forEach(System.out::println);
8
9// Lambda: (s) -> s.length()
10Function<String, Integer> lengthFunc = String::length;
11System.out.println(lengthFunc.apply("Hello")); // 5
12
13// Sorting with unbound reference
14// Lambda: (s1, s2) -> s1.compareToIgnoreCase(s2)
15names.sort(String::compareToIgnoreCase);
16
17// Object methods
18List<Object> objects = Arrays.asList("A", 1, 3.14);
19
20// Lambda: o -> o.toString()
21objects.stream()
22 .map(Object::toString)
23 .forEach(System.out::println);Constructor references
java
1// 4. Constructor Reference - ClassName::new
2// Lambda: () -> new ArrayList<>()
3Supplier<List<String>> listSupplier = ArrayList::new;
4List<String> newList = listSupplier.get();
5
6// Lambda: s -> new StringBuilder(s)
7Function<String, StringBuilder> sbCreator = StringBuilder::new;
8StringBuilder sb = sbCreator.apply("Hello");
9
10// With streams - creating objects
11List<String> names = Arrays.asList("Alice", "Bob");
12
13// Lambda: name -> new User(name)
14List<User> users = names.stream()
15 .map(User::new) // Constructor reference
16 .collect(Collectors.toList());
17
18// Array constructor reference
19// Lambda: size -> new String[size]
20IntFunction<String[]> arrayCreator = String[]::new;
21String[] array = arrayCreator.apply(5); // new String[5]
22
23// With toArray()
24String[] namesArray = names.stream()
25 .toArray(String[]::new);Use Cases
- Stream operations (map, filter, forEach)
- Sorting with Comparator
- Factory methods and Supplier pattern
- Event handlers and callbacks
- Collection operations
- Functional interface implementations
Common Mistakes to Avoid
- Using when lambda does more than call a method
- Confusing bound vs unbound references
- Wrong method reference type for context
- Not understanding parameter mapping
- Using with ambiguous overloaded methods
- Forgetting method references are not lambdas