TGViewer
Грамота от Кузьмича Грамота от Кузьмича @java_ot_kuzmicha · 208 subscribers
Post #27 204
Грамота от Кузьмича Присылаю вам пламенный привет🔥💌 с прошедшей конференции Dump из Питера! На конфе было круто - есть треки докладов по фронт, бек-разработке, менеджменту и тестированию. (А вот в Питере сейчас не круто - дубак и ветруган🥶) Доклады огонь, спикеры топ, но сегодня…
Счастливого понедельника! Как обещал - публикую ответы к задачкам выше:

#1
Имеем цикл while (count < 4) - который опирается на значение count, которое никогда внутри цикла не меняется. Значит цикл бесконечный. Например попав в цикл с count = 3 - count всегда будет оставаться = 3, значит условия цикла будет верно, значит мы будем в нем кружиться до тепловой смерти вселенной.

П.С. Вообще бесконечные циклы - это нормально, до тех пор пока в них у вас описаны способы выхода, в один из которых можно гарантированно прийти - это может быть и break и return, выброс исключения, да даже простихосспаде System.exit(0) - что угодно, лишь бы из цикла можно было как-то выбраться. Либо рассчитывайте на то что приложение придется прерывать вручную.

#2
return capitalized / words.size() < 0.2;
Тут пара проблем. Во-первых - можно нарваться на ArithmeticException при делении на 0.
Но важнее здесь то что при делении capitalized / words.size() происходит деление целого числа (int) на целое число (int) и результатом будет тоже int, а значит никаких дробей мы ни при каком раскладе не получим и сравнение не принесет того смысла который мы хотели. Например:
capitalized = 1;
words.size() = 5;
capitalized / words.size() = 1 / 5 = 0 - потому что произошло целочисленное деление.

Решением может стать явное преобразование одного из int к double, что бы результат деления тоже дал double:
return (double) capitalized / words.size() < 0.2;

#3
if (endKey[i] < 0xff) - вот корень зла. Здесь мы имеем условие, которое будет выполняться всегда - а значит либо это условие описано неправильно, либо if тут вообще лишний. Почему условие будет выполняться всегда? Разбираем значения и типы данных:
byte[] endKey - массив байт,
endKey[i] - один байт из массива, может хранить значение от -128 до 127
0xff - число в 16-ричной форме записи, в человеческом виде это число 255.
Собственно, читаем исходную строку кода с if новым взглядом:
if (endKey[i] < 0xff)
if ([значение от -128 до 127] меньше [255]) - очевидно что это условие будет выполняться всегда.

#4
Проблема кроется в этой строке:

val = val | (1 << j);

Начну с вводной. Часть 1 << j - по сути аналог математического выражения 2^j (2 в степени j). В Java нет оператора степени, но есть метод Math.pow(). Без оператора побитового сдвига строчка кода выше могла бы выглядеть как:

val = val | (1 * Math.pow(2, j));
или просто
val = val | Math.pow(2, j);

Почему тут вообще решено было использовать операцию левого битового сдвига << ? Многим эта тема кажется стремной и неоправданной, но представьте что ваш метод - "горячий", его вызовы в приложении происходят по 10000 раз в секунду, а то и больше - тогда конечно вы будете гнаться за каждой милисекундой в ущерб читаемости. Загляните ради любопытства в реализацию метода Math.pow() - и ужаснитесь сколько всего там происходит. Оператор же побитового сдвига прост как сапог - двигает биты в памяти влево на N позиций.

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

Теперь про причину ошибки в упомянутой строке - проблема в интовом типе 1 (единицы) в выражении:
val = val | (1 << j);

Все числовые литералы - неявно int-ы (если только у них не указаны постфиксы: L, l (для long), D, d (для double), F, f (для float)).
1 << j - означает что единица целочисленного 4-байтного типа (т.е. 00000000 00000000 00000000 00000001 в двоичном виде) будет сдвинута на j разрядов влево. Например:
1 << 2 = 00000000 00000000 00000000 00000100 в двоичной системе = 8
1 << 13 = 00000000 00000000 00100000 00000000 в двоичной системе = 8192
Если j окажется больше или равно 31 - мы получим переполнение типа, знакомое нам и по обычным арифметическим операциям (ну например System.out.println(2000000000 + 2000000000); //result: -294967296).
  • 👍 2
  • 🔥 1
More from @java_ot_kuzmicha
  1. Jul 28, 2026Добавляю краски в музыку🟥🟨🟦🟧🟩 Пришла мне тут шальная мысль - что если каждый альбом к…
  2. Dec 10, 2025Более жизовые итоги чем эти ваши я.музыка или спотифаи. Кстати, че бы еще вы добавили в та…
  3. Nov 24, 2025уже пора?🤔 тренды все-таки
  4. Nov 19, 20253 из 25 - это не про лото и не про биатлон. Для тех кто пропустил релиз Java 25 - смотрим…
  5. Nov 1, 2025в рабочую субботу законодательно запрещены посты на серьезные темы. поэтому вот вам веселы…
  6. Oct 9, 2025Достал такое из почтового ящика. Скажите, кто вызывал таких мастеров - а с деплоем в прод…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →