JavaRush /Java блог /Random /Кофе-брейк #183. Что такое проверяемое и непроверяемое ис...

Кофе-брейк #183. Что такое проверяемое и непроверяемое исключение в Java. Как работает абстракция в Java

Статья из группы Random

Что такое проверяемое и непроверяемое исключение в Java

Источник: Medium Прочитав эту статью, вы узнаете о разнице между проверяемыми и непроверяемыми исключениями, а также о том, что нужно делать при работе с этими типами исключений. Кофе-брейк #183. Что такое проверяемое и непроверяемое исключение в Java. Как работает абстракция в Java - 1Для начала давайте рассмотрим проверяемые исключения. Это тип исключений, которые проверяются во время компиляции. Например, мы используем класс FileReader в классе Checked, чтобы попытаться прочитать файл test.json. Если вы используете IDE, то увидите предупреждение, подобное приведенному на изображении ниже исключению java.io.FileNotFoundException. А если вы не используете IDE, то столкнетесь с ошибкой при компиляции. Кофе-брейк #183. Что такое проверяемое и непроверяемое исключение в Java. Как работает абстракция в Java - 2

public class Checked {

    public static void main(String[] args) {

        FileReader fileReader = new FileReader("test.json");
    }
}
Java предупреждает нас, что при создании нового объекта FileReader может возникнуть исключение, если файл test.json не существует. Этот код указывает на то, что нам нужно обработать исключение, которое будет выдано, если этот файл не найдется. То есть, Java требует, чтобы вы обработали это исключение, прежде чем ваша программа сможет работать, иначе ваше приложение не будет скомпилировано. Если бы эта ошибка была непроверяемым исключением, то вы могли бы скомпилировать свое приложение. Правда тут есть нюансы, которые мы обсудим чуть позже. Итак, как избавиться от ошибки и скомпилировать нашу программу? Здесь у нас есть два решения. В первом мы можем заключить блок кода, где возникает ошибка, в блок try-catch и обработать FileNotFoundException.

public class Checked {

