簡體   English   中英

Servlet中的Java Lambda表達式

[英]Java Lambda Expression inside a Servlet

除非我在Lambda表達式中捕獲並重新捕獲了各種Exception,否則下面的代碼不會編譯。 誰能幫我理解原因?

 protected void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException
    {  
        Consumer <String> forwardTo =(s) ->
        {
            RequestDispatcher rd= req.getRequestDispatcher(s);
            try {
                rd.forward(req, res);
            } catch (IOException|ServletException is) {
                try {
                    throw new Exception(is);
                } catch (Exception e) {
                }
            }
        };

doGet會拋出異常,但是您的lambda不會在doGet中執行。 您只是在聲明一個變量-與執行您編寫的表達式不同。

在Java-8之前的版本中,這是等效的代碼:

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    Consumer<String> forwardTo = new Consumer<String>() {
            @Override
            public void accept(String t) {
                RequestDispatcher rd = req.getRequestDispatcher(t);
                try {
                    rd.forward(req, res);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    };
}

您只能將RuntimeExceptions從lambda函數中拋出。 如果更改,則throw new Exception(is); throw new RuntimeException(is); 您無需重新捕獲Exception

支持未檢查異常的另一個原因,尤其是在使用Java 8流時。

Java 8中的默認功能接口被聲明為不拋出任何已檢查的異常。 這意味着您將需要一種或另一種方式來處理代碼可能拋出的已檢查異常。

如果您對Java 8功能接口沒有硬性依賴,則可以自己編寫:

interface ThrowingConsumer<T,E extends Exception> { public void accept(T t) throws E;}

然后只使用它代替Java 8 Consumer

如果您對Java 8功能接口有嚴格的依賴性,則可以隨時包裝產生的異常:

public <T> Consumer<T> ignoreExceptions(ThrowingConsumer<T,?> consumer){
  return t -> {
    try{consumer.accept(t);}catch(Throwable t){/*ignored*/}
  };
}

您可以這樣使用此方法:

Consumer<String> forwardTo = ignoreExceptions(t -> 
       req.getRequestDispatcher(t).forward(req, res));

或者,您可以將它們扔掉:

public <T> Consumer<T> rethrowExceptions(ThrowingConsumer<T,?> consumer){
  return t -> {
    try{consumer.accept(t);}catch(Throwable t){throw new RuntimeException(e);}
  };
}

ServletRequest.getRequestDispatcher方法采用String參數。 您的代碼未為Consumer指定通用類型,因此為lambda參數“ s”給出的類型是Object。 如果您這樣聲明使用方:使用方應進行編譯。

您必須捕獲Exception的原因是因為RequestDispatcher.forward方法拋出ServletException和IOException,這兩個都是Java稱為“ Checked Exception”。 已檢查的異常必須由調用方處理。 這是一篇有關Java異常的文章(互聯網上有很多文章)。 http://www.geeksforgeeks.org/checked-vs-unchecked-exceptions-in-java/

如果要創建一種將已檢查的異常轉換為未檢查的異常的方法,則可以像在下面的代碼中一樣創建一個新的RuntimeException:

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException 
{
    Consumer<String> forwardTo = (s) -> 
    {
        forward(req, res, s);
    };
}

private void forward(HttpServletRequest req, HttpServletResponse res, String s)
{
    RequestDispatcher rd = req.getRequestDispatcher(s); 
    try 
    { 
        rd.forward(req, res); 
    } 
    catch (IOException|ServletException is) 
    { 
        throw new RuntimeException(is);
    } 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM