[英]Can someone explain to me this method signature
我正在查看以下代码(其他人的代码),部分代码对我来说似乎很模糊:
List<string> result = forkJoinPool.invokeAll(tasks)
.stream()
.map(MUtil.rethrowFunction(Future::get))
.collect(toList());
这部分很简单,一个 ForkJoinPool.invokeAll() 返回一个未来对象列表,进一步处理返回一个字符串列表。
稍后,list.stream().map() 在 Mutil class Mutil.rethrowFunction(Future::get) 上使用 static 方法,并将其传递给 Future 类型的 ZA8CFDE6331BD59EB2AC96F8911C4B66。 查看 Mutil 源代码:
public class Mutil {
public static <T, R> Function<T, R> rethrowFunction(WithExceptionsIF<T, R> function) {
return t -> {
try { return function.apply(t); }
catch (Exception exception) { throwAsUnchecked(exception); return null; }
};
}
@FunctionalInterface
public interface WithExceptionsIF<T, R> {
R apply(T t) throws Exception;
}
@SuppressWarnings ("unchecked")
private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E { throw (E)exception; }
}
Mutil.rethrowFunction()
的签名表示它返回<T, R> Function<T, R>
并使用类型为WithExceptionsIF<T, R>
的参数(这是一个功能接口)。 Future.get() 如何转换为Mutil.rethroFunction()
签名? Future.get(),返回计算结果而不是 Function?
传递给Mutil.rethrowFunction()
Future.get()
Future.get() 如何转换为WithExceptionIF<T,R>
类型?
t->{return function.apply(t);}
这个语句是怎么回事? 不是未来 object,如果是,那么“功能”是谁?
Mutil.throwAsUnchecked(Exception exception)
方法的签名在关键字“static”之后定义了<E extends Throwable>
。 如果“异常”是传递给方法的唯一参数,那么 E 来自哪里,为什么在方法的返回类型(void)之前声明它?
感谢您的澄清。
这是一个完整的可运行示例。
package org.example;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.function.Function;
import static java.util.stream.Collectors.toList;
public class SO62737345 {
public static void main(String... args) {
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
List<Callable<String>> tasks = Collections.singletonList(() -> "fish");
List<String> result = forkJoinPool.invokeAll(tasks)
.stream()
.map(rethrowFunction(Future::get))
.collect(toList());
}
public static <T, R> Function<T, R> rethrowFunction(WithExceptionsIF<T, R> function) {
return t -> {
try {
return function.apply(t);
}
catch (Exception exception) { throwAsUnchecked(exception); return null; }
};
}
@FunctionalInterface
public interface WithExceptionsIF<T, R> {
R apply(T t) throws Exception;
}
@SuppressWarnings ("unchecked")
private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E { throw (E)exception; }
}
调用rethrowFunction
时不会执行get()
方法。 对rethrowFunction
的调用只是将传入的 function 从一个引发检查异常的一个转换为一个不引发检查的异常(因为任何异常都包含在未经检查的异常中)。 collect()
方法实际上调用了 function,为 Stream 中的每个Future
调用一次。
考虑使用 lambda 而不是方法引用传递Future::get
。 这将是f -> f.get()
。 因为我们传递了一个成员 function ,所以它将它所属的 object 作为参数。 所以我们传递了一个 function,并且由于 get() 的签名是V get() throws InterruptedException, ExecutionException
它匹配WithExceptionsIF
。 实际上,在这种特殊情况下,它是WithExceptionsIF<Future,String>
的一个实例。
如果你通过替换上面的 lambda 来扩展它,你会得到: return (f -> f.get()).apply(t)
所以当评估 rethrowFunction` 返回get is being applied to the parameter being passed when the function which
。
此处解释了这一点Java 8 Java 中异常类型推断的特殊功能正在执行“类型推断”。 编译器被告知throwAsUnchecked
会抛出 object ,其 class 是 Throwable 的子类。 因为rethrowFunction
的返回类型没有声明检查异常,所以编译器决定throwAsUnchecked
必须抛出RuntimeException
。 另一种看待它的方式是,在这种情况下,类型参数的值是从调用 function 的上下文中推断出来的,而不是从其参数中推断出来的。 至少我认为它是这样工作的,不是那么容易理解的!
更一般地解释通用语法,通常方法是参数化类型的一部分,例如List<A>
,因此类型参数可以出现在成员函数的签名中,例如A get(int i)
。 You can also have a generic function whose signature has type parameters which do not appear in the class (or a static function which is not associated with an instance of the class), and here they are declared before the return type.
„
get()
方法在调用 rethrowFunction 时不执行……“
这是不正确的。 Future::get
在rethrowFunction()s
调用链中被调用过; 作为调用rethrowFunction()
的副作用。 Future::get
的返回类型是MUtil.WithExceptionsIF
。 它是作为输入参数传递给rethrowFunction()
的返回值。
„这只是将传入的 function 从一个引发检查异常的一个转换为一个不... “
这句话的措辞令人困惑。 读起来好像句子中的“那个”指的是Future::get
。 get()
方法不执行该转换。 rethrowFunction()
方法是繁重的工作。
„考虑传递 Future::get ......因为我们正在传递一个成员 function 它需要它所属的 object 作为参数“
„ ...因为 get() 的签名是
V get() throws InterruptedException, ExecutionException
在这种特殊情况下匹配WithExceptionsIF
...“
这也不对。 Future.get()
的签名与任何事情无关。 Future.get()
的签名与 WithExceptionsIF WithExceptionsIF
肯定不是真的。 同样,在此特定调用中, Future.get()
的返回类型将是WithExceptionsIF
。 但是方法的返回类型不是其签名的一部分。
Future.get()
转换为 * WithExceptionsIF<T,R>
因为forkJoinPool.invokeAll(tasks)
返回一个List<Future <MUtil.WithExceptionsIF<T,R>>>
。
„如果你通过替换上面的 lambda 来扩展它,你会得到:
return (f -> f.get()).apply(t)
所以get is being applied to the parameter being passed when the function which
。 “
不正确。 同样, Future.get()
与它无关。 Future.get()s
工作在将 WithExceptionsIF 传递给WithExceptionsIF
后rethrowFunction
。 t -> {...}
块定义了一个 lambda ,由rethrowFunction()
调用返回。 t
是 lambda 的输入参数。 它的类型将是类型参数T
实例化的任何类型。
当实际调用 lambda 时,会调用WithExceptionsIF.apply()
方法的一些具体实现; 在后来的某个未知点。
function
我们看到有一个WithExceptionsIF<T, R>
实例传入rethrowFunction(WithExceptionsIF<T, R> function)
。
„ …如果“异常”是传递给方法的唯一参数,那么 E 来自哪里,为什么要在方法的返回类型 (void) 之前声明它? “
这: static <E extends Throwable> void throwAsUnchecked(Exception exception)
是声明泛型方法的方式。 在类型参数部分中声明的E
类型变量用于方法的throws
子句。 也在它的身体里; 将传递给方法的Exception
转换为另一种更具体的类型,该类型将在实际调用泛型方法时指定。
最后但并非最不重要的一点是: List<string>...
分配错误有几个原因。 主要原因是您示例中的 stream 不产生Stream<String>
。 它产生Stream<Function<T, R>>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.