我知道如何创建一个有String参数并返回int的方法的引用,它是:

Function<String, Integer>

然而,如果函数抛出异常,比如它被定义为:

Integer myMethod(String s) throws IOException

我该如何定义这个引用呢?


当前回答

然而,你可以创建自己的FunctionalInterface,抛出如下..

@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
  void accept(T instance) throws X;
}

然后使用Lambdas或引用实现它,如下所示。

import java.io.FileWriter;
import java.io.IOException;

//lambda expressions and the execute around method (EAM) pattern to
//manage resources

public class FileWriterEAM  {
  private final FileWriter writer;

  private FileWriterEAM(final String fileName) throws IOException {
    writer = new FileWriter(fileName);
  }
  private void close() throws IOException {
    System.out.println("close called automatically...");
    writer.close();
  }
  public void writeStuff(final String message) throws IOException {
    writer.write(message);
  }
  //...

  public static void use(final String fileName, final UseInstance<FileWriterEAM, IOException> block) throws IOException {

    final FileWriterEAM writerEAM = new FileWriterEAM(fileName);    
    try {
      block.accept(writerEAM);
    } finally {
      writerEAM.close();
    }
  }

  public static void main(final String[] args) throws IOException {

    FileWriterEAM.use("eam.txt", writerEAM -> writerEAM.writeStuff("sweet"));

    FileWriterEAM.use("eam2.txt", writerEAM -> {
        writerEAM.writeStuff("how");
        writerEAM.writeStuff("sweet");      
      });

    FileWriterEAM.use("eam3.txt", FileWriterEAM::writeIt);     

  }


 void writeIt() throws IOException{
     this.writeStuff("How ");
     this.writeStuff("sweet ");
     this.writeStuff("it is");

 }

}

其他回答

我在课堂上遇到了这个问题。forName和Class。newInstance在lambda中,所以我做了:

public Object uncheckedNewInstanceForName (String name) {

    try {
        return Class.forName(name).newInstance();
    }
    catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

在lambda中,我没有调用Class.forName("myClass").newInstance(),而是调用uncheckedNewInstanceForName ("myClass")

一些提供的解决方案使用E的泛型参数来传递抛出的异常类型。

更进一步,不是传递异常的类型,而是传递异常类型的Consumer,如……

Consumer<E extends Exception>

您可以创建几个Consumer<Exception>的可重用变体,这些变体将覆盖应用程序的常见异常处理需求。

默认情况下,Java 8函数不允许抛出异常,正如在多个回答中所建议的那样,有许多方法来实现它,其中一种方法是:

@FunctionalInterface
public interface FunctionWithException<T, R, E extends Exception> {
    R apply(T t) throws E;
}

定义为:

private FunctionWithException<String, Integer, IOException> myMethod = (str) -> {
    if ("abc".equals(str)) {
        throw new IOException();
    }
  return 1;
};

并在调用者方法中添加抛出或尝试/捕获相同的异常。

这并不是Java 8所特有的。你正在尝试编译一些等价的东西:

interface I {
    void m();
}
class C implements I {
    public void m() throws Exception {} //can't compile
}

我会做一些一般的事情:

public interface Lambda {

    @FunctionalInterface
    public interface CheckedFunction<T> {

        T get() throws Exception;
    }

    public static <T> T handle(CheckedFunction<T> supplier) {
        try {
            return supplier.get();
        } catch (Exception exception) {
            throw new RuntimeException(exception);

        }
    }
}

用法:

 Lambda.handle(() -> method());