Java class library exceptions

Throwing exceptions in a Java Library Best Practice

I am developing an JAR library for database access. I first caught all the exceptions that are found in try blocks and handled them. But later, I thought it would be better since its a library to throw the exception to the end-programmer to catch it and do the handling. What is the best practice regarding handling exceptions in JAR files? The following is a sample code from my JAR, and as you can see there are many exceptions thrown. Is that a good practice or is there a way to do this better? (Like defining a new custom exception; if so, how is it done?) Any help regarding this is much appreciated.

 public static NConnection getNConnection(String path) throws IOException, ParserConfigurationException, SAXException

I am coding a java library for db access, and would like to know whether its best to throw the exceptions in method signatures or just handle the exception in try-catch blocks.

You should understand de difference between checked exception and runtime exception first. if path is provided by the library user, he/she needs to catch the exception when the file does not exists in the path. Also if file is not in expected format. That is you should throw all the errors in your case. That’s my opinion.

Читайте также:  Year code in php

Thank you, so as per your suggestion since all three exceptions thrown here are Checked, I’ll have to throw them and ask the end-programmer to handle.?

4 Answers 4

There is no easy answer to that and the community is somehow undecided about what is actually best practice. In a nutshell you can use checked exceptions if you want to force the caller to handle the case that something went wrong / give him a chance to recover from this exceptional state. Use runtime exceptions for any other cases like programming errors like violating contracts or such.

In my opinion it is best practice for any library to extend its own exception class, even if it does nothing more than wrapping the original exception. This way — as a client — I can read the stacktrace and easily spot in which part of my code something went wrong. E.g. if there is a DBFrameworkException it’s much more clear than the common NullPointerException.

Also see Bloch’s Effective Java item 58 for some good explanation on this topic.

All three exceptions thrown in the sample code are checked. Is it ok to throw multiple exceptions for the end-programmer to handle ? or is it frowned upon in good design principles.

I’d not recommend it as it will blow up the size of the caller’s code a lot. It’s not really bad design, just cumbersome to use as a client.

Thank you for the suggestion, So I would go with wrapping up the three exceptions in maybe a «DBFrameworkException » and throw it so the user will know where and what went wrong.

Источник

Java — Built-in Exceptions

Java defines several exception classes inside the standard package java.lang.

The most general of these exceptions are subclasses of the standard type RuntimeException. Since java.lang is implicitly imported into all Java programs, most exceptions derived from RuntimeException are automatically available.

Java defines several other types of exceptions that relate to its various class libraries. Following is the list of Java Unchecked RuntimeException.

Arithmetic error, such as divide-by-zero.

ArrayIndexOutOfBoundsException

Array index is out-of-bounds.

Assignment to an array element of an incompatible type.

IllegalArgumentException

Illegal argument used to invoke a method.

IllegalMonitorStateException

Illegal monitor operation, such as waiting on an unlocked thread.

IllegalStateException

Environment or application is in incorrect state.

IllegalThreadStateException

Requested operation not compatible with the current thread state.

IndexOutOfBoundsException

Some type of index is out-of-bounds.

NegativeArraySizeException

Array created with a negative size.

Invalid use of a null reference.

NumberFormatException

Invalid conversion of a string to a numeric format.

Attempt to violate security.

StringIndexOutOfBounds

Attempt to index outside the bounds of a string.

UnsupportedOperationException

An unsupported operation was encountered.

Following is the list of Java Checked Exceptions Defined in java.lang.

ClassNotFoundException

CloneNotSupportedException

Attempt to clone an object that does not implement the Cloneable interface.

IllegalAccessException

Access to a class is denied.

InstantiationException

Attempt to create an object of an abstract class or interface.

One thread has been interrupted by another thread.

A requested field does not exist.

NoSuchMethodException

A requested method does not exist.

Источник

Обработка исключений в Java в функциональном стиле

В данной статье автор предоставит информацию о собственной библиотеке для обработки исключений (Exception) в функциональном стиле.

Предпосылки

В Java начиная с версии 8 появились новые возможности в виде функциональных интерфейсов и потоков (Stream API). Эти возможности позволяют писать код в новом функциональном стиле без явных циклов, временных переменных, условий ветвления и проч. Я уверен что этот стиль программирования станет со временем основным для большинства Java программистов.

Однако применение функционального стиля на практике осложняется тем, что все стандартные функциональные интерфейсы из пакета java.util.function не объявляют проверяемых исключений (являются checked exception unaware).

Рассмотрим простой пример преобразования URL из строкового представления к объектам URL.

 public List urlListTraditional(String[] urls) < return Stream.of(urls) .map(URL::new) //MalformedURLException here .collect(Collectors.toList()); >