    public static void main(String[] args) {

        try {
            FileReader fileReader = new FileReader("test.json");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}
После добавления try-catch мы видим, что Java больше не выдает ошибку компиляции. В дальнейшем мы можем настроить поведение программы при возникновении подобной ситуации (например, ведение журнала). Другой вариант решения состоит в использовании ключевого слова throw, которое укажет, что наш код будет генерировать исключение.

public class Checked {

    public static void main(String[] args) throws FileNotFoundException {

        FileReader fileReader = new FileReader("test.json");
    }
}
В данном решении сгенерированное исключение не перехватывается ни в одном из написанных нами блоков catch, и Java обрабатывает его. И здесь вы не увидите ошибки компиляции. Теперь давайте посмотрим на непроверяемые исключения. В отличие от проверяемых исключений, непроверяемые исключения не вызывают ошибки во время компиляции, поэтому вы можете нормально компилировать и запускать свой код. Однако вы можете столкнуться с ошибкой во время работы приложения. Давайте посмотрим на пример кода.

public class Unchecked {

    public static void main(String[] args) {
        ArrayList<String> textList = new ArrayList<>();
        textList.add("test-1");
        textList.add("test-2");

        System.out.println(getLength(textList));
    }

    private static int getLength(ArrayList<String> textList) {
        return textList.size();
    }
}
Представим, что у нас есть функция, которая просто возвращает размер массива. Как показано выше, когда приложение запускается, оно выводит на экран 2. Кажется, здесь пока нет проблем, но если мы столкнемся с ситуацией, подобной приведенной ниже, у нас могут возникнуть некоторые трудности.

public class Unchecked {

    public static void main(String[] args) {
        System.out.println(getLength(null));
    }

    private static int getLength(ArrayList<String> textList) {
        return textList.size();
    }
}
Например, я напрямую присвоил функции getLength нулевое значение и запустил код. На экране возникла следующая ошибка:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.util.ArrayList.size()" because "textList" is null at ...
Исключение, с которым мы здесь столкнулись, было вызвано тем, что функция пыталась найти размер нулевого значения. Мы не получили никаких ошибок в компиляционной части кода (хотя некоторые продвинутые IDE могут предупреждать вас о таких ситуациях). Но когда мы запустим приложение, то есть во время выполнения, мы столкнемся с этой ошибкой, наше приложение выдаст исключение и остановится. Если мы посмотрим на примеры кода, то сможем сказать, что разница между двумя типами исключений заключается в том, что одно из них предупреждается Java во время компиляции. Исключения, с которыми мы сталкиваемся перед запуском приложения, являются проверяемыми исключениями, а остальные — непроверяемыми исключениями, с которыми мы сталкиваемся во время выполнения приложения. Я хотел бы закончить эту статью небольшой деталью: “В Java все исключения, производные от класса RuntimeException, не проверяются, а все исключения, непосредственно производные от класса Exception, являются проверяемыми исключениями”.

Что такое абстракция в Java

Источник: Usemynotes Благодаря этому руководству вы узнаете, что такое абстракция в языке Java и как работает этот процесс. Кофе-брейк #183. Что такое проверяемое и непроверяемое исключение в Java. Как работает абстракция в Java - 3Абстракция — это процесс сокрытия фоновой работы задачи и показа пользователю только релевантной или важной функции. В абстракции мы пытаемся упростить вещи, скрывая ненужные или несущественные детали и показывая пользователю только те из них, которые важны. Таким образом, для пользователя все намного упрощается. Чтобы лучше понять концепцию абстракции, давайте рассмотрим пример. Вам когда-нибудь приходилось разбирать телевизор, чтобы узнать, как он работает или как формируются изображения на экране? Я думаю, что нет. Вы никогда этого не делали. Почему? Потому что производитель этого телевизора наверняка знал, что это не важно для вас. Для вас важны только те кнопки, которые он разместил на пульте управления, с помощью которых вы регулируете громкость, переключаете каналы и так далее. Это лучший пример абстракции. Производитель скрыл ненужные функции телевизора и раскрыл только важные. Та же концепция абстракции применима и к Java. В Java мы используем ключевое слово abstract для выполнения абстракции. Также ключевое слово abstract используется для классов и методов, чтобы сделать их абстрактными.

Несколько вещей, которые нужно знать, прежде чем мы перейдем к примеру:

  • Объект абстрактного класса нельзя создать напрямую.

  • Абстрактный класс можно использовать для расширения класса, а его свойства, методы и переменные можно использовать в его подклассе (наследование).

  • Абстрактный класс может иметь любое количество абстрактных методов.

  • Абстрактные методы — это те методы, которые не имеют тела метода и заканчиваются точкой с запятой.

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

  • Если подкласс не реализует все абстрактные методы унаследованного абстрактного класса, то этот подкласс также становится абстрактным классом и не может быть создан.

Давайте посмотрим на абстракцию на примере кода.

abstract class Television {
    int volume = 50;
    int channelNumber = 34;
 
    public abstract void powerOn();
 
    public abstract void powerOff();
 
    void increaseVolume(int amount) {
        volume = volume + amount;
    }
 
    void decreaseVolume(int amount) {
        volume = volume + amount;
    }
 
    void gotoChannel(int newChannelNumber) {
        channelNumber = newChannelNumber;
    }
}
В отображенном выше примере есть класс с именем Television. Этот класс является абстрактным по своей природе, что означает, что он не может быть создан напрямую. Под созданием экземпляра мы подразумеваем создание объекта. Мы можем наследовать класс Television другому классу и реализовать все абстрактные методы, а затем создать экземпляр класса.

class MyTelevision extends Television {
    boolean powerStatus = false;
 
    public void powerOn() {
        powerStatus = true;
        System.out.println("The television is ON");
    }
 
    public void powerOff() {
        powerStatus = false;
        System.out.println("The television is OFF");
    }
}
Приведенный выше класс расширяет функциональные возможности класса Television. Теперь все, что есть в классе Television, является частью класса MyTelevision. Пользователю нужно будет только реализовать необходимые методы powerOn() и powerOff(), после чего он сможет создать экземпляр класса.

class MainClass {
    public static void main (String agmts[]) {
        MyTelevision myTv = new MyTelevision();
        myTv.powerOn();
        System.out.println("Current volume: " + myTv.volume);
        myTv.increaseVolume(20);
        System.out.println("New volume: " + myTv.volume);
    }
}
 
/* Output
The television is ON
Current volume: 50
New volume: 70
*/
Таким образом, вы можете создать любое количество подклассов, которые будут расширять класс Television, а затем вам нужно будет реализовать только важные необходимые части. А все остальные компоненты абстрактного класса работают для вас. Java предоставляет разработчикам много абстрактных классов, которые можно расширить и реализовать лишь соответствующие необходимые функции. Это сэкономит много времени и вам не придется кодировать эти классы с нуля. Надеюсь, теперь вы лучше понимаете, как достигается абстракция в Java. Спасибо за чтение.
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Игорь Попович Уровень 16
10 декабря 2022
abstract class Television { int volume = 50; int channelNumber = 34; public abstract void powerOn(); public abstract void powerOff(); void increaseVolume(int amount) { volume = volume + amount; } void decreaseVolume(int amount) { volume = volume + amount; } void gotoChannel(int newChannelNumber) { channelNumber = newChannelNumber; } } Ошибка в логике метода. Нужно вычитать значение. void decreaseVolume(int amount) { volume = volume - amount; }