Java для начинающих.
Урок 1: JDK и Hello World
Урок 2: Переменные. Примитивные типы данных
Урок 3: Строки(String) в Java. Ссылочные типы данных
Урок 4: Цикл while
Урок 5: Цикл for
Урок 6: Условный оператор if
Урок 7: Ввод данных. Класс Scanner
Урок 8: Цикл do...while
Урок 9: Операторы break и continue
Урок 10: Оператор switch.
Урок 11: Массивы в Java.
Урок 12: Цикл for each, Массивы строк.
Урок 13: Многомерные массивы.
Урок 14: Классы и объекты.
Урок 15: Методы в Java.
Урок 16: Тип возвращаемого значения метода.
Урок 17: Параметры метода.
Урок 18: Инкапсуляция. Сеттеры и геттеры.
Урок 19: Ключевое слово this.
Урок 20: Конструкторы
Урок 21: Ключевое слово static.
Урок 22: Ключевое слово final.
Урок 23: StringBuilder
Урок 23(продолжение): Форматирование строк в Java
Урок 24: Класс Object и метод toString()
Урок 25: Наследование
Урок 26: Интерфейсы
Урок 27: Пакеты
Урок 28: Модификаторы доступа public, private, protected и default
Урок 29: Полиморфизм
Урок 30: Приведение примитивных типов данных.
Урок 31: Классы-обертки примитивных типов данных.
Урок 32: Восходящее и нисходящее преобразование.
Урок 33: Введение в параметризацию. (Generics)
Урок 34: Wildcards (Generics)
Урок 35: Анонимные классы
Урок 36: Чтение из файла.
Урок 37: Исключения (часть 1). Обработка исключений.
Урок 38: Исключения (часть 2). Выбрасывание исключений.
Урок 39: Исключения (часть 3). Checked и Unchecked исключения.
Урок 40: Исключения (часть 4).
Урок 41: Абстрактные классы.
Урок 42: Метод equals() и String Pool.
Урок 43: Вложенные классы.
Урок 44: Запись в файл.
Урок 45: Сериализация (часть 1).
Урок 46: Сериализация (часть 2). Сериализация массивов.
Урок 47: Сериализация (часть 3). Transient, serialVersionUID.
Урок 48: Enum (Перечисления).
Урок 49: Рекурсия.
Ссылка на youtube
Урок 1: JDK и Hello World
Урок 2: Переменные. Примитивные типы данных
Урок 3: Строки(String) в Java. Ссылочные типы данных
Урок 4: Цикл while
Урок 5: Цикл for
Урок 6: Условный оператор if
Урок 7: Ввод данных. Класс Scanner
Урок 8: Цикл do...while
Урок 9: Операторы break и continue
Урок 10: Оператор switch.
Урок 11: Массивы в Java.
Урок 12: Цикл for each, Массивы строк.
Урок 13: Многомерные массивы.
Урок 14: Классы и объекты.
Урок 15: Методы в Java.
Урок 16: Тип возвращаемого значения метода.
Урок 17: Параметры метода.
Урок 18: Инкапсуляция. Сеттеры и геттеры.
Урок 19: Ключевое слово this.
Урок 20: Конструкторы
Урок 21: Ключевое слово static.
Урок 22: Ключевое слово final.
Урок 23: StringBuilder
Урок 23(продолжение): Форматирование строк в Java
Урок 24: Класс Object и метод toString()
Урок 25: Наследование
Урок 26: Интерфейсы
Урок 27: Пакеты
Урок 28: Модификаторы доступа public, private, protected и default
Урок 29: Полиморфизм
Урок 30: Приведение примитивных типов данных.
Урок 31: Классы-обертки примитивных типов данных.
Урок 32: Восходящее и нисходящее преобразование.
Урок 33: Введение в параметризацию. (Generics)
Урок 34: Wildcards (Generics)
Урок 35: Анонимные классы
Урок 36: Чтение из файла.
Урок 37: Исключения (часть 1). Обработка исключений.
Урок 38: Исключения (часть 2). Выбрасывание исключений.
Урок 39: Исключения (часть 3). Checked и Unchecked исключения.
Урок 40: Исключения (часть 4).
Урок 41: Абстрактные классы.
Урок 42: Метод equals() и String Pool.
Урок 43: Вложенные классы.
Урок 44: Запись в файл.
Урок 45: Сериализация (часть 1).
Урок 46: Сериализация (часть 2). Сериализация массивов.
Урок 47: Сериализация (часть 3). Transient, serialVersionUID.
Урок 48: Enum (Перечисления).
Урок 49: Рекурсия.
Ссылка на youtube
YouTube
Java для начинающих
Share your videos with friends, family, and the world
👍24
new String("Hello_42") == "Hello_" + 42?
Такие вопросы о сравнении строковых и числовых констант проверяют знания о понятии пулов литералов (literal pool). Не следует путать с пулом констант класса. Виртуальная машина переиспользует один и тот же объект для строкового литерала при загрузке класса, если такой уже выделен в куче. Вот почему
Кроме самих литералов, интернирование применяется ко всем константным выражениям. К таким выражениям в этом примере относятся неявное приведение числа
Пул литералов не работает, когда явно используется оператор new. Это причина, по которой выражение
#Строки
#JVM
Такие вопросы о сравнении строковых и числовых констант проверяют знания о понятии пулов литералов (literal pool). Не следует путать с пулом констант класса. Виртуальная машина переиспользует один и тот же объект для строкового литерала при загрузке класса, если такой уже выделен в куче. Вот почему
"Hello" == "Hello"
истинно, не смотря на то что String
– ссылочный тип. Такая оптимизация возможна благодаря свойству неизменяемости (immutable) класса String
, и называется интернирование строк.Кроме самих литералов, интернирование применяется ко всем константным выражениям. К таким выражениям в этом примере относятся неявное приведение числа
42
к строке и конкатенация констант. Это делает истинным "Hello_42" == "Hello_" + 42
.Пул литералов не работает, когда явно используется оператор new. Это причина, по которой выражение
new String("Hello_42") == "Hello_" + 42
ложно.#Строки
#JVM
👍8
Forwarded from Академия Кода
HashMaps
Чтобы использовать эту структуру данных, импортируйте
Подписывайтесь на канал 👉@coddy_academy
#java
HashMap
– это встроенная структура данных, которая хранит набор пар ключ-значение. Каждый ключ действует как уникальный идентификатор для связанного с ним значения.Чтобы использовать эту структуру данных, импортируйте
HashMap
класс в верхней части программы. Подписывайтесь на канал 👉@coddy_academy
#java
👍7👎2
Параметры в Java передаются по ссылке или по значению?
Этот вопрос уходит корнями в C++ прошлое (скорее всего интервьюера), это терминология из C++. Для начала нужно разобраться в этой терминологии.
В C++ ссылка – это переменная-псевдоним для другой переменной. Меняя значение ссылки, поменяется и оригинал. В Java такого нет, легко понять это подумав например о ссылке на int.
Ссылка в Java – это нечто похожее на адрес объекта в памяти. Похожая сущность в C++ называется указатель.
Передача параметра по значению – это копирование значения в переменную-параметр метода. По ссылке – передача ссылки, то есть по сути использование той же самой переменной. Разобраться подробнее (осторожно, много C++).
В Java параметр метода – всегда копия. Значит параметры передаются всегда по значению, просто это значение может быть ссылкой на объект. Код ниже это демонстрирует.
#JVM
Этот вопрос уходит корнями в C++ прошлое (скорее всего интервьюера), это терминология из C++. Для начала нужно разобраться в этой терминологии.
В C++ ссылка – это переменная-псевдоним для другой переменной. Меняя значение ссылки, поменяется и оригинал. В Java такого нет, легко понять это подумав например о ссылке на int.
Ссылка в Java – это нечто похожее на адрес объекта в памяти. Похожая сущность в C++ называется указатель.
Передача параметра по значению – это копирование значения в переменную-параметр метода. По ссылке – передача ссылки, то есть по сути использование той же самой переменной. Разобраться подробнее (осторожно, много C++).
В Java параметр метода – всегда копия. Значит параметры передаются всегда по значению, просто это значение может быть ссылкой на объект. Код ниже это демонстрирует.
#JVM
👎6👍5
Forwarded from Академия Кода
Перегрузка в Java
Перегрузка позволяет различным методам иметь одно и то же имя, но разные сигнатуры, где сигнатура может отличаться по количеству входных параметров или по типу входных параметров, либо по обоим этим признакам.
Подписывайтесь на канал 👉@coddy_academy
#java
Перегрузка позволяет различным методам иметь одно и то же имя, но разные сигнатуры, где сигнатура может отличаться по количеству входных параметров или по типу входных параметров, либо по обоим этим признакам.
Подписывайтесь на канал 👉@coddy_academy
#java
👍10
Какие в Java бывают виды ссылок?
Кроме обычной жесткой ссылки на объект существуют варианты ссылок, которые обрабатываются сборщиком мусора особым образом. Это наследники класса
Виды ссылок в порядке убывания «жесткости»:
Обычная жесткая ссылка – любая переменная ссылочного типа. Очистится сборщиком мусора не раньше, чем станет неиспользуемой (перестанет быть доступной из GC roots, подробнее в следующих постах).
SoftReference – мягкая ссылка. Объект не станет причиной израсходования всей памяти – гарантированно будет удален до возникновения
WeakReference – слабая ссылка. Слабее мягкой. Не препятствует утилизации объекта, сборщик мусора игнорирует такие ссылки.
PhantomReference – фантомная ссылка. Используется для «предсмертной» обработки объекта: объект доступен после финализации, пока не очищен сборщиком мусора.
Подробнее можно почитать в этой статье, и как обычно в документации классов.
#JVM
Кроме обычной жесткой ссылки на объект существуют варианты ссылок, которые обрабатываются сборщиком мусора особым образом. Это наследники класса
java.lang.ref.Reference
. Все они реализуют разного рода слабые ссылки. Технически это обертки над объектом, который доступен по методу get()
, и может быть удален сборщиком мусора пока объект-обертка еще не удален. Используются они для экономии памяти, для реализации кэшей, для финализации внешних ресурсов. Например в Android слабые ссылки иногда используются для борьбы с утечкой Activity.Виды ссылок в порядке убывания «жесткости»:
Обычная жесткая ссылка – любая переменная ссылочного типа. Очистится сборщиком мусора не раньше, чем станет неиспользуемой (перестанет быть доступной из GC roots, подробнее в следующих постах).
SoftReference – мягкая ссылка. Объект не станет причиной израсходования всей памяти – гарантированно будет удален до возникновения
OutOfMemoryError
. Может быть раньше, зависит от реализации сборщика мусора.WeakReference – слабая ссылка. Слабее мягкой. Не препятствует утилизации объекта, сборщик мусора игнорирует такие ссылки.
PhantomReference – фантомная ссылка. Используется для «предсмертной» обработки объекта: объект доступен после финализации, пока не очищен сборщиком мусора.
Подробнее можно почитать в этой статье, и как обычно в документации классов.
#JVM
👍12
Из чего состоит .class-файл?
.class-файл представляет собой один скомпилированный класс. Это то, что в конечном итоге исполняет Java Virtual Machine. В .class компилируется код любого JVM языка, формат входит в спецификацию и не зависит от платформы или реализации виртуальной машины. Содержимое конкретного класса просматривают утилитой javap из стандартного набора JDK. Подробно структура файла описана на википедии, в документации и во множестве статей. Файл состоит из 10 секций, которые можно условно разбить на группы:
🔘 Свойства файла: определяющее тип файла «волшебное слово»
🔘 Пул констант – содержит все используемые имена методов и классов в специальном формате, и прочую символьную информацию. В других местах используются только ссылки на элементы пула;
🔘 Основные свойства класса: флаги доступа, имя этого класса, его предка, интерфейсов;
🔘 Внутреннее содержимое: список полей класса и байткод методов
🔘 Атрибуты класса;
Для внутренних классов тоже создаются отдельные файлы с названиями формата
#JVM
.class-файл представляет собой один скомпилированный класс. Это то, что в конечном итоге исполняет Java Virtual Machine. В .class компилируется код любого JVM языка, формат входит в спецификацию и не зависит от платформы или реализации виртуальной машины. Содержимое конкретного класса просматривают утилитой javap из стандартного набора JDK. Подробно структура файла описана на википедии, в документации и во множестве статей. Файл состоит из 10 секций, которые можно условно разбить на группы:
🔘 Свойства файла: определяющее тип файла «волшебное слово»
0xCAFEBABE
и версия формата;🔘 Пул констант – содержит все используемые имена методов и классов в специальном формате, и прочую символьную информацию. В других местах используются только ссылки на элементы пула;
🔘 Основные свойства класса: флаги доступа, имя этого класса, его предка, интерфейсов;
🔘 Внутреннее содержимое: список полей класса и байткод методов
🔘 Атрибуты класса;
Для внутренних классов тоже создаются отдельные файлы с названиями формата
OuterClass$InnerClass.class
. Если класс анонимный, вместо имени используются номера с 1.#JVM
👍12🔥2
Из чего состоит .class-файл?
.class-файл представляет собой один скомпилированный класс. Это то, что в конечном итоге исполняет Java Virtual Machine. В .class компилируется код любого JVM языка, формат входит в спецификацию и не зависит от платформы или реализации виртуальной машины. Содержимое конкретного класса просматривают утилитой javap из стандартного набора JDK. Подробно структура файла описана на википедии, в документации и во множестве статей. Файл состоит из 10 секций, которые можно условно разбить на группы:
🔘 Свойства файла: определяющее тип файла «волшебное слово»
🔘 Пул констант – содержит все используемые имена методов и классов в специальном формате, и прочую символьную информацию. В других местах используются только ссылки на элементы пула;
🔘 Основные свойства класса: флаги доступа, имя этого класса, его предка, интерфейсов;
🔘 Внутреннее содержимое: список полей класса и байткод методов
🔘 Атрибуты класса;
Для внутренних классов тоже создаются отдельные файлы с названиями формата
#JVM
.class-файл представляет собой один скомпилированный класс. Это то, что в конечном итоге исполняет Java Virtual Machine. В .class компилируется код любого JVM языка, формат входит в спецификацию и не зависит от платформы или реализации виртуальной машины. Содержимое конкретного класса просматривают утилитой javap из стандартного набора JDK. Подробно структура файла описана на википедии, в документации и во множестве статей. Файл состоит из 10 секций, которые можно условно разбить на группы:
🔘 Свойства файла: определяющее тип файла «волшебное слово»
0xCAFEBABE
и версия формата;🔘 Пул констант – содержит все используемые имена методов и классов в специальном формате, и прочую символьную информацию. В других местах используются только ссылки на элементы пула;
🔘 Основные свойства класса: флаги доступа, имя этого класса, его предка, интерфейсов;
🔘 Внутреннее содержимое: список полей класса и байткод методов
🔘 Атрибуты класса;
Для внутренних классов тоже создаются отдельные файлы с названиями формата
OuterClass$InnerClass.class
. Если класс анонимный, вместо имени используются номера с 1.#JVM
🔥4👍2
Когда изучаешь Java, в ход идет всё: книжки, видео с Ютюба и комменты на
Хабре. И все же системные знания и практику тяжело заменить информацией из интернета.
В KATA Academy можно выучиться на Java-разработчика бесплатно, а
заплатить уже после трудоустройства — это прописано в договоре.
👉 Что это за модель и чем отличается от кредита:
— мы инвестируем в своих учеников: бесплатно обучаем их, а затем получаем процент от зарплаты разработчиков;
— нам не все равно, в кого вкладывать деньги — чтобы попасть на курсы,
нужно пройти отбор и выполнить тестовое;
— мы развиваем навыки ребят и после курсов: проводим выездные
мероприятия и мастер-классы — и доходы наших ребят растут;
— мы не зависим от банков и их рассрочек — кризис не повлиял на
доступность курсов.
С самого начала у нас была тактика: «После обучения в KATA Academy
выпускники получают работу, а не бумажку о том, что их пытались учить» — и мы ее придерживаемся.
Переходи по ссылке и оставляй заявку — пришлем тестовое задание.
Хабре. И все же системные знания и практику тяжело заменить информацией из интернета.
В KATA Academy можно выучиться на Java-разработчика бесплатно, а
заплатить уже после трудоустройства — это прописано в договоре.
👉 Что это за модель и чем отличается от кредита:
— мы инвестируем в своих учеников: бесплатно обучаем их, а затем получаем процент от зарплаты разработчиков;
— нам не все равно, в кого вкладывать деньги — чтобы попасть на курсы,
нужно пройти отбор и выполнить тестовое;
— мы развиваем навыки ребят и после курсов: проводим выездные
мероприятия и мастер-классы — и доходы наших ребят растут;
— мы не зависим от банков и их рассрочек — кризис не повлиял на
доступность курсов.
С самого начала у нас была тактика: «После обучения в KATA Academy
выпускники получают работу, а не бумажку о том, что их пытались учить» — и мы ее придерживаемся.
Переходи по ссылке и оставляй заявку — пришлем тестовое задание.
👎8👍4
Для чего используется оператор assert?
Assert (Утверждение) — это специальная конструкция, позволяющая проверять предположения о значениях произвольных данных в произвольном месте программы. Утверждение может автоматически сигнализировать об обнаружении некорректных данных, что обычно приводит к аварийному завершению программы с указанием места обнаружения некорректных данных.
Утверждения существенно упрощают локализацию ошибок в коде. Даже проверка результатов выполнения очевидного кода может оказаться полезной при последующем рефакторинге, после которого код может стать не настолько очевидным и в него может закрасться ошибка.
Обычно утверждения оставляют включенными во время разработки и тестирования программ, но отключают в релиз-версиях программ.
Т.к. утверждения могут быть удалены на этапе компиляции либо во время исполнения программы, они не должны менять поведение программы. Если в результате удаления утверждения поведение программы может измениться, то это явный признак неправильного использования assert. Таким образом, внутри assert нельзя вызывать методы, изменяющие состояние программы, либо внешнего окружения программы.
В Java проверка утверждений реализована с помощью оператора
Assert (Утверждение) — это специальная конструкция, позволяющая проверять предположения о значениях произвольных данных в произвольном месте программы. Утверждение может автоматически сигнализировать об обнаружении некорректных данных, что обычно приводит к аварийному завершению программы с указанием места обнаружения некорректных данных.
Утверждения существенно упрощают локализацию ошибок в коде. Даже проверка результатов выполнения очевидного кода может оказаться полезной при последующем рефакторинге, после которого код может стать не настолько очевидным и в него может закрасться ошибка.
Обычно утверждения оставляют включенными во время разработки и тестирования программ, но отключают в релиз-версиях программ.
Т.к. утверждения могут быть удалены на этапе компиляции либо во время исполнения программы, они не должны менять поведение программы. Если в результате удаления утверждения поведение программы может измениться, то это явный признак неправильного использования assert. Таким образом, внутри assert нельзя вызывать методы, изменяющие состояние программы, либо внешнего окружения программы.
В Java проверка утверждений реализована с помощью оператора
assert
, который имеет форму: [Выражение типа boolean];
или assert [Выражение типа boolean] : [Выражение любого типа, кроме void];
Во время выполнения программы в том случае, если поверка утверждений включена, вычисляется значение булевского выражения, и если его результат false
, то генерируется исключение java.lang.AssertionError
. В случае использования второй формы оператора assert выражение после двоеточия задаёт детальное сообщение о произошедшей ошибке (вычисленное выражение будет преобразовано в строку и передано конструктору AssertionError
).👍8
События последнего месяца изменили рынок труда. Часть компаний приостановили подбор сотрудников, другие распустили команду, а третьи наоборот активно нанимают. Оценить масштаб перемен пока сложно. Чтобы это сделать, AGIMA проводит круглый стол.
14 апреля в прямом эфире эксперты из Альфа-Банка, Tochka, Хабра, HeadHunter, Kaspersky и другие разберутся, чего ждать разработчикам:
- кого и где сокращают;
- какие компании начали активно нанимать;
- что будет с зарплатами;
- что делать уехавшим разработчикам;
- как компании помогают сотрудникам пережить кризис.
Цель встречи — найти тенденции в найме и дать прогнозы. Полезно будет для веб- и мобильных разработчиков, тимлидов, QA, DevOps.
Регистрируйтесь!
14 апреля в прямом эфире эксперты из Альфа-Банка, Tochka, Хабра, HeadHunter, Kaspersky и другие разберутся, чего ждать разработчикам:
- кого и где сокращают;
- какие компании начали активно нанимать;
- что будет с зарплатами;
- что делать уехавшим разработчикам;
- как компании помогают сотрудникам пережить кризис.
Цель встречи — найти тенденции в найме и дать прогнозы. Полезно будет для веб- и мобильных разработчиков, тимлидов, QA, DevOps.
Регистрируйтесь!
👍3
Можем ли мы перегружать статические методы?
Ответ - да. У нас может быть два или более статических метода с одинаковым именем, но с разными входными параметрами.
Можем ли мы перегрузить методы, которые отличаются только ключевым словом static?
Мы не можем перегрузить два метода в Java, если они отличаются только ключевым словом static (количество параметров и типы параметров одинаковы).
Можем ли мы перегрузить main() в Java?
Как и другие статические методы, мы можем перегрузить main() в Java.
#вопросыссобеседований
Ответ - да. У нас может быть два или более статических метода с одинаковым именем, но с разными входными параметрами.
Можем ли мы перегрузить методы, которые отличаются только ключевым словом static?
Мы не можем перегрузить два метода в Java, если они отличаются только ключевым словом static (количество параметров и типы параметров одинаковы).
Можем ли мы перегрузить main() в Java?
Как и другие статические методы, мы можем перегрузить main() в Java.
#вопросыссобеседований
👍7
Сколько памяти занимает объект?
Размер экземпляров ссылочных типов, как и примитивов, зависит от конкретной реализации JVM и параметров ее запуска. Обычно в вопросе подразумевается самая популярная машина – HotSpot от Oracle.
Размеры полей-примитивов бывают больше чем необходимо, например в целях выравнивания (alignment). Из-за того же выравнивания между полями в памяти могут возникать пустоты.
Как говорилось ранее, ссылка в Java – не то же самое что указатель в C++, это не адрес в памяти. Из-за этого размер поля-ссылки может не совпадать с размером машинного слова, например когда HotSpot использует оптимизацию «сжатие ссылок» (Compressed OOP).
Кроме полей и промежутков, каждый объект в HotSpot начинается с заголовка – runtime-метаинформации. Заголовок занимает от 8 до 16 байт.
В общем можно только сказать, что размер объекта строго больше суммы размеров его полей. Примерный размер конкретного объекта измеряется средствами инструментации.
#JVM
Размер экземпляров ссылочных типов, как и примитивов, зависит от конкретной реализации JVM и параметров ее запуска. Обычно в вопросе подразумевается самая популярная машина – HotSpot от Oracle.
Размеры полей-примитивов бывают больше чем необходимо, например в целях выравнивания (alignment). Из-за того же выравнивания между полями в памяти могут возникать пустоты.
Как говорилось ранее, ссылка в Java – не то же самое что указатель в C++, это не адрес в памяти. Из-за этого размер поля-ссылки может не совпадать с размером машинного слова, например когда HotSpot использует оптимизацию «сжатие ссылок» (Compressed OOP).
Кроме полей и промежутков, каждый объект в HotSpot начинается с заголовка – runtime-метаинформации. Заголовок занимает от 8 до 16 байт.
В общем можно только сказать, что размер объекта строго больше суммы размеров его полей. Примерный размер конкретного объекта измеряется средствами инструментации.
#JVM
👍7
Программа на Java, убирающая все переносы в строке
Для замены всех переносов («\n») можно использовать функцию
Таким образом с помощью функции
#вопросыссобеседований
Для замены всех переносов («\n») можно использовать функцию
replace()
. String replace() возвращает новый объект String, который содержит ту же последовательность символов, что и исходная строка, но с замененным символом.Таким образом с помощью функции
replace()
можно заменять любые символы в строке на нужные.#вопросыссобеседований
👍10👎5
Media is too big
VIEW IN TELEGRAM
Уроки Java с нуля
- Введение и установка. Что пишут на Java
- Условные операторы If, Else If, Switch case
- Циклы For, While, Do while
- Массивы. Перебор массива
- Методы, как их писать и что делают
- Работа со строками. Методы строк
- Введение в ООП. Создание класса. Конструкторы. This
- Основы ООП. Наследование
https://www.youtube.com/playlist?list=PLVfMKQXDAhGVWEKi2wKx4y-yNLk7QKam3
- Введение и установка. Что пишут на Java
- Условные операторы If, Else If, Switch case
- Циклы For, While, Do while
- Массивы. Перебор массива
- Методы, как их писать и что делают
- Работа со строками. Методы строк
- Введение в ООП. Создание класса. Конструкторы. This
- Основы ООП. Наследование
https://www.youtube.com/playlist?list=PLVfMKQXDAhGVWEKi2wKx4y-yNLk7QKam3
👍4👎1