以下代码无法编译,
Validation<String, AdRequest> validateTrackingRequest(final AdRequest request) {
return request.getTracking().stream()
.filter(tracker -> tracker.url().length() > URL_CHAR_LIMIT).findAny()
.map(tracker ->
Validation.invalid("Tracking URL for event " + tracker.type() + " exceeds "
+ URL_CHAR_LIMIT + " character limit: " + tracker.url()))
.orElse(Validation.valid(request));
}
带有错误消息
Incompatible types. Required: Validation<String, AdRequest>. Found Validation<String, Object>.
尝试一下,我发现在调用map
之前添加这种奇怪的语法可以解决问题:
.<Validation<String, AdRequest>>map(tracker ->
(之前我见过其他人这样做过。)
这是什么语法?
我知道发生这种情况是因为Validation.invalid
的基础机制必须基于通用Object
,因此需要某种类型的转换。所以也许这个语法是&#34; cast&#34;。
但是,还有更好的方式来写我正在做的事情吗?
(这是javaslang
a.k.a. vavr
的验证库。)
答案 0 :(得分:3)
它被称为带有显式类型参数的方法调用。你可以使用一种不那么“怪异”的语法:
Validation.<String, AdRequest>invalid(...)
问题在于如何定义Validation.invalid
方法以及将在其中调用的上下文。
static <E, T> Validation<E, T> invalid(E error)
无法隐式确定第二个通用参数T
,因为map
并不关心结果的类型。
// no context
Validation<String, Object> v1 = Validation.invalid("error");
// the context set explicitly
Validation<String, AdRequest> v2 = Validation.<String, AdRequest>invalid("error");
// the type is determined by the context implicitly
Validation<String, AdRequest> v3 = Validation.invalid("error");
要弄清楚类型,应该存在上下文。 Optional.map
没有给你这个背景。它适用于您传递的任何结果类型R
:
// v1 = Validation<String, Object>
Optional<Validation<String, Object>> o1 = ofNullable(null).map(i -> v1);
// v2 = Validation<String, AdRequest>
Optional<Validation<String, AdRequest>> o2 = ofNullable(null).map(i -> v2);
它将按您提供的类型返回一个通用实例。您正在提供一个Validation<String, Object>
对象,因此您收到的map(Function<..., Validation<String, Object>>)
会混淆orElse
并与返回类型相矛盾。
这是一个品味问题,但我会把一些东西放到变量中:
Validation<String, AdRequest> validateTrackingRequest(AdRequest request) {
Validation<String, AdRequest> valid = Validation.valid(request);
Function<Tracker, Validation<String, AdRequest>> mapper = tracker -> Validation.invalid(...);
Predicate<Tracker> predicate = tracker -> ...;
return request.getTracking().stream().filter(predicate).findAny().map(mapper).orElse(valid);
}