Skip to content

ExtensionContext.Store#computeifAbsent(...) method signatures - Final hour concern - before 6.0.0 is GA #5004

@kaipe

Description

@kaipe

Final hour concern - before 6.0.0 is GA!
I'm surprised to see these new method signatures on ExtensionContext.Store ...

<K, V> Object computeIfAbsent(K key,
		Function<? super K, ? extends V> defaultCreator);
<K, V> V computeIfAbsent(K key,
		Function<? super K, ? extends V> defaultCreator,
		Class<V> requiredType);

... because imho it would be sufficient with just this one ...

<K, V> V computeIfAbsent(K key, Function<? super K, ? extends V> defaultCreator);

... having V as return-type.

Current javadoc also pushes for the third parameter Class<V> requiredType as a mean for better type safety:

		 * <p>For greater type safety, consider using
		 * {@link #computeIfAbsent(Object, Function, Class)} instead.

However, I dont agree, in part because this third method-parameter of type Class<V> is not much help when considering generic type-parameters (e.g. collection types). - This example addresses it:

static class Config {
    static List<Config> parse(String value) {return List.of();}

    static List<Config> resolve(Method m) {
        return parse(m.getAnnotation(ConfigData.class).value());
    }
}
@Retention(RetentionPolicy.RUNTIME) @interface ConfigData {  String value();  }

ExtensionContext.Store myStore;

/** alternative hack with proposed return-type V: */
<K,V> V computeIfAbsent(K key, Function<? super K, ? extends V> defaulter) {
    return (V) myStore.computeIfAbsent(key, defaulter, Object.class);
}

List<Config> withReturnType_V_thisCompilesWithoutCast__(ExtensionContext ctx) {
    return computeIfAbsent(  ctx.getRequiredTestMethod(),   Config::resolve);
}
List<StringBuilder> __andPreventsThisFromCompiling_asIntended__(ExtensionContext ctx) {
    return computeIfAbsent(  ctx.getRequiredTestMethod(),   Config::resolve);
}

List<StringBuilder> __but_core_Store_method_allowsThisToCompile/*!!!*/(ExtensionContext ctx) {
     /* ... i.e. the "requiredType" parameter does not enforce the desired type safety! */
     return myStore.computeIfAbsent(  ctx.getRequiredTestMethod(),  Config::resolve,  List.class);
     /* Do note how this compiles - and also
      * generic type-parameter erasure can make it survive quite far downstream during runtime. */
}

Summary

I see poor type safety with the computeIfAbsent(...) methods signatures of version 6.0.0-RC3
and instead I propose a single method having return-type V ...

<K, V> V computeIfAbsent(K key, Function<? super K, ? extends V> defaultCreator);

... as a simplier and more type safe solution.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions