microJUG – Telegram
microJUG
979 subscribers
155 photos
1 video
2 files
237 links
Мысли о Java.
Основной канал: @miniJUG
Буст: https://news.1rj.ru/str/microJUG?boost
Чат: https://news.1rj.ru/str/micro_JUG
Таблица JEP'ов: https://minijug.org/jeps.html
Download Telegram
Квиз вам на ночь
Марк Рейнолд объявил, что LTS-релизы будут выходить раз в 2 года, а не в 3.
#java21 #lts
Классный вводный доклад про арифметику с плавающей точкой. Не поленитесь и потратьте всего полчаса на просмотр. Гарантирую, что время будет потрачено не зря. Я вот, например, узнал, как вообще на английском читается аббревиатура IEEE 754 😅. Оказывается, её произносят как "I triple-E seven fifty-four".

Ну это не самое полезное знание, конечно. Куда важнее понять, что в double числа дискретные и их множество конечно, в то время как вещественные числа непрерывны и их бесконечное количество. Это значит, double аппроксимирует вещественные числа, т.е. каждое вещественное число конвертируется в double путём нахождения ближайшего. Например, числа 0.1 в double нет, а ближайшее к нему это 0.1000000000000000055511151231257827021181583404541015625. Но почему тогда Double.toString(0.1) возвращает "0.1", а не "0.1000000000000000055511151231257827021181583404541015625"?

А ещё из-за такой аппроксимации нарушаются многие аксиомы. Не работают ассоциативность сложения, ассоциативность умножения, дистрибутивность и т.д. Например:

> 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1
$1 ==> 0.9999999999999999

Но:

> (0.1+0.1+0.1+0.1)+(0.1+0.1+0.1+0.1)+0.1+0.1
$2 ==> 1.0

(Это кстати отличный пример, демонстрирующий, почему double ни в коем случае нельзя использовать для хранения денег)

В общем, про всё это можно узнать из лекции.

#IEEE754 #double
Думаю, написать кусок кода на Java через стрим или цикл
#юмор
Три самых сложных проблемы в разработке ПО – это именование переменных, инвалидация кешей, и… порядок объявления полей, методов и параметров. Третье особенно болезненно в Java, потому что в ней нет никаких ограничений по порядку. Например, можно объявить поле в классе, потом десяток методов, а потом опять поле. Когда я вижу такое в коде, у меня сильно бомбит. Считаю, что Java не должна вообще такое позволять. Но с другой стороны, в далёких 90-х не было понятно, какой должен быть строгий порядок, поэтому решили не ограничивать вообще. Например, люди, пришедшие из C++ (а это основная целевая группа в то время), привыкли группировать по области видимости:

class C {
private:
// поля, методы
public:
// поля, методы
}

Я же считаю, что надо группировать по типу членов: поля отдельно, методы отдельно.

Далее я поделюсь моим личным предпочтением относительно порядка.
Порядок объявления членов класса должен быть таким, по моему мнению:

class C {
// статические константы (static final)
// статические поля (static)
// final поля
// поля
// конструкторы
// геттеры/сеттеры
// методы
// вложенные классы
}

Порядок самих полей – вещь сложная, надо решать в каждом индивидуальном случае. Строгого правила нет, но можно исходить из здравого смысла: если, например, есть Text inputText и Button okButton, и поле ввода в окошке находится выше кнопки ОК, то и поле inputText должно быть объявлено выше okButton.

Порядок параметров конструкторов, очевидно, должен соответствовать порядку полей. Если конструкторов несколько, то они должны быть отсортированы по принципу «кто кого дёргает». Если конструктор A вызывает конструктор B, то конструктор A должен быть объявлен выше. Если конструкторы не связаны друг с другом, то выше лучше объявить тот конструктор, у которого поменьше параметров (он более простой и, скорее всего, будет вызываться чаще, поэтому лучше, чтобы он находился читателем кода пораньше).

С методами то же самое: тот, который вызывает, должен быть выше того, кого вызывают. То есть чем ниже мы скроллим класс, тем всё глубже в детали реализации мы погружаемся. Чем ниже, тем более низкоуровневые методы мы видим. Бывает, что методы вызывают друг друга, тогда непонятно, что должно быть выше. Но взаимная рекурсия довольно редкая штука, на самом деле. Сложнее, если методы не связаны друг с другом. В этом случае уже надо подключать здравый смысл и логику: я предпочитаю группировать по функциональности. Связанные вещи должны быть рядом:

// Функциональность a
a() {
aImpl1()
aImpl2()
}

aImpl1() {}

aImpl2() {}

// Функциональность b
b() {
bImpl1()
bImpl2()
}

bImpl1() {}

bImpl2() {}

С порядком параметров методов посложнее – здесь я ещё не до конца выработал правила. Есть только несколько не очень чётких принципов. Один из них: in-параметры, очевидно, должны быть раньше, чем out-параметры. Что такое in- и out-параметры? Суть должна стать понятна на примере:

public void copy(Path from, Path to) {}

Думаю, не стоит пояснять, что in, а что out. Всё очевидно. Что in, а что out, должно вытекать из здравого смысла.

Ещё принцип: стабильные параметры должны быть раньше нестабильных. Это не так уж и просто объяснить, что стабильно, а что нет, но попытаюсь опять привести пример:

public void drawPoint(GC gc, int x, int y) {}
public void drawCircle(GC gc, int x, int y, int r) {}

GC – это graphics context. Он более стабилен, чем координаты, потому что создаётся один раз, а рисуется туда много всего и приходит много разных иксов и игреков. Другими словами, если что-то более постоянное и долгоживущее, тем оно более стабильно и должно идти раньше.

Также я всегда объявляю лямбды последними. Например:

public void addEvent(EventType type, Runnable r);

Иначе будет вот так:

addEvent(() -> {
// 100500 строк кода
}, EventType.MOUSE_CLICK);

Лучше, чтобы MOUSE_CLICK был первым, а после длинной лямбды не шло ничего.

В общем, как-то так. Такой вот набор правил и принципов я применяю.

Вопросы? Замечания?
Кружка на работе. Как вам?
Как же хорошо, когда у тебя заботливые коллеги
Жалкая пародия / неповторимый оригинал
Какой оператор используете для XOR по boolean?
Anonymous Poll
40%
x ^ y
23%
x != y
36%
Никогда не задумывался
Ну что, как вам реклама в Телеграме? Спасибо хоть, что не казино Три Топора 🤣
Как подросла производительность сборщиков мусора с JDK 8 по JDK 17. Увеличилась пропускная способность, уменьшились паузы и уменьшилось потребление памяти (кроме ZGC). Поэтому, если вы тупо перейдёте на Java 17, даже без перекомпиляции, то автоматом всё станет быстрее.
Ссылка.