Вопросы на собеседовании по Java: сложные вопросы

Некоторое время назад я написал статью о Топ-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