Method/constructor references are commonly agreed to be, most of the time, more compact and readable than using lambdas, and are therefore preferred.

In some rare cases, when it is not clear from the context what kind of function is being described and reference would not increase the clarity, it might be fine to keep the lambda.

Similarly, null checks can be replaced with references to the Objects::isNull and Objects::nonNull methods, casts can be replaced with SomeClass.class::cast and instanceof can be replaced with SomeClass.class::isInstance.

Note that this rule is automatically disabled when the project's sonar.java.source is lower than 8.

Noncompliant Code Example

class A {
  void process(List<A> list) {
    list.stream()
      .filter(a -> a instanceof B)
      .map(a -> (B) a)
      .map(b -> b.<String>getObject())
      .forEach(b -> { System.out.println(b); });
  }
}

class B extends A {
  <T> T getObject() {
    return null;
  }
}

Compliant Solution

class A {
  void process(List<A> list) {
    list.stream()
      .filter(B.class::isInstance)
      .map(B.class::cast)
      .map(B::<String>getObject)
      .forEach(System.out::println);
  }
}

class B extends A {
  <T> T getObject() {
    return null;
  }
}