MethodReferenceUsage
SUGGESTION
Style
Summary
Prefer method references over lambda expressions
Suppression
Suppress false positives by adding the suppression annotation
@SuppressWarnings("MethodReferenceUsage")
to the enclosing element.Disable this pattern completely by adding
-Xep:MethodReferenceUsage:OFF
as compiler argument. Learn more.
Samples
Replacement
Shows the difference in example code before and after the bug pattern is applied.
import static java.util.Collections.emptyList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.IntSupplier;
import java.util.function.Supplier;
import java.util.stream.Stream;
class A {
static class B extends A {
final A a = new B();
final B b = new B();
IntSupplier intSup;
Supplier<List<?>> listSup;
void m() {
- intSup = () -> a.iint0();
- intSup = () -> b.iint0();
- intSup = () -> this.iint0();
- intSup = () -> super.iint0();
+ intSup = a::iint0;
+ intSup = b::iint0;
+ intSup = this::iint0;
+ intSup = super::iint0;
intSup = () -> a.sint0();
intSup = () -> b.sint0();
intSup = () -> this.sint0();
intSup = () -> super.sint0();
- intSup = () -> A.sint0();
- intSup = () -> B.sint0();
+ intSup = A::sint0;
+ intSup = B::sint0;
- listSup = () -> Collections.emptyList();
- listSup = () -> emptyList();
+ listSup = Collections::emptyList;
+ listSup = Collections::emptyList;
- Stream.of((Class<?>) int.class).filter(c -> c.isEnum());
- Stream.of((Map<?, ?>) null).map(Map::keySet).map(s -> s.size());
+ Stream.of((Class<?>) int.class).filter(Class::isEnum);
+ Stream.of((Map<?, ?>) null).map(Map::keySet).map(Set::size);
}
@Override
int iint0() {
return 0;
}
}
int iint0() {
return 0;
}
static int sint0() {
return 0;
}
}
Identification
Shows code lines which will (not) be flagged by this bug pattern.
A //BUG: Diagnostic contains:
comment is placed above any violating line.
import com.google.common.collect.Streams;
import java.util.HashMap;
import java.util.Map;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.stream.Stream;
class A {
private final Stream<Integer> s = Stream.of(1);
private final Map<Integer, Integer> m = new HashMap<>();
private final Runnable thrower =
() -> {
throw new RuntimeException();
};
void unaryExternalStaticFunctionCalls() {
s.forEach(String::valueOf);
// BUG: Diagnostic contains:
s.forEach(v -> String.valueOf(v));
s.forEach(
// BUG: Diagnostic contains:
(v) -> {
String.valueOf(v);
});
s.forEach(
// BUG: Diagnostic contains:
(Integer v) -> {
{
String.valueOf(v);
}
});
s.forEach(
v -> {
String.valueOf(v);
String.valueOf(v);
});
s.map(String::valueOf);
// BUG: Diagnostic contains:
s.map(v -> String.valueOf(v));
// BUG: Diagnostic contains:
s.map((v) -> (String.valueOf(v)));
s.map(
// BUG: Diagnostic contains:
(Integer v) -> {
return String.valueOf(v);
});
s.map(
// BUG: Diagnostic contains:
(final Integer v) -> {
return (String.valueOf(v));
});
s.map(
v -> {
String.valueOf(v);
return String.valueOf(v);
});
s.findFirst().orElseGet(() -> Integer.valueOf("0"));
m.forEach((k, v) -> String.valueOf(v));
m.forEach((k, v) -> String.valueOf(k));
}
void binaryExternalInstanceFunctionCalls() {
m.forEach(m::put);
// BUG: Diagnostic contains:
m.forEach((k, v) -> m.put(k, v));
m.forEach((k, v) -> m.put(v, k));
m.forEach(
// BUG: Diagnostic contains:
(Integer k, Integer v) -> {
m.put(k, v);
});
m.forEach(
(k, v) -> {
m.put(k, k);
});
m.forEach(
// BUG: Diagnostic contains:
(final Integer k, final Integer v) -> {
{
m.put(k, v);
}
});
m.forEach(
(k, v) -> {
{
m.put(v, v);
}
});
m.forEach((k, v) -> new HashMap<Integer, Integer>().put(k, v));
m.forEach(
(k, v) -> {
m.put(k, v);
m.put(k, v);
});
Streams.zip(s, s, m::put);
// BUG: Diagnostic contains:
Streams.zip(s, s, (a, b) -> m.put(a, b));
Streams.zip(s, s, (a, b) -> m.put(b, a));
// BUG: Diagnostic contains:
Streams.zip(s, s, (Integer a, Integer b) -> (m.put(a, b)));
Streams.zip(s, s, (a, b) -> (m.put(a, a)));
Streams.zip(
s,
s,
// BUG: Diagnostic contains:
(final Integer a, final Integer b) -> {
return m.put(a, b);
});
Streams.zip(
s,
s,
(a, b) -> {
return m.put(b, b);
});
Streams.zip(
s,
s,
// BUG: Diagnostic contains:
(a, b) -> {
return (m.put(a, b));
});
Streams.zip(
s,
s,
(a, b) -> {
return (m.put(b, a));
});
Streams.zip(
s,
s,
(a, b) -> {
m.put(a, b);
return m.put(a, b);
});
}
void nullaryExternalInstanceFunctionCalls() {
s.map(Integer::doubleValue);
// BUG: Diagnostic contains:
s.map(i -> i.doubleValue());
s.map(i -> i.toString());
s.map(i -> s.toString());
// BUG: Diagnostic contains:
Stream.of(int.class).filter(c -> c.isEnum());
Stream.of((Class<?>) int.class).filter(Class::isEnum);
// BUG: Diagnostic contains:
Stream.of((Class<?>) int.class).filter(c -> c.isEnum());
}
void localFunctionCalls() {
s.forEach(v -> ivoid0());
s.forEach(v -> iint0());
s.forEach(v -> svoid0());
s.forEach(v -> sint0());
s.forEach(this::ivoid1);
// BUG: Diagnostic contains:
s.forEach(v -> ivoid1(v));
s.forEach(
// BUG: Diagnostic contains:
v -> {
ivoid1(v);
});
s.forEach(this::iint1);
// BUG: Diagnostic contains:
s.forEach(v -> iint1(v));
s.forEach(
// BUG: Diagnostic contains:
v -> {
iint1(v);
});
s.forEach(A::svoid1);
// BUG: Diagnostic contains:
s.forEach(v -> svoid1(v));
s.forEach(
// BUG: Diagnostic contains:
v -> {
svoid1(v);
});
s.forEach(A::sint1);
// BUG: Diagnostic contains:
s.forEach(v -> sint1(v));
s.forEach(
// BUG: Diagnostic contains:
v -> {
sint1(v);
});
s.forEach(v -> ivoid2(v, v));
s.forEach(v -> iint2(v, v));
s.forEach(v -> svoid2(v, v));
s.forEach(v -> sint2(v, v));
m.forEach((k, v) -> ivoid0());
m.forEach((k, v) -> iint0());
m.forEach((k, v) -> svoid0());
m.forEach((k, v) -> sint0());
m.forEach(this::ivoid2);
// BUG: Diagnostic contains:
m.forEach((k, v) -> ivoid2(k, v));
m.forEach(
// BUG: Diagnostic contains:
(k, v) -> {
ivoid2(k, v);
});
m.forEach(this::iint2);
// BUG: Diagnostic contains:
m.forEach((k, v) -> iint2(k, v));
m.forEach(
// BUG: Diagnostic contains:
(k, v) -> {
iint2(k, v);
});
m.forEach(A::svoid2);
// BUG: Diagnostic contains:
m.forEach((k, v) -> svoid2(k, v));
m.forEach(
// BUG: Diagnostic contains:
(k, v) -> {
svoid2(k, v);
});
m.forEach(A::sint2);
// BUG: Diagnostic contains:
m.forEach((k, v) -> sint2(k, v));
m.forEach(
// BUG: Diagnostic contains:
(k, v) -> {
sint2(k, v);
});
}
void functionCallsWhoseReplacementWouldBeAmbiguous() {
receiver(
i -> {
Integer.toString(i);
});
}
void assortedOtherEdgeCases() {
s.forEach(v -> String.valueOf(v.toString()));
TernaryOp o1 = (a, b, c) -> String.valueOf(a);
TernaryOp o2 = (a, b, c) -> String.valueOf(b);
TernaryOp o3 = (a, b, c) -> String.valueOf(c);
TernaryOp o4 = (a, b, c) -> c.concat(a);
TernaryOp o5 = (a, b, c) -> c.concat(b);
TernaryOp o6 = (a, b, c) -> a.concat(c);
TernaryOp o7 = (a, b, c) -> b.concat(c);
}
void receiver(IntFunction<?> op) {}
void receiver(IntConsumer op) {}
void ivoid0() {}
void ivoid1(int a) {}
void ivoid2(int a, int b) {}
int iint0() {
return 0;
}
int iint1(int a) {
return 0;
}
int iint2(int a, int b) {
return 0;
}
static void svoid0() {}
static void svoid1(int a) {}
static void svoid2(int a, int b) {}
static void svoid3(int a, int b, int c) {}
static int sint0() {
return 0;
}
static int sint1(int a) {
return 0;
}
static int sint2(int a, int b) {
return 0;
}
interface TernaryOp {
String collect(String a, String b, String c);
}
}