Статьи

5 странных вопросов о Java, которые заставят вашу голову кружиться

Некоторые из самых странных Java-головоломок, которые мы получили в свои руки

Даже самые опытные разработчики Java сочтут вопросы в этом посте запутанными. Или, по крайней мере, забавно (и совершенно несправедливо). После нашего приключения с Java Deathmatch мы решили опубликовать на этот раз другой набор вопросов, подчеркивая некоторые необычные и причудливые вещи, которые вы можете сделать с Java. С результатами наших предыдущих викторин вы можете ознакомиться с этим постом и посмотреть, сможете ли вы решить вопрос о том, что 4 из 5 разработчиков ошиблись. weird.java_

Попробуйте это дома (или в офисе). Но, пожалуйста, не используйте его в реальных приложениях Java! Если вы не пытаетесь кого-то троллить и в этом случае все идет. Огромная огромная благодарность Питеру Лори за то, что он поделился с нами большинством этих вопросов. Решения доступны в нижней части этого поста, но попробуйте дать им честную попытку и посмотреть, сколько из них вам удастся объяснить.

И вопросы …

1. Закрывающие скобки переоценены

Как ни странно, следующий фрагмент кода прекрасно компилируется. Но что это печатает?

1
2
3
4
5
6
7
8
9
import static java.lang.Character.getNumericValue;
 
public class BigCharacters {
    public static void main(String... a‮) {
        for (char c‮ = 1; c‮ > 0; c‮++)
            if (getNumericValue(c‮) > 50)
                System.out.println(c‮ + ": " + getNumericValue(c‮));
    }
}

Примечание: getNumbericValue возвращает числовое значение типа int, которое представляет символ Unicode. Если символ не имеет числового значения, возвращается -1.

тото

2. Ответ на жизнь, вселенную и все

Уф. У нас есть закрывающие скобки на этот раз. Но что распечатывает следующий фрагмент кода? И почему?

1
2
3
4
5
6
Integer a = 42;
Integer b = 42;
System.out.println(a == b);
Integer c = 666;
Integer d = 666;
System.out.println(c == d);

3. Символ арифметики

Двигаемся дальше. Можете ли вы объяснить, что здесь происходит?

1
2
3
char ch = '0';
ch *= 1.1;
System.out.println(ch);

Возможные варианты:

  • Ошибка компилятора
  • Ошибка выполнения
  • Отпечатки 0
  • Prints 4

4. Не сдавайся!

Этот только что из этого мира. Что тут происходит?

1
2
3
4
String _‎ = "Hello ";
String _‏ = "World";
String _‎‏ = " !!";
System.out.println(_‎+_‏+_‎‏);

Оповещение о спойлере: печатается «Hello World !!»

¯ \ _ (ツ) _ / ¯

ghost.busters

5. Этот вопрос самоосознан

Какое наименьшее значение печатает WTF? Тип х зависит от вас.

1
2
if (x != (x += 0.0f)) 
    System.out.println("WTF");

Решения

1. Закрывающие скобки переоценены

Сначала немного предыстории. Есть символ, закодированный с \ u202e, который используется для языков справа налево, таких как иврит или арабский, и заставляет остальную часть строки отображаться в обратном порядке. Это символ нулевой ширины, и не только, он также допустим для использования в качестве идентификатора Java. Попробуйте скопировать фрагмент кода, переместите курсор, и вы увидите, где он появляется в коде.

Помимо поддержки языка RTL, это также очень полезно, если вы хотите разыграть кого-то. Замените закрывающую скобку открывающей скобкой, за которой стоит этот символ, чтобы перевернуть остальную часть строки — и посмотрите, что будет дальше. Если вы решите сделать это, пожалуйста, пришлите нам фотографию лица жертвы. 🙂

2. Ответ на жизнь, вселенную и все

Целые числа, конечно, являются объектами, в отличие от типа int, который является примитивным типом. Тем не менее, этот фрагмент кода:

1
2
3
4
5
6
Integer a = 42;
Integer b = 42;
System.out.println(a == b);
Integer c = 666;
Integer d = 666;
System.out.println(c == d);

Выводит «true» для первого сравнения и «false» для следующего. Это не сработает для целых чисел, но поскольку целые числа являются отдельными объектами, имеет смысл, что c и d — это не одно и то же. Но почему а == б?

Тип Integer хранит кэш всех объектов со значением в диапазоне от -128 до 127 по соображениям производительности. Поэтому, когда вы объявляете новые переменные в этом диапазоне, вы фактически ссылаетесь на один и тот же объект.

3. Символ арифметики

Этот фрагмент кода печатает 4:

1
2
3
char ch = '0'; // ASCII for ‘0’ is 48
ch *= 1.1; // 48 x 1.1 is 52.8 which turns to 52 when cast to char
System.out.println(ch); // 52 represents ‘4’ in ASCII

4. Не сдавайся!

Почему _, _ и _ являются разными переменными? Возможно, вы догадались, это правильно. Ответ со скрытыми символами, которые передаются как законные идентификаторы Java. Вы можете прочитать больше об этом в блоге Питера Лори прямо здесь .

5. Этот вопрос самоосознан

Так что же делает это выражение верным?

1
2
if (x != (x += 0.0f))
    System.out.println("WTF");

Вы можете использовать любую String, а также int или long (1 << 24) + 1 работают для этих типов как их наименьшее значение. Но наименьшее значение из них — Double.MIN_VALUE, который округляется до 0.0f при приведении к плавающей точке.

Последние мысли

Мы надеемся, что вам понравилась эта коллекция вопросов! Однако, если вы обнаружите, что тратите слишком много времени на головоломки в своей собственной кодовой базе, это, вероятно, будет далеко не идеальным. Для таких ситуаций мы создали Takipi для Java . Takipi — это Java-агент, который собирает все данные, необходимые для устранения ошибок в работе — БЕЗ просмотра файлов журналов и попытки воссоздать состояние, которое их вызвало. Он позволяет вам видеть значения переменных, которые вызывают ошибки, по всему стеку и накладывать их на ваш код.