Java 是否可以声明供应商<;T>;需要抛出异常吗?
因此,我尝试重构以下代码:Java 是否可以声明供应商<;T>;需要抛出异常吗?,java,java-8,functional-interface,Java,Java 8,Functional Interface,因此,我尝试重构以下代码: /** * Returns the duration from the config file. * * @return The duration. */ private Duration durationFromConfig() { try { return durationFromConfigInner(); } catch (IOException ex) { throw new IllegalStat
/**
* Returns the duration from the config file.
*
* @return The duration.
*/
private Duration durationFromConfig() {
try {
return durationFromConfigInner();
} catch (IOException ex) {
throw new IllegalStateException("The config file (\"" + configFile + "\") has not been found.");
}
}
/**
* Returns the duration from the config file.
*
* Searches the log file for the first line indicating the config entry for this instance.
*
* @return The duration.
* @throws FileNotFoundException If the config file has not been found.
*/
private Duration durationFromConfigInner() throws IOException {
String entryKey = subClass.getSimpleName();
configLastModified = Files.getLastModifiedTime(configFile);
String entryValue = ConfigFileUtils.readFileEntry(configFile, entryKey);
return Duration.of(entryValue);
}
我首先想到了以下几点:
private <T> T getFromConfig(final Supplier<T> supplier) {
try {
return supplier.get();
} catch (IOException ex) {
throw new IllegalStateException("The config file (\"" + configFile + "\") has not been found.");
}
}
更新,我刚刚意识到供应商
界面是一个非常简单的界面,因为它只有get()
方法。我扩展供应商的最初原因是为了优先使用基本功能,例如默认方法。- 如果您这样做,您将无法将其用作
,因为它只会抛出UnsupportedOperationException供应商
- 考虑到上述情况,为什么不创建一个新接口并在其中声明
方法呢getWithIO
@FunctionalInterface public interface SupplierWithIO<T> { public T getWithIO() throws IOException; }
@functioninterface 带有IO的公共接口供应商{ public T getWithIO()抛出IOException; }
- 也许有些东西比旧式Java接口更好?旧式Java并不是因为现在有了Java8就消失了
@FunctionalInterface
public interface CheckedSupplier<T, E extends Exception> {
public T get() throws E;
}
private <R> R getFromConfig(final String entryKey, final Function<String, R> converter) throws IOException {
Objects.requireNonNull(entryKey);
Objects.requireNonNull(converter);
configLastModified = Files.getLastModifiedTime(configFile);
return ConfigFileUtils.readFileEntry(configFile, entryKey, converter);
}
private <T> T handleIOException(final CheckedSupplier<T, IOException> supplier) {
Objects.requireNonNull(supplier);
try {
return supplier.get();
} catch (IOException ex) {
throw new IllegalStateException("The config file (\"" + configFile + "\") has not been found.");
}
}
我不太乐意将IOException
转换为UncheckedIOException
,如下所示:
IOException
的方法添加一个未经检查的变量IOException
,而不是希望您不要忘记捕获未选中的IOException
在lambda邮件列表中,这是一个。正如您所见,Brian Goetz在那里建议,替代方法是编写您自己的combinator:
static<T> Block<T> exceptionWrappingBlock(Block<T> b) {
return e -> {
try { b.accept(e); }
catch (Exception e) { throw new RTE(e); }
};
}
或者您可以编写自己的简单组合器:
static<T> Block<T> exceptionWrappingBlock(Block<T> b) {
return e -> {
try { b.accept(e); }
catch (Exception e) { throw new RTE(e); }
};
}
静态块例外WrappingBlock(块b){
返回e->{
试试{b.接受(e);}
catch(异常e){抛出新的RTE(e);}
};
}
你可以写一次,用的时间比写你的文章要少
原始电子邮件。同样,每种SAM使用一次
我宁愿我们把它看作是“99%装满的玻璃”,而不是
可供替代的并非所有的问题都需要新的语言特性
解决。(更不用说新的语言特性总是会导致
新问题。)
在那些日子里,消费者界面被称为Block
我认为这与上面Marko的建议相符
后来,Brian这样设计(问题的原因)
是的,您必须提供自己的特殊SAM。但是兰姆达
转换将与他们一起工作
专家组讨论了这方面的其他语言和库支持
问题,并最终认为这是一个糟糕的成本/效益
权衡
基于库的解决方案导致SAM类型激增2倍(例外
vs not),它们与现有的组合爆炸产生了严重的交互作用
对于原始专业化
可用的基于语言的解决方案是来自
复杂性/价值权衡。虽然有一些选择
我们将继续探索解决方案——尽管显然不是
8岁,可能也不是9岁
同时,你有工具去做你想做的事。我明白了
您希望我们为您提供最后一英里(其次是您的
这个请求实际上是一个隐晦的请求,“你为什么不
已经放弃检查异常),但我认为当前
州政府让你完成工作
由于我在这个问题上还有一点要说,我决定补充我的答案 您可以选择编写一个方便的方法,该方法可以是:
stream.forEachOrdered(uncheckWrapOneArg(o -> out.write(o)));
我还发现,为所有lambda签名重载包装方法名称通常会导致不明确的lambda表达式错误。因此,您需要更长的不同名称,从而产生比上述方法更长的char-for-char代码
@FunctionalInterface
public interface CheckedCall<T, E extends Throwable> {
T call() throws E;
}
public <T> T logTime(CheckedCall<T, Exception> block) throws Exception {
Stopwatch timer = Stopwatch.createStarted();
try {
T result = block.call();
System.out.println(timer.stop().elapsed(TimeUnit.MILLISECONDS));
return result;
} catch (Exception e) {
throw e;
}
}
最后,请注意,上述方法仍然不排除编写简单的包装器方法,这些方法重用uncheckedRun/Call
,但我发现它很无趣,因为节省最多可以忽略不计。Edit
正如多次指出的,您不需要任何自定义类,而是使用Callable和Runnable
错误、过时的解决方案
考虑以下通用解决方案:
// We need to describe supplier which can throw exceptions
@FunctionalInterface
public interface ThrowingSupplier<T> {
T get() throws Exception;
}
// Now, wrapper
private <T> T callMethod(ThrowingSupplier<T> supplier) {
try {
return supplier.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
// And usage example
String methodThrowsException(String a, String b, String c) throws Exception {
// do something
}
String result = callMethod(() -> methodThrowsException(x, y, z));
//我们需要描述能够抛出异常的供应商
@功能接口
公共接口供应商{
T get()抛出异常;
}
//现在,包装器
私人呼叫方式(通过供应商){
试一试{
返回供应商。get();
}捕获(例外e){
抛出新的运行时异常(e);
}
返回null;
}
//以及使用示例
String methodThrowsException(字符串a、字符串b、字符串c)引发异常{
//做点什么
}
String result=callMethod(()->methodThrowsException(x,y,z));
我们也可以使用这种通用解决方案。我们用这种方法处理的任何类型的异常
@FunctionalInterface
public interface CheckedCall<T, E extends Throwable> {
T call() throws E;
}
public <T> T logTime(CheckedCall<T, Exception> block) throws Exception {
Stopwatch timer = Stopwatch.createStarted();
try {
T result = block.call();
System.out.println(timer.stop().elapsed(TimeUnit.MILLISECONDS));
return result;
} catch (Exception e) {
throw e;
}
}
@functioninterface
公共接口CheckedCall{
T call()抛出E;
}
公共T日志时间(CheckedCall块)引发异常{
秒表计时器=Stopwatch.createStarted();
试一试{
T result=block.call();
System.out.println(timer.stop();
返回结果;
}捕获(例外e){
投掷e;
}
}
忘记保留选中的异常。。。在中使用抛出异常
签名
// We need to describe supplier which can throw exceptions
@FunctionalInterface
public interface ThrowingSupplier<T> {
T get() throws Exception;
}
// Now, wrapper
private <T> T callMethod(ThrowingSupplier<T> supplier) {
try {
return supplier.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
// And usage example
String methodThrowsException(String a, String b, String c) throws Exception {
// do something
}
String result = callMethod(() -> methodThrowsException(x, y, z));
@FunctionalInterface
public interface CheckedCall<T, E extends Throwable> {
T call() throws E;
}
public <T> T logTime(CheckedCall<T, Exception> block) throws Exception {
Stopwatch timer = Stopwatch.createStarted();
try {
T result = block.call();
System.out.println(timer.stop().elapsed(TimeUnit.MILLISECONDS));
return result;
} catch (Exception e) {
throw e;
}
}