Понятия "оператор" и "операнд" играют ключевую роль в построении выражений и выполнении операций.
Оператор — это специальный символ или ключевое слово, которое указывает на выполнение определенного действия. Операторы используются для выполнения операций над переменными и значениями.
В Java существует несколько типов операторов:
✔️ Арифметические операторы
✔️ Операторы присваивания
✔️ Операторы сравнения
✔️ Логические операторы
✔️ Побитовые операторы
✔️ Операторы инкремента и декремента
Операнд — это элемент, над которым оператор выполняет действие. Операнды могут быть переменными, константами или результатами других выражений.
Примеры:
👉 В выражении a + b операнды это a и b, а оператор +.
👉 В выражении x = 5 операнды это x и 5, а оператор =.
👉 В выражении count++ операнд это count, а оператор ++.
#java #operator #operand
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥3❤1
Тут разработчики не стали мудрствовать лукаво и просто использовали экземпляр
HashMap внутри HashSet. Каждый элемент HashSet хранится как ключ в этой хэш-таблице, а значение для каждого ключа установлено в фиксированное значение PRESENT, что является специальным объектом (обычно new Object()).При добавлении элемента, у него вычисляется хэш-код, определяется соответствующий бакет, и элемент добавляется в этот бакет, если он еще не присутствует (проверяется с помощью метода
equals()).При удалении вычисляется хэш-код элемента, определяется бакет, и элемент удаляется, если он присутствует в этом бакете.
Упрощённый код класса HashSet:
public class HashSet<E> implements Set<E>, Cloneable, java.io.Serializable {
// Внутренний экземпляр HashMap
private transient HashMap<E, Object> map;
// Специальный константный объект, используемый в качестве значения для всех ключей
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
return map.put(e, PRESENT) == null;
}
public boolean remove(Object o) {
return map.remove(o) == null;
}
public boolean contains(Object o) {
return map.containsKey(o);
}
// Другие методы...
}
#java #hashset #hashmap
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19❤1😁1
public class Quest {
public static void main(String[] args) {
int b = oper2() | oper3() & oper4();
System.out.println("-" + b);
}
private static byte oper2() {
System.out.print(2);
return 2;
}
private static byte oper3() {
System.out.print(3);
return 3;
}
private static byte oper4() {
System.out.print(4);
return 4;
}
}#java #quest
👍2
🎉7
class Person {
Long id;
String name;
public Person(Long id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object obj) {
System.out.print(1);
if (obj == this) {
return true;
}
if (obj instanceof Person person) {
return id.equals(person.id);
}
return false;
}
}
public class Quest {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person(1L, "Leo"));
list.add(new Person(2L, "Raph"));
list.add(new Person(3L, "Donnie"));
list.add(new Person(4L, "Mikey"));
list.contains(new Person(3L, "Shredder"));
}
}👍5❤1
🎉2❤1😁1
public class Quest {
public static void main(String[] args) {
byte b = 50;
print(b);
}
private static void print(Short num) {
System.out.println(num++);
}
}👍6
🎉1
Позволяет вставлять новые записи в таблицу или обновлять существующие, если они уже присутствуют. Это удобная операция для предотвращения дублирования данных и упрощения логики обработки записей.
Есть две опции что должно происходить при конфликте при вставке: DO UPDATE и DO NOTHING. Тут все понятно из названия, или обновить запись или ни делать ничего.
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...)
ON CONFLICT (conflict_target)
DO UPDATE SET column1 = value1, column2 = value2, ...;
conflict_target это колонка или набор колонок, которые используются для определения конфликта, обычно это первичный ключ или уникальный индекс. conflict_target можно не указывать и тогда при любом конфликте (дублируется первичный ключ, нарушение уникального индекса и тд.) сработает UPDATE или ничего.
Пример:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username TEXT UNIQUE,
email TEXT
);
INSERT INTO users (id, username, email)
VALUES (1, 'user1', 'user1@example.com')
ON CONFLICT
DO NOTHING;
INSERT INTO users (id, username, email)
VALUES (1, 'user1', 'user1@example.com')
ON CONFLICT
DO NOTHING;
Первый INSERT добавит запись, а второй ничего не сделает, так как произойдет дублирование первичного ключа.
#java #PostgreSQL #upsert #update #insert
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥2❤1
public class Quest {
public static void main(String[] args) {
Short b = 50;
inc(b);
System.out.println(b);
}
private static void inc(Short num) {
num++;
}
}👍6🎉3
Этот класс состоит из статических служебных методов для работы с объектами или проверки определенных условий перед операцией.
Класс финальный и создать его не получится, об этом позаботились разработчики:
public final class Objects {
private Objects() {
throw new AssertionError("No java.util.Objects instances for you!");
}
...
}
Метод equals для NPE-безопасного сравнения объектов:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
Метод toString для NPE-безопасного преобразования объекта в строку:
public static String toString(Object o) {
return String.valueOf(o);
}
Метод toString с дефолтным значением для случая если объект равен null:
public static String toString(Object o, String nullDefault) {
return (o != null) ? o.toString() : nullDefault;
}
Метод requireNonNull позволяет чекнуть объект на null:
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Забавные методы isNull и nonNull проверяют переменную на null и на не null:
public static boolean isNull(Object obj) {
return obj == null;
}
public static boolean nonNull(Object obj) {
return obj != null;
}
#java #Objects #NPE
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤4🥱2
Java является строго типизированным языком программирования, а это означает, то что каждое выражение и каждая переменная имеет строго определенный тип уже на момент компиляции. Однако определен механизм приведения типов (casting) - способ преобразования значения переменной одного типа в значение другого типа.
В Java существуют несколько разновидностей приведения:
✔️ Тождественное (identity). Преобразование выражения любого типа к точно такому же типу всегда допустимо и происходит автоматически.
✔️ Расширение (повышение, upcasting) примитивного типа (widening primitive). Означает, что осуществляется переход от менее емкого типа к более ёмкому. Например, от типа
byte (длина 1 байт) к типу int (длина 4 байта). Такие преобразование безопасны в том смысле, что новый тип всегда гарантировано вмещает в себя все данные, которые хранились в старом типе и таким образом не происходит потери данных. Этот тип приведения всегда допустим и происходит автоматически.✔️ Сужение (понижение, downcasting) примитивного типа (narrowing primitive). Означает, что переход осуществляется от более емкого типа к менее емкому. При таком преобразовании есть риск потерять данные. Например, если число типа
int было больше 127, то при приведении его к byte значения битов старше восьмого будут потеряны. В Java такое преобразование должно совершаться явным образом, при этом все старшие биты, не умещающиеся в новом типе, просто отбрасываются - никакого округления или других действий для получения более корректного результата не производится.✔️ Расширение объектного типа (widening reference). Означает неявное восходящее приведение типов или переход от более конкретного типа к менее конкретному, т.е. переход от потомка к предку. Разрешено всегда и происходит автоматически.
✔️ Сужение объектного типа (narrowing reference). Означает нисходящее приведение, то есть приведение от предка к потомку (подтипу). Возможно только если исходная переменная является подтипом приводимого типа. При несоответствии типов в момент выполнения выбрасывается исключение
ClassCastException. Требует явного указания типа.✔️ Преобразование к строке (to String). Любой тип может быть приведен к строке, т.е. к экземпляру класса
String.✔️ Запрещенные преобразования (forbidden). Не все приведения между произвольными типами допустимы. Например, к запрещенным преобразованиям относятся приведения от любого ссылочного типа к примитивному и наоборот (кроме преобразования к строке). Кроме того, невозможно привести друг к другу классы, находящиеся на разных ветвях дерева наследования и т.п.
При приведении ссылочных типов с самим объектом ничего не происходит, - меняется лишь тип ссылки, через которую происходит обращение к объекту.
Для проверки возможности приведения нужно воспользоваться оператором
instanceof:
Parent parent = new Child();
if (parent instanceof Child) {
Child child = (Child) parent;
}
#java #casting #upcasting #downcasting
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤1
public class Quest {
public static void main(String[] args) {
System.out.println(concat1() < concat2());
}
private static long concat1() {
long start = System.nanoTime();
String s = "";
for (int i = 0; i < 1000; i++) {
s += "-" + i;
}
return System.nanoTime() - start;
}
private static long concat2() {
long start = System.nanoTime();
StringBuilder s = new StringBuilder();
for (int i = 0; i < 1000; i++) {
s.append("-" + i);
}
return System.nanoTime() - start;
}
}#java #quest
👏3
Автоупаковка - это механизм неявной инициализации объектов классов-оберток (
Byte, Short, Integer, Long, Float, Double, Character, Boolean) значениями соответствующих им исходных примитивных типов (byte, short, int...), без явного использования конструктора класса.Автоупаковка происходит при прямом присваивании примитива классу-обертке (с помощью оператора
=), либо при передаче примитива в параметры метода (типа класса-обертки).Автоупаковке в классы-обертки могут быть подвергнуты как переменные примитивных типов, так и константы времени компиляции (литералы и
final-примитивы). При этом литералы должны быть синтаксически корректными для инициализации переменной исходного примитивного типа.Автоупаковка переменных примитивных типов требует точного соответствия типа исходного примитива типу класса-обертки. Например, попытка упаковать переменную типа
byte в Short, без предварительного явного приведения byte в short вызовет ошибку компиляции.Автоупаковка констант примитивных типов допускает более широкие границы соответствия. В этом случае компилятор способен предварительно осуществлять неявное расширение/сужение типа примитивов:
✔️ неявное расширение/сужение исходного типа примитива до типа примитива, соответствующего классу-обертке (для преобразования
int в Byte, сначала компилятор самостоятельно неявно сужает int к byte)✔️ автоупаковку примитива в соответствующий класс-обертку. Однако, в этом случае существуют два дополнительных ограничения:
a) присвоение примитива обертке может производится только оператором
= (нельзя передать такой примитив в параметры метода без явного приведения типов) b) тип левого операнда не должен быть старше чем
Character, тип правого не должен старше, чем int: допустимо расширение/сужение byte в/из short, byte в/из char, short в/из char и только сужение byte из int, short из int, char из int. Все остальные варианты требуют явного приведения типов).Дополнительной особенностью целочисленных классов-оберток, созданных автоупаковкой констант в диапазоне -128 ... +127 является то, что они кэшируются JVM. Поэтому такие обертки с одинаковыми значениями будут являться ссылками на один объект.
#java #autoboxing
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8