К сожалению данный код не будет компилироваться из-за того, что конструктор URL может выбросить MalformedURLException . Правильный код будет выглядеть следующим образом

 public List urlListTraditional(String[] urls) < return Stream.of(urls) .map(s -> < try < return new URL(s); >catch (MalformedURLException me) < return null; >>).filter(Objects::nonNull) .collect(Collectors.toList()); > 

Мы должны явно обработать MalformedURLException , вернуть null из лямбды, а затем отфильтровать нулевые значения в потоке. Увы, такой код на практике нивелирует все преимущества функционального подхода.

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

 public List urlListWithTry(String[] urls) < return Stream.of(urls) .map(s ->Try.of(() -> new URL(s))) .flatMap(Try::stream) .collect(Collectors.toList()); > 

Интерфейс Try

Интерфейс Try представляет собой некоторое вычисление, которое может завершиться успешно с результатом типа T или неуспешно с исключением. Try очень похож на Java Optional , который может иметь результат типа T или не иметь результата вообще (иметь null значение).

Объекты Try создаются с помощью статического фабричного метода Try.of(. ) который принимает параметром поставщика (supplier) значения типа T, который может выбросить любое исключение Exception.

 Try url = Try.of(() -> new URL("foo")); 

Каждый объект Try находится в одном из двух состояний — успеха или неудачи, что можно узнать вызывая методы Try#isSuccess() или Try#isFailure() .

Для логирования исключений подойдет метод Try#onFailure(Consumer) , для обработки успешных значений — Try#.onSuccess(Consumer) .

Многие методы Try возвращают также объект Try, что позволяет соединять вызовы методов через точку (method chaining). Вот пример как можно открыть InputStream от строкового представления URL в несколько строк без явного использования try/catch .

 Optional input = Try.success(urlString) //Factory method to create success Try from value .filter(Objects::nonNull) //Filter null strings .map(URL::new) //Creating URL from string, may throw an Exception .map(URL::openStream) //Open URL input stream, , may throw an Exception .onFailure(e -> logError(e)) //Log possible error .optional(); //Convert to Java Optional 

Интеграция Try с Java Optional и Stream

Try легко превращается в Optional при помощи метода Try#optional() , так что в случае неуспешного Try вернется Optional.empty .

Я намеренно сделал Try API восьма похожим на Java Optional API. Методы Try#filter(Predicate) и Try#map(Function) имеют аналогичную семантику соответствующих методов из Optional. Так что если Вы знакомы с Optional , то Вы легко будете работать с Try .

Try легко превращается в Stream при помощи метода Try#stream() точно так же, как это сделано для Optional#stream() . Успешный Try превращается в поток (stream) из одного элемента типа T, неуспешный Try — в пустой поток.

Фильтровать успешные попытки в потоке можно двумя способами — первый традиционный с использованием Try#filter()

 . .filter(Try::isSuccess) .map(Try::get) . 

Второй короче — при помощи Try#stream()

будет фильтровать в потоке неуспешные попытки и возвращать поток успешных значений.

Восстановление после сбоев (Recovering from failures)

Try имеет встроенные средства recover(. ) для восстановления после сбоев если вы имеете несколько стратегий для получения результата T. Предположим у Вас есть несколько стратегий:

 public T planA(); public T planB(); public T planC(); 

Задействовать все три стратегии/плана одновременно в коде можно следующим образом

 Try.of(this::planA) .recover(this::planB) .recover(this::planC) .onFailure(. ) .map(. ) . 

В данном случае сработает только первый успешный план (или ни один из них). Например, если план А не сработал, но сработал план Б, то план С не будет выполняться.

Работа с ресурсами (Try with resources)

Try имплементирует AutoCloseable интерфейс, а следовательно Try можно использовать внутри try-with-resource блока. Допустим нам надо открыть сокет, записать несколько байт в выходной поток сокета и затем закрыть сокет. Соответствующий код с использованием Try будет выглядеть следующим образом.

 try (var s = Try.of(() -> new Socket("host", 8888))) < s.map(Socket::getOutputStream) .onSuccess(out ->out.write(new byte[] )) .onFailure(e -> System.out.println(e)); > 

Сокет будет закрыт при выходе за последнюю фигурную скобку.

Выводы

Try позволяет обрабатывать исключения в функциональном стиле без явного использования конструкций try/catch/finally и поможет сделать Ваш код более коротким, выразительным, легким для понимания и сопровождения.

Надеюсь Вы получите удовольствие от использования Try

Ссылки

Автор — Сергей А. Копылов
e-mail skopylov@gmail.com

Последнее место работы
Communications Solutions CMS IUM R&D Lab
Hewlett Packard Enterprise
Ведущий специалист

Источник

Оцените статью