Betrachten Sie das folgende minimale Kotlin-Beispiel:
fun <U> someWrapper(supplier: () -> U): () -> (U) {
return { supplier() }
}
fun foo(taskExecutor: TaskExecutor): Int {
val future = CompletableFuture.supplyAsync(someWrapper {
42
}, taskExecutor::execute)
return future.join()
}
@Test
public void shouldFoo() {
assertThat(foo(), is(42));
}
Ich habe in Jacoco Regeln für die Zweigstellenabdeckung, die für den obigen Code fehlschlagen und besagen, dass 1 von 2 Zweigstellen in der Anrufleitung nicht abgedeckt ist someWrapper
. Leider ist es für mich nicht möglich, alle someWrapper
aufgerufenen Klassen auszuschließen .
Betrachten Sie den dekompilierten Java-Code:
public final int foo(TaskExecutor taskExecutor) {
Object var10000 = WrappersKt.someWrapper((Function0)null.INSTANCE);
if (var10000 != null) {
Object var2 = var10000;
var10000 = new Foo$sam$java_util_function_Supplier$0((Function0)var2);
}
Supplier var3 = (Supplier)var10000;
Function1 var4 = (Function1)(new Function1(this.taskExecutor) {
// $FF: synthetic method
// $FF: bridge method
public Object invoke(Object var1) {
this.invoke((Runnable)var1);
return Unit.INSTANCE;
}
public final void invoke(Runnable p1) {
((TaskExecutor)this.receiver).execute(p1);
}
public final KDeclarationContainer getOwner() {
return Reflection.getOrCreateKotlinClass(TaskExecutor.class);
}
public final String getName() {
return "execute";
}
public final String getSignature() {
return "execute(Ljava/lang/Runnable;)V";
}
});
CompletableFuture future = CompletableFuture.supplyAsync(var3, (Executor)(new Foo$sam$java_util_concurrent_Executor$0(var4)));
var10000 = future.join();
Intrinsics.checkExpressionValueIsNotNull(var10000, "future.join()");
return ((Number)var10000).intValue();
}
Ich denke, das Problem ist der if (var10000 != null)
Zweig, der sogar von der IDE als unnötig markiert wird (immer wahr).
Ist es irgendwie möglich, den Code so anzupassen, dass alle Zweige abgedeckt werden können, z. indem Sie sicherstellen, dass der Compiler diese zusätzliche Nullprüfung nicht generiert? Ich kann den Code von beiden ändern foo(..)
und someWrapper(..)
solange ich ein dekoriertes Lambda liefern kann.
Ich benutze Kotlin 1.3.50 und Jacoco 0.8.4.
BEARBEITEN.
Eine offensichtliche Problemumgehung besteht darin, supplyAsync(someWrapper { ... })
in eine Utils-Klasse zu extrahieren und nur diese Klasse auszuschließen, dh:
fun <U> supplyAsync(supplier: () -> U, executor: TaskExecutor): CompletableFuture<U> {
return CompletableFuture.supplyAsync(someWrapper { supplier() }, executor::execute)
}
Das wäre gut genug für mich, obwohl ich immer noch neugierig bin, warum der Zweig von Kotlin hinzugefügt wird, wo kein Zweig sein muss.
Type inference failed
wenn ich versuche, Ihren Beispielcode kompilieren zu lassen. Wäre großartig, wenn Sie Beispielcode bereitstellen könnten, der sofort funktioniert! Zum BeispieltaskExecutor
undcontroller
sind Unbekannte.Antworten:
Wenn der Rückgabewert von
someWrapper
nur als Instanz von verwendet werden sollSupplier
, können Sie die unnötige Nullprüfung entfernen, indem Sie sie explizitSupplier
als Rückgabetyp verwenden.quelle