在JDK 8中将函数作为参数传递

时间:2015-12-16 05:02:46

标签: java functional-programming java-8 refactoring

我正在尝试重构下面的代码

class FileDownloadResource{

   @Inject
   private FileDownload fileDownload;

    @Path(/abc)
    public Response downloadFileABC(){

         try{
              fileDownload.downloadABC();

         }catch(IOException e){

         }
          //Some code here that is common to the second method as well

    }

    @Path(/xyz)
     public Response downloadFileXYZ(){

         try{
              fileDownload.downloadXYZ();

         }catch(IOException e){
             //handle exception
         }
          //Some code here that is common to the first method as well

    }  
  }

该类是JAX-RS休息资源。正如您在上面的代码中看到的,除了try块中的内容之外的所有内容对于两个方法都是相同的。我们可以使用任何新的JDK 8吗? 将fileDownload.downloadABC()作为参数传递给私有方法的功能?

基本上,我正在寻找一些传递函数的方法 作为参数,让代码的其他部分相同。

2 个答案:

答案 0 :(得分:4)

当然可以。您需要使用现有的功能接口或创建新的功能接口。如您所希望选中IOException,最好创建新版本(您也可以使用Callable<Void>,但不太方便):

@FunctionalInterface
interface IORunnable {
    void run() throws IOException;
}

现在您可以创建通用请求处理程序私有方法:

public Response handleRequest(IORunnable r){
     try {
         r.run();
     } catch(IOException e){
         // handle exception
     }
     //Common code follows
}

并像这样使用它:

@Path("/abc")
public Response downloadFileABC(){
    return handleRequest(fileDownload::downloadABC);
}

或者使用lambda:

@Path("/abc")
public Response downloadFileABC(){
    return handleRequest(() -> fileDownload.downloadABC());
}

答案 1 :(得分:3)

只要downloadABC()downloadXYZ()方法具有与download()接口的Download方法相同的参数和返回值,就可以执行此操作。

接口名称和接口方法可以是您选择的任何内容。

@FunctionalInterface
interface DownloadMethod {
    public void doDownload() throws IOException;
}

class FileDownload {
    public void downloadABC() throws IOException {}
    public void downloadXYZ() throws IOException {}
}

class FileDownloadResource{

    @Inject
    private FileDownload fileDownload;

    @Path("/abc")
    public Response downloadFileABC(){
        return download(fileDownload::downloadABC);
    }

    @Path("/xyz")
    public Response downloadFileXYZ() {
        return download(fileDownload::downloadXYZ);
    }

    private Response download(DownloadMethod method){
        try{
            method.doDownload();
        }catch(IOException e){
            //handle exception
        }
        //Some code here that is common to both methods
    }
}