以下代码无法编译,
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的基础机制必须基于通用对象,因此必须进行某种类型的强制转换.因此,也许这种语法就是“ cast”.
但是,还有一种更好的方式来写我在做什么吗?
(这是javaslang a.k.a. vavr的验证库.)
解决方法:
这称为带有显式类型参数的方法调用.您可以使用不太“奇怪”的语法:
Validation.<String, AdRequest>invalid(...)
问题在于Validation.invalid方法的定义方式以及将在其中调用什么上下文.
static <E, T> Validation<E, T> invalid(E error)
由于map不在乎结果的类型,因此无法隐式确定第二个通用参数T.
// 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);
}