Некоторое время назад я написал статью о Топ-50 вопросов по Java-программированию. Наши читатели её очень оценили. Поэтому сегодня мы рассмотрим несколько хитрых вопросов на собеседовании по Java.
Вопросы на собеседовании по Java
Это вопросы по программированию, но если у вас нет глубокого понимания Java, будет сложно угадать вывод и объяснить его.
1. Null в качестве аргумента
У нас есть перегруженные функции, и мы передаем null. Какая функция будет вызвана, и каков будет вывод программы?
public class Test {
public static void main(String[] args) {
foo(null);
}
public static void foo(Object o) {
System.out.println("Object argument");
}
public static void foo(String s) {
System.out.println("String argument");
}
}
2. Использование “L” для long
Можете ли вы угадать вывод следующих утверждений?
long longWithL = 1000*60*60*24*365L;
long longWithoutL = 1000*60*60*24*365;
System.out.println(longWithL);
System.out.println(longWithoutL);
Объяснение хитрого вопроса о null-аргументе
Согласно спецификации Java, в случае перегрузки компилятор выбирает самую конкретную функцию. Очевидно, что класс String более конкретен, чем класс Object, поэтому будет выведено “String argument”. Но что, если у нас есть еще один метод в классе, как показано ниже?
public static void foo(StringBuffer i){
System.out.println("StringBuffer impl");
}
В этом случае компилятор Java выдаст ошибку “Метод foo(String) является неоднозначным для типа Test”. У классов String и StringBuffer нет иерархии наследования. Таким образом, ни один из них не является более конкретным по отношению к другому. Метод считается более конкретным, чем другой, если любой вызов, обработанный первым методом, может быть передан другому без ошибки времени компиляции. Мы можем передать String в качестве параметра методу с аргументом Object и методу с аргументом String, но не методу с аргументом StringBuffer.
Объяснение для переменной Long
Вывод фрагмента кода будет следующим:
31536000000
1471228928
Мы явно создаем первую переменную как long, добавляя суффикс “L”. Таким образом, компилятор будет рассматривать ее как long и присваивать ей первую переменную. Для второго оператора компилятор выполнит вычисление и рассмотрит его как 32-битное целое число. Поскольку результат выходит за пределы максимального значения для целого числа (2147483647), компилятор усечет наиболее значимые биты, а затем присвоит его переменной. Двоичный эквивалент 1000*60*60*24*365L = 011101010111101100010010110000000000 (36 бит). После удаления 4 наиболее значимых битов для помещения в 32-битное int, новое значение = 01010111101100010010110000000000 (32 бита). Это равно 1471228928, отсюда и вывод. Недавно я создал серию видеороликов на YouTube по сложным программам на Java.
Вы можете ознакомиться с большим количеством примеров программ на Java в нашем репозитории GitHub.
Source:
https://www.digitalocean.com/community/tutorials/java-tricky-interview-questions