JavaRush /Курсы /Модуль 2. Java Core /Стандартные интерфейсы

Стандартные интерфейсы

Модуль 2. Java Core
4 уровень , 6 лекция
Открыта

— Привет, Амиго! Сейчас я тебе расскажу про два интерфейса – InputStream и OutputStream. Объявлены они как абстрактные классы, но если начать разбираться, то можно увидеть, что по своей сути – это интерфейсы. Почти все их методы абстрактные, кроме нескольких незначительных методов. Очень похожи на нашего «телохранителя», которого мы рассматривали.

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

— Хорошо. Так что это за интерфейсы?

— Сейчас расскажу.

Есть такая интересная вещь в Java как «поток». Поток – это очень простая сущность. И его простота есть залог очень мощного механизма обмена данными. Потоки бывают двух видов: поток для чтения и поток для записи.

В поток для записи, как ты уже, наверное, догадался, можно записывать данные. Для этого у него есть метод write(). Из потока для чтения можно данные читать. Для этого у него есть метод read().

InputStream – это интерфейс потока чтения, описывающий такую способность: «из меня можно читать байты».

А OutputStream– это, соответственно, интерфейс потока записи, описывающий способность: «в меня можно записывать байты».

— И это все?

— Фактически да. Но все дело в том, что в Java есть очень много классов, которые умеют работать с интерфейсами InputStream и OutputStream. Например, ты хочешь прочитать файл с диска и вывести его содержимое на экран. Нет ничего проще.

Для того, чтобы прочитать данные из файла на диске, есть специальный класс FileInputStream, который реализует интерфейс InputStream. Хочешь записать прочитанные данные в другой файл? Для этого есть класс FileOutputStream, который реализует интерфейс OutputStream. Вот как выглядит код копирования [данных одного] файла в другой.

Код
public static void main(String[] args) throws IOException
{
 InputStream inStream = new FileInputStream("c:/source.txt");
 OutputStream outStream = new FileOutputStream("c:/result.txt");

 while (inStream.available() > 0)
 {
  int data = inStream.read(); //читаем один байт из потока для чтения
  outStream.write(data); //записываем прочитанный байт в другой поток.
 }

 inStream.close(); //закрываем потоки
 outStream.close();
}

Представь, что мы написали класс, и добавили ему способности InputStream и OutputStream.

Если мы корректно реализовали поддержку этих интерфейсов, то объекты нашего класса теперь можно сохранить в файл на диске. Просто вычитав их содержимое через метод read. Или загрузить из файла, создав объект и записав в него содержимое файла через метод write.

— А можно пример?

— Можно.

Код Описание
class MyClass
{
private List<Integer> list =
 new ArrayList<>(Arrays.asList(111, 222, 333));
}
Для простоты представим, что наш класс содержит в себе один объект – ArrayList типа Integer. Наполним список тестовыми данными.

Теперь добавим в него методы read и write

Код Описание
class MyClass
{
private List<Integer> list =
 new ArrayList<>(Arrays.asList(111, 222, 333));

public void write(int data)
{
list.add(data);
}

public int read()
{
int first = list.get(0);
list.remove(0);
return first;
}

public int available()
{
return list.size();
}
}
Теперь у нас в классе реализован метод read, который позволяет последовательно вычитать все содержимое нашего списка list.

И метод write, который позволяет записывать в наш list значения.

Это, конечно, не реализация интерфейсов InputStream и OutputStream, но очень похоже.

— Да, это понятно. А как все-таки сохранить содержимое такого объекта в файл?

— Давай я напишу тебе пример:

