«Неуместный вызов метода блокировки», когда один StringBuilder добавляет другой

#java #intellij-idea #reactive-programming #project-reactor #stringbuilder

Вопрос:

Почему IntelliJ IDEA показывает предупреждение «Неподходящий вызов метода блокировки», когда один StringBuilder добавляет другой?

 public Mono<String> doSomethingReactive() {
    final StringBuilder sb1 = new StringBuilder("hello");
    final StringBuilder sb2 = new StringBuilder("world");
    sb1.append(sb2); // This append() causes warning "Inappropriate blocking method call"
    sb1.append(sb2.toString()); // ... but this append() is OK :)
    return Mono.just(sb1.toString());
}
 

Комментарии:

1. Я подозреваю, что это IntelliJ особенный. Если бы мы говорили об StringBuffer этом, все было бы по-другому, но StringBuilder у AFAIK нет кода блокировки.

2. @MichaelBerry Я создал проблему в инструменте отслеживания JetBrains: youtrack.jetbrains.com/issue/IDEA-282947

Ответ №1:

Я подозреваю, что это ошибка в ИДЕЕ IntelliJ, если только кто-нибудь не даст разумного объяснения. Видишь https://youtrack.jetbrains.com/issue/IDEA-282947

Ответ №2:

Я думаю, что это блокирует, так что, возможно, именно поэтому IntelliJ жалуется. Поскольку вы создаете Моно в конце метода, все, что предшествует этому, выполняется до или вне потока Моно. Это противоречит цели реактивного потока. Если я поставлю Моно вверху, то без предупреждения:

 public Mono<String> doSomethingReactive() {
    return Mono.just(new StringBuilder("hello"))
            .map(sb1 -> {
                StringBuilder sb2 = new StringBuilder("world");
                sb1.append(sb2);
                sb1.append(sb2.toString());
                return sb1.toString();
            });
}
 

В этом случае только создание первого StringBuilder выполняется вне монопотока.

Кроме того, имейте в виду, я думаю, что IntelliJ может подумать, что sb1.append(sb2) это вызов Object::toString (), который вполне может блокировать, когда он кэширует имя класса в виртуальной машине, тогда sb1.append(sb2.toString()) как называется StringBuilder::toString (), который может не блокировать.