2016-03-11 1 views
2

Итак, я начал играть с Java 8 потоками/лямбда-выражениями и столкнулся с интересной проблемой, и я не совсем уверен, как ее решить. Итак, вот я, прошу вас о помощи.Java 8 - эффективные конечные переменные, lambdas и try/catch/finally block

Пример кода в вопросе:

public void insertBlankPages(File inputFile, String outputFile, final int OFFSET) { 
    PDDocument newDocument; 
    PDDocument oldDocument; 
    try { 
     newDocument = createNewDocument(); 
     oldDocument = createOldDocument(inputFile); 
     List<PDPage> oldPages = getAllPages(oldDocument); 

     oldPages.stream() 
       .limit(oldPages.size() - OFFSET) 
       .forEach(page -> { 
        newDocument.addPage(page); 
        newDocument.addPage(new PDPage(page.getMediaBox())); 
       }); 

     newDocument.save(outputFile); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (COSVisitorException e) { 
     e.printStackTrace(); 
    } finally { 
     newDocument.close(); 
     oldDocument.close(); 
    } 
} 

С выше кода, компилятор жалуется на вызов, чтобы закрыть() в блоке, наконец. Ошибка: «Переменная newDocument, возможно, не была инициализирована». То же самое для oldDocument.

Естественно, я иду вперед и инициализировать переменные следующим образом:

PDDocument newDocument = null; 
PDDocument oldDocument = null; 

Теперь я получаю ошибку компилятора «Variable используется в лямбда-выражения должно быть эффективно окончательным».

Как это сделать?

Методы createNewDocument и createOldDocument выдают исключение, поэтому вызовы должны быть в блоке try/catch. Мне также нужно закрыть документы в блоке finally.

У меня должна быть возможность обойти эту проблему с помощью try-in-resources. Но мне интересно узнать, есть ли для этого какое-то другое правильное решение.

Спасибо.

ответ

2

Правильное решение - это попытка использования ресурсов.

Без этого, вам нужно вручную гнездятся еще немного попробовать /, наконец, блоки:

try { 
    PDDocument newDocument = createNewDocument(); 
    try{   
     PDDocument oldDocument = createOldDocument(inputFile); 
     try{ 
      // ..... 
     } 
     finally { oldDocument.close() } 
    } 
    finally{ newDocument.close(); } 
} 
catch (IOException e) { 
    e.printStackTrace(); 
} 
0

Простой Обходной использовать массив, который сам по себе является окончательным, так что вы можете ссылаться на него в лямбда, но его содержимое может быть изменено.

Этот код является по существу такой же как ваш, но не имеет никаких ошибок компиляции:

public void insertBlankPages(File inputFile, String outputFile, final int OFFSET) { 
    PDDocument[] newDocument = new PDDocument[1]; // automatically filled with a null 
    PDDocument oldDocument = null; 
    try { 
     newDocument[0] = createNewDocument(); 
     oldDocument = createOldDocument(inputFile); 
     List<PDPage> oldPages = getAllPages(oldDocument); 

     oldPages.stream() 
       .limit(oldPages.size() - OFFSET) 
       .forEach(page -> { 
        newDocument[0].addPage(page); 
        newDocument[0].addPage(new PDPage(page.getMediaBox())); 
       }); 

     newDocument[0].save(outputFile); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (COSVisitorException e) { 
     e.printStackTrace(); 
    } finally { 
     if (newDocument[0] != null) 
      newDocument[0].close(); 
     if (oldDocument != null) 
      oldDocument.close(); 
    } 
} 
+0

Это приведет к исключению NullPointerException, если 'createNewDocument' генерирует исключение. – Thilo

+0

@ Тило так что? это не касается отладки его кода, это отвечает «как я могу справиться с окончательным окончанием». Когда он получит NPE, он выяснит, что ему нужно проверить значение null. Я отредактировал код, чтобы обработать это, хотя – Bohemian

+0

Почему бы просто не сделать его «final» (и использовать try-in-resources)? Кажется, это было сделано специально для подобных случаев. – Thilo

1

Спасибо всем за идеи. Похоже, что нет «хорошего» способа сделать это без использования ресурсов try-with-resources. Вот пример использования try-with-resources.

public void insertBlankPages(File inputFile, String outputFile, final int OFFSET) { 
    try (PDDocument newDocument = createNewDocument(); 
     PDDocument oldDocument = createOldDocument(inputFile)) { 

     List<PDPage> oldPages = getAllPages(oldDocument); 

     oldPages.stream() 
       .limit(oldPages.size() - OFFSET) 
       .forEach(page -> { 
        newDocument.addPage(page); 
        newDocument.addPage(new PDPage(page.getMediaBox())); 
       }); 

     newDocument.save(outputFile); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (COSVisitorException e) { 
     e.printStackTrace(); 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^