Запись объекта MyClass в файл
public static void main(String[] args) throws IOException
{
 MyClass myObject = new MyClass();
 OutputStream outStream = new FileOutputStream ("c:/my-object-data.txt");

 while (myObject.available() > 0)
 {
  int data = myObject.read(); //читаем один int из потока для чтения
  outStream.write(data); //записываем прочитанный int в другой поток.
 }

 outStream.close();
}
16
Задача
Java Core, 4 уровень, 6 лекция
Недоступна
Куриная фабрика
Создадим международную куриную фабрику, заселим её курами разного происхождения. Создадим каталог, в котором будем указывать национальность курицы будем подсчитывать, сколько яиц в месяц они несут. Как это сделать? С помощью абстрактных классов и наследования, разумеется.
Чтение объекта MyClass из файла
public static void main(String[] args) throws IOException
{
 InputStream inStream = new FileInputStream("c:/my-object-data.txt");
 MyClass myObject = new MyClass();

 while (inStream.available() > 0)
 {
  int data = inStream.read(); //читаем один int из потока для чтения
  myObject.write(data); //записываем прочитанный int в другой поток.
 }

 inStream.close(); //закрываем потоки
}

— Ух ты! Действительно, очень похоже на работу с InputStream/OutputStream. Потоки – это крутая вещь!

— А то!

Комментарии (8)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Олег Уровень 109 Expert
5 февраля 2024
Этот стиль общения с Амиго только отвлекает от материала постоянными Ух ты или Круто или что-то подобное. Хорошо еще что не LOL )). Почему абстрактные классы InputStream \OutputStream называют интерфейсами не ясно.
Владимир Кругман Уровень 51 Expert
27 августа 2023
Какая-то бестолковая лекция..
Олег Уровень 79 Expert
1 июня 2023
Дааааа.... Зачем время тратить на эту лекцию... для меня не понятно. Что то пыжаться с какими то примерами???? Зачем???
Юрий Кохно Уровень 62 Expert
10 марта 2023
В Java есть несколько стандартных интерфейсов, которые предоставляют различную функциональность и могут быть использованы для решения различных задач. Рассмотрим некоторые из них: Iterable: Определяет метод iterator(), который позволяет проходить по элементам коллекции. Используется в цикле for-each. Comparable: Определяет метод compareTo(), который позволяет сравнивать объекты и упорядочивать их. Используется в сортировке. Runnable: Определяет метод run(), который запускает отдельный поток выполнения. Используется для параллельной работы. Serializable: Интерфейс, который позволяет сохранять состояние объекта в виде последовательности байтов и восстанавливать его в последующем. Используется для сохранения объектов в файлы и передачи по сети. Cloneable: Интерфейс, который позволяет создавать копию объекта. Используется для создания глубоких копий объектов. List, Set, Map: Интерфейсы, определяющие структуры данных. List – это упорядоченная коллекция элементов с возможностью повторяющихся элементов. Set – это неупорядоченная коллекция элементов без повторений. Map – это коллекция пар «ключ-значение», где каждый ключ уникален. Function: Интерфейс, который позволяет определить функцию, которая принимает один аргумент и возвращает результат. Используется для функционального программирования. Predicate: Интерфейс, который позволяет определить предикат, который принимает один аргумент и возвращает булево значение. Используется для функционального программирования. Это только некоторые из стандартных интерфейсов в Java. Все они имеют свои особенности и могут быть использованы для решения различных задач в разных областях программирования.
Денис Уровень 108 Expert
8 апреля 2022
"Очень похожи на нашего «телохранителя», которого мы рассматривали." Про каких телохранителях речь?
Andrei Уровень 34
29 июня 2022
Это думаю статья написанная в разделе статьи
Тарас Ш. Уровень 72
30 сентября 2022
Судя по стилю - это из Квеста (Игровой стиль подачи информации на JR), а там свои примеры. Статьи в разделе Статьи пишутся обычным стилем, без обращений героев друг к другу.
Sergey Drogunov Уровень 111 Expert
4 апреля 2022
Не очень нравиться хоть и для примера называть InputSteam/OutputStream интерфейсами. И не увидел ответа на интригу. (Заинтриговать получилось)


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