Что напечатает следующий код?
public classPoint { private final int x; private final int y; publicPoint (int x, int y) { this.x = x; this.y = y; } public booleanequals (Point other) { if (this == other) return true; return this.x == other.x && this.y == other.y; } public inthashCode () { return Objects.hash(x, y); } } Point p1 = new Point(1, 2); Point p2 = new Point(1, 2); Point p3 = new Point(2022, 2023); System.out.println(p1.equals(p2)); System.out.println(p1.equals(p3)); Set<Point> set = new HashSet<>(); set.add(p1); System.out.println(set.contains(p2)); System.out.println(set.contains(p3));
true false false false
Метод boolean equals(Point other) не переопределяет Object.equals,
а перегружает его.
Плюс не определен метод hashcode(), что осложняет нахождение объекта в HashSet.
Какое свойство equals нарушается в этом случае? (если нарушается)
public classPoint { private final int x; private final int y; publicPoint (int x, int y) { this.x = x; this.y = y; } // getters@Override public booleanequals (Object o) { if (this == o) return true; if (!(o instanceof Point)) return false; Point other = (Point) o; return x == other.x && y == other.y; } } public classColourPoint extendsPoint { private final String colour; publicColourPoint (int x, int y, String colour) { super(x, y); this.colour = colour; } // getters@Override public booleanequals (Object o) { if (this == o) return true; if (!(o instanceof ColourPoint)) return false; ColourPoint other = (ColourPoint) o; return this.getX() == other.getX() && this.getY() == other.getY() && this.colour.equals(other.colour); } }
Симметрия
Что будет выведено в консоль?
classA {} classB extendsA {} classC extendsB {} classD extendsC {} public classLoader { public static voidmain (String[] args) { B b = new C(); A a = b; if (a instanceof A) System.out.println("A"); if (a instanceof B) System.out.println("B"); if (a instanceof C) System.out.println("C"); if (a instanceof D) System.out.println("D"); } }
A B C
Что будет выведено в консоль?
classSuperBase { public int i = 3; public voidfoo (Object o) { System.out.println("Object " + i); } public voidfoo (String s) { System.out.println("String " + i); } } classBase extendsSuperBase { publicBase () { i = 5; } public static voidmain (String[] args) { SuperBase sb = new Base(); Object o = ""; sb.foo(o); sb.foo(""); } }
Object 5 String 5
Каким будет результат кода?
classParent {} classDeriveOne extendsParent {} classDeriveTwo extendsParent {} Parent p = new Parent(); DeriveOne d1 = new DeriveOne(); DeriveTwo d2 = new DeriveTwo(); d1 = (DeriveOne) d2;
Ошибка компиляции.
Компилятору сразу понятно, что невозможно кастировать d2 к классу DeriveOne, т.к. d2 не является наследником DeriveOne
Будет ли использоваться индекс в запросе?
CREATE index ON post (owner_id); SELECT * FROM post WHERE likes_count > ? AND owner_id = ?;
Да, индекс будет использоваться в запросе.
В данном запросе имеется условие owner_id = ?, которое соответствует индексу, созданному на owner_id.
Индекс на owner_id может помочь улучшить производительность запроса, делая выборку более быстрой.
Условие likes_count > ? может быть вторичным, но главный фильтрующий критерий здесь — это owner_id.
CREATE index ON post (owner_id, likes_count); SELECT * FROM post WHERE owner_id = ?;
Да, индекс будет использоваться в запросе.
В данном запросе имеется условие owner_id = ?, которое соответствует первой колонке составного индекса
(owner_id, likes_count).
Индексы могут использоваться даже если условие соответствует только первой колонке составного
индекса.
CREATE index ON post (owner_id, likes_count); SELECT * FROM post WHERE likes_count = ?;
Нет, индекс не будет использован в этом запросе.
Поскольку условие фильтрации затрагивает только likes_count, а индекс начинается с owner_id, то индекс
(owner_id, likes_count) не будет полезен.
Составной индекс может быть использован, только если условия фильтрации затрагивают первый столбец
(или первый и второй) в индексе.
CREATE index ON post (owner_id); CREATE index ON post (likes_count); SELECT * FROM post WHERE owner_id = ? AND likes_count = ?;
Да, индекс будет использоваться в запросе.
В этом случае оба индекса (owner_id и likes_count) могут быть использованы.
СУБД может использовать оба индекса для более эффективного выполнения запроса.
Например, некоторые системы управления базами данных могут выполнить пересечение индексов (bitmap
index merge)
или выбрать наиболее селективный индекс для начала поиска и затем использовать другой индекс для
дальнейшей фильтрации.
CREATE index ON post (owner_id); CREATE index ON post (likes_count); SELECT * FROM post WHERE owner_id = ? OR likes_count = ?;
Здесь ответ может зависеть от конкретной СУБД и её возможностей оптимизации. В некоторых случаях, особенно для сложных OR-условий, использование индексов может быть ограниченным.
Обычно:
- Некоторые СУБД могут использовать индексы для обеих колонок при запросах с OR-условиями, выполняя
два индексных поиска и объединяя результаты.
- Другие СУБД могут выбрать полный скан таблицы, если считают, что это будет более эффективно по
времени.
Таким образом, хотя технически оба индекса потенциально могут быть использованы,
всё зависит от подсистемы оптимизации запросов конкретной СУБД.
В большинстве случаев конкретная база данных будет принимать решение, исходя из своих алгоритмов
оптимизации.
classVolatileExample { private static booleanrunning = true;// Не использовано volatile public static voidmain (String[] args) throws InterruptedException { Thread thread = new Thread(() -> { int count = 0; while (running) { count++; } System.out.println("Stopped at count: " + count); }); thread.start(); Thread.sleep(1000); running = false; thread.join(); System.out.println("Main thread completed."); } }
Что выведет программа в конце работы?
В таком виде программа не закончится.
т.к. не использовано volatile, while (running) может быть преобразовано в while (true)
classReorderingExample { private intx = 0; private booleanflag = false;// тут нужен volatile public voidwriter () { x = 42;// (1) flag = true;// (2) } public voidreader () { if (flag) {// (3) System.out.println(x);// (4) } } public static voidmain (String[] args) { ReorderingExample example = new ReorderingExample(); Thread writerThread = new Thread(example::writer); Thread readerThread = new Thread(example::reader); writerThread.start(); readerThread.start(); } }
Что выведет программа в конце работы?
0, 42 или ничего
0 - потому-что оптимизатор может поменять местами строки 1 и 2
Что сделать что бы получить ожидаемое?
Добавить volatile для флага
Как правильно создать синглтон
classSingleton { private static Singletoninstance ;// Тут еще нужно вкрячить volatile privateSingleton () {// Private constructor } public static SingletongetInstance () { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
Наиболее распространенный способ — «Double-Checked Locking»
volatile тут нужен, что бы мы отдали полностью созданный и инициализированный объект, иначе может быть ситуация что ссылка на объект опубликована, а объект еще не создан, или объект создан, но его поля еще не проинициализированны.
classUnsafePublication { private Objectresource ;// нужен volatile что бы решить проблему publicUnsafePublication () { new Thread(() -> { resource = new Object(); }).start(); } public ObjectgetResource () { return resource; } public static voidmain (String[] args) throws InterruptedException { UnsafePublication unsafe = new UnsafePublication(); Thread.sleep(100); if (unsafe.getResource() != null) { System.out.println("Resource is initialized"); } else { System.out.println("Resource is null"); } } }
Что тут не так?
Небезопасная публикация
Можем отдать не полностью проинициализированный объект, т.е. объект не null, но еще не все поля проинициализированы