Генерування виключень в лямбда-виразах. Приклади
Зміст
- 1. Особливості генерування виключень в лямбда-виразах
- 2. Приклади генерування стандартного виключення в лямбда-виразі
- 3. Приклад генерування виключення, яке обробляється спеціально розробленим класом
- Зв’язані теми
Пошук на інших ресурсах:
1. Особливості генерування виключень в лямбда-виразах
Бувають випадки, коли у лямбда-виразах може виникнути виключна ситуація. У цьому випадку лямбда-вираз повинен згенерувати виключення. Генерування виключення лямбда-виразом реалізується стандартним способом з допомогою оператора throw. Фрагмент, що перевіряється у лямбда-виразі береться у блок try-catch.
Як і в методі, у лямбда-виразі можна генерувати виключення двох видів:
- наперед визначених типів Java (ArithmeticException, ArrayIndexOutOfBoundsException і т.д.);
- власноруч розроблених класів виключень.
⇑
2. Приклади генерування стандартного виключення в лямбда-виразі
2.1. Ділення двох чисел. Генерування виключення ділення на нуль
У прикладі наводиться лямбда-вираз, який повертає результат ділення двох чисел. У коді лямбда-виразу перевіряється значення дільника. Якщо це значення рівне 0, то генерується стандартне виключення ArithmeticException з відповідним повідомленням.
// Генерування виключень у лямбда-виразах // Оголосити функціональний інтерфейс interface IDivNumbers { // Оголосити метод, який ділить два числа double Division(double a, double b); } // Клас, що містить методи, які реалізують лямбда-вираз та // тестують роботу програми. public class Lambda { public static void main(String[] args) { // 1. Оголосити посилання на IDivNumbers IDivNumbers ref; // 2. Реалізувати лямбда-вираз, який ділить два числа і // при необхідності генерує виключення ref = (a, b) -> { try { // Обробити перевірку ділення на 0 if (b==0) throw new ArithmeticException("Exception: divide by zero."); return a/b; // якщо b!=0, то повернути результат ділення } catch (ArithmeticException e) { System.out.println(e.getMessage()); // Вивести повідомлення return 0.0; } }; // 3. Протестувати лямбда-вираз на виключну ситуацію double res = ref.Division(5, 0); // Exception: divide by zero. // 4. Вивести результат System.out.println("res = " + res); // res = 0.0 } }
Результат виконання програми
Exception: divide by zero. res = 0.0
⇑
2.2. Поелементне сумування масивів. Шаблонний функціональний інтерфейс. Генерування виключення в лямбда-виразі. Передача лямбда-виразу в метод
Умова задачі. Використовуючи механізм лямбда-виразів реалізувати поелементне додавання масивів узагальненого типу T. Лямбда-вираз повинен обробляти нижчевказані виключення, які генеруються у випадку, якщо масиви не відповідають заданим вимогам.
Основні вимоги до масивів:
- масиви повинні підтримувати роботу з числовими типами.
- масиви повинні мати ненульову довжину. Якщо один з масивів має нульову довжину, то згенерувати виключення EmptyArrayException. Для реалізації виключення EmptyArrayException розробити однойменний клас;
- масиви повинні мати однакову довжину. Якщо масиви мають різну довжину, то згенерувати стандартне виключення ArrayIndexOutOfBoundsException.
Лямбда-вираз повинен передаватись в метод як параметр. Для виконання цього потрібно оголосити додатковий клас з методом, який отримує лямбда-вираз в якості параметру.
У функції main() продемонструвати використання лямбда-виразів для обробки виключень.
Розв’язок. Згідно з умовою задачі у програмі потрібно ввести наступні класи та інтерфейс:
- узагальнений (шаблонний) функціональний інтерфейс ISumArrays<T>, який оперує числовим типом T. Тип інтерфейсу обмежується типом Number (усі числові типи). В інтерфейсі потрібно визначити метод SumArrays(), який отримує параметром два масиви та повертає результуючий масив;
- клас EmptyArrayException, який визначає виключення, що виникає у випадку, коли один з масивів має нульову довжину;
- клас ArrayMethod, який містить єдиний метод AddMethod(). Цей метод отримує три параметри: два масиви-доданки та лямбда-вираз у вигляді посилання на ISumArrays<T>;
- клас Lambda, в якому оголошується функція main(). У функції main() створюються тестувальні масиви для різних типів та лямбда-вираз. Ці всі дані передаються в метод AddMethod() екземпляру класу ArrayMethod.
Текст розв’язку задачі наведено нижче
// Генерування виключень у лямбда-виразах // Оголосити узагальнений функціональний інтерфейс, // який оперує типом T. Тип T обмежується числовими типами (Number). interface ISumArrays<T extends Number> { // Метод, що отримує два масиви та повертає масив T[] SumArrays(T[] array1, T[] array2); } // Клас, що визначає виключення, яке виникає коли один з масивів // має нульову довжину. Клас повинен бути успадкований з класу Exception class EmptyArrayException extends Exception { // Конструктор класу EmptyArrayException(String message) { super(message); // викликати конструктор суперкласу } } // Узагальнений клас, що містить метод, в який передається лямбда-вираз. // Для просумовування елементів метод викликає інший метод SumArrays() // інтерфейсу ISumArrays. class ArrayMethod<T extends Number> { // Метод, що отримує лямбда-вираз в якості параметру public T[] AddMethod(T[] array1, T[] array2, ISumArrays<T> ref) { T[] array3 = null; array3 = ref.SumArrays(array1, array2); // повернути суму масивів return array3; } } // Клас, що містить методи, які реалізують лямбда-вираз та // тестують роботу програми. public class Lambda { public static void main(String[] args) { // 1. Реалізація для масивів типу Double // 1.1. Оголосити посилання на інтерфейс ISumArrays<T> ISumArrays<Double> ref; // 1.2. Сформувати лямбда-вираз з прив'язкою до типу Double ref = (array1, array2) -> { try { // Перевірка на нульову довжину масивів if (array1.length==0) throw new EmptyArrayException("array1 is empty."); if (array2.length==0) throw new EmptyArrayException("array2 is empty."); // Перевірка на рівність елементів в масивах if (array1.length!=array2.length) throw new ArrayIndexOutOfBoundsException("Arrays are not equal"); } catch (EmptyArrayException e) { System.out.println(e.getMessage()); return null; } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.getMessage()); return null; } // Код просумовування масивів Double[] array3 = new Double[array1.length]; for (int i=0; i<array1.length; i++) array3[i] = array1[i] + array2[i]; return array3; }; // 1.3. Оголосити два масиви різної довжини Double[] AD1 = { 2.0, 1.5, 3.8 }; Double[] AD2 = { 1.1, 4.0 }; // 1.4. Викликати метод AddMethod() з класу ArrayMethod<T> Double[] AD3; ArrayMethod<Double> obj = new ArrayMethod<Double>(); AD3 = obj.AddMethod(AD1, AD2, ref); // 1.5. Вивести масив AD3 if (AD3 != null) { System.out.println("Array AD3:"); for (int i=0; i<AD3.length; i++) System.out.print(" " + AD3[i]); System.out.println(); } // 2. Реалізація масивів однакової довжини // 2.1. Оголосити масиви, що мають однаковий розмір Double[] AD4 = { 1.5, 2.5, 3.3 }; Double[] AD5 = { 2.0, 1.8, 1.9 }; // 2.2. Викликати метод просумовування масивів AD3 = obj.AddMethod(AD4, AD5, ref); // 2.3. Вивести масив AD3 if (AD3 != null) { System.out.println("Array AD3:"); for (int i=0; i<AD3.length; i++) System.out.print(" " + AD3[i]); System.out.println(); } } }
Результат роботи програми
Arrays are not equal Array AD3: 3.5 4.3 5.199999999999999
⇑
3. Приклад генерування виключення, яке обробляється спеціально розробленим класом
Умова задачі. Розробити клас NegativeRootException, який обробляє виключення що виникає при спробі взяття кореня квадратного з від’ємного числа. Реалізувати лямбда-вираз, який обчислює площу трикутника за довжинами його сторін. Розрахунок ведеться за формулою Герона. Якщо у формулі Герона виникає корінь з від’ємного числа (трикутник не існує), то згенерувати виключення NegativeRootException. Виключення повинно генеруватись в лямбда-виразі.
Розв’язок. Текст розв’язку задачі наступний.
// Генерування виключень у лямбда-виразах // Оголосити функціональний інтерфейс interface INegativeRoot { // Оголосити метод, визначає площу трикутника за його сторонами double AreaTriangle(double a, double b, double c); } // Створити клас виключення, який обробляє корінь квадратний з від'ємного числа // Таке виключення є контрольоване (checked). class NegativeRootException extends Exception { // Конструктор класу NegativeRootException(String message) { super(message); // викликати конструктор суперкласу Exception } } // Клас, що містить методи, які реалізують лямбда-вираз та // тестують роботу програми. public class Lambda { @SuppressWarnings("finally") public static void main(String[] args) { // 1. Оголосити посилання на INegativeRoot INegativeRoot ref = null; // 2. Реалізувати лямбда-вираз, який обчислює площу // трикутника за формулою Герона ref = (a, b, c) -> { double p = (a+b+c)/2; // півпериметер double t = p*(p-a)*(p-b)*(p-c); // підкореневий вираз try { // перевірка на від'ємний корінь з генеруванням виключення if (t<0) { t=0; throw new NegativeRootException("Exception: negative root."); } return Math.sqrt(t); } catch (NegativeRootException e) { t = 0; System.out.println(e.getMessage()); } finally { // Блок, який виконується завжди return t; } }; // 3. Протестувати лямбда-вираз на виключну ситуацію double res = ref.AreaTriangle(1, 1, 5); // Exception: negative root. // 4. Вивести результат System.out.println("res = " + res); // res = 0.0 } }
Після виконання програма видасть наступний результат
Exception: negative root. res = 0.0
⇑
Зв’язані теми
- Лямбда-вирази. Основні поняття. Функціональний інтерфейс. Приклади
- Лямбда-вирази для узагальнених функціональних інтерфейсів. Приклади
- Передача лямбда-виразу в метод в якості параметру. Приклади
- Доступ до елементів класу з лямбда-виразу. Захоплення змінних у лямбда-виразах. Приклади
⇑