I have a code that prints some metadata information from cosmos, and I want to print it in case that the response is not null, if it's, it's not important, and just log a null entry
Java File:
private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor {
@Override
public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) {
if (responseDiagnostics != null && log.isDebugEnabled()) {
CosmosDiagnostics cosmosResponseDiagnostics = responseDiagnostics.getCosmosDiagnostics();
Duration latency = tryGet(cosmosResponseDiagnostics::getDuration);
log.debug("action=CosmosQueryLatencyInMs, value={}", tryGet(latency::toMillis));
}
}
}
The tryGet function just makes sure that if any invocation throws an exception it will return a null
/***
* try to get a value with optional null on error
* @param supplier object supplier
* @return returns T type
*/
static <T> T tryGet(Supplier<T> supplier) {
return tryGet(supplier, null);
}
/***
* try to get a value with optional default on null
* @param supplier object supplier
* @param defaultValue defaultValue
* @return returns T type
*/
static <T> T tryGet(Supplier<T> supplier, T defaultValue) {
try {
T result = supplier.get();
if (result == null) {
return defaultValue;
}
return result;
} catch (Exception e) {
//ignore
// this is to get value with null propagation
return defaultValue;
}
}
But unfortunately the generated code adds Objects.requireNonNull, which defeats the whole purpose of the tryGet to stop the null propagation
Compiled .Class File:
private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor {
private ResponseDiagnosticsProcessorImplementation() {
}
public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) {
if (responseDiagnostics != null && CosmosDbConfiguration.log.isDebugEnabled()) {
CosmosDiagnostics cosmosResponseDiagnostics = responseDiagnostics.getCosmosDiagnostics();
Objects.requireNonNull(cosmosResponseDiagnostics);
Duration latency = (Duration)ValueSupplierUtil.tryGet(cosmosResponseDiagnostics::getDuration);
Logger var10000 = CosmosDbConfiguration.log;
Objects.requireNonNull(latency);
var10000.debug("action=CosmosQueryLatencyInMs, value={}", ValueSupplierUtil.tryGet(latency::toMillis));
}
}
}
I can simply change the code so that the try get evaluates the whole expression so that it doesn't propagate the null pointer exception
Java File:
private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor {
@Override
public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) {
if (responseDiagnostics != null && log.isDebugEnabled()) {
log.debug("action=CosmosQueryLatencyInMs, value={}",
tryGet(() -> responseDiagnostics.getCosmosDiagnostics().getDuration().toMillis()));
}
}
}
And that keeps the same behaviour in the class code:
Compiled .Class File:
private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor {
private ResponseDiagnosticsProcessorImplementation() {
}
public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) {
if (responseDiagnostics != null && CosmosDbConfiguration.log.isDebugEnabled()) {
CosmosDbConfiguration.log.debug("action=CosmosQueryLatencyInMs, value={}", ValueSupplierUtil.tryGet(() -> {
return responseDiagnostics.getCosmosDiagnostics().getDuration().toMillis();
}));
}
}
}
My question is, in which cases the Java Compiler adds a requires non null check and why?