Топ-50 вопросов на собеседовании по Java-программированию

Введение

Если вы проходите собеседование на должность Java-программиста, то ваши навыки программирования, скорее всего, будут проверены. Независимо от того, являетесь ли вы новичком в Java или опытным разработчиком, в этой статье представлены некоторые распространенные вопросы и ответы на собеседовании по Java, чтобы помочь вам подготовиться.

1. Как перевернуть строку в Java?

В классе String нет метода reverse(). Однако вы можете создать массив символов из строки и затем перебирать его с конца к началу. Вы можете добавлять символы в StringBuilder и, наконец, вернуть перевернутую строку.

Приведенный ниже пример кода показывает один из способов переворота строки:

public class StringPrograms {

	public static void main(String[] args) {
		String str = "123";

		System.out.println(reverse(str));
	}

	public static String reverse(String in) {
		if (in == null)
			throw new IllegalArgumentException("Null is not valid input");

		StringBuilder out = new StringBuilder();

		char[] chars = in.toCharArray();

		for (int i = chars.length - 1; i >= 0; i--)
			out.append(chars[i]);

		return out.toString();
	}

}

Бонусные баллы за добавление проверки на null в методе и использование StringBuilder для добавления символов. Обратите внимание, что индексация в Java начинается с 0, поэтому в цикле for нужно начинать с chars.length - 1.

2. Как поменять местами два числа, не используя третью переменную на Java?

Обмен числами без использования третьей переменной – это трехшаговый процесс, который лучше визуализировать в коде:

b = b + a; // now b is sum of both the numbers
a = b - a; // b - a = (b + a) - a = b (a is swapped)
b = b - a; // (b + a) - b = a (b is swapped)

Следующий пример кода показывает один из способов реализации метода обмена числами:

public class SwapNumbers {

public static void main(String[] args) {
	int a = 10;
	int b = 20;

    System.out.println("a is " + a + " and b is " + b);

	a = a + b;
	b = a - b;
	a = a - b;

    System.out.println("After swapping, a is " + a + " and b is " + b);
    }

}

Результат показывает, что значения целых чисел поменялись местами:

Output
a is 10 and b is 20 After swapping, a is 20 and b is 10

3. Напишите программу на Java для проверки наличия гласной буквы в строке.

Следующий пример кода показывает, как использовать регулярное выражение для проверки наличия гласных букв в строке:

public class StringContainsVowels {

	public static void main(String[] args) {
		System.out.println(stringContainsVowels("Hello")); // true
		System.out.println(stringContainsVowels("TV")); // false
	}

	public static boolean stringContainsVowels(String input) {
		return input.toLowerCase().matches(".*[aeiou].*");
	}

}

4. Напишите программу на Java для проверки, является ли заданное число простым.

Вы можете написать программу для деления заданного числа n на число от 2 до n/2 и проверки остатка. Если остаток равен 0, то это не простое число. Следующий пример кода показывает один из способов проверки, является ли заданное число простым:

public class PrimeNumberCheck {

	public static void main(String[] args) {
		System.out.println(isPrime(19)); // true
		System.out.println(isPrime(49)); // false
	}

	public static boolean isPrime(int n) {
		if (n == 0 || n == 1) {
			return false;
		}
		if (n == 2) {
			return true;
		}
		for (int i = 2; i <= n / 2; i++) {
			if (n % i == 0) {
				return false;
			}
		}

		return true;
	}

}

Хотя эта программа работает, она не очень эффективна по памяти и времени. Учтите, что для заданного числа N, если существует простое число M между 2 и √N (корень из N), которое равномерно делит его, то N не является простым числом.

5. Напишите программу на Java для печати последовательности Фибоначчи с использованием рекурсии.

A Fibonacci sequence is one in which each number is the sum of the two previous numbers. In this example, the sequence begins with 0 and 1. The following example code shows how to use a for loop to print a Fibonacci sequence:

public class PrintFibonacci {

	public static void printFibonacciSequence(int count) {
		int a = 0;
		int b = 1;
		int c = 1;

		for (int i = 1; i <= count; i++) {
			System.out.print(a + ", ");

            a = b;
			b = c;
			c = a + b;
		}
	}

	public static void main(String[] args) {
    	printFibonacciSequence(10);
	}

}
Output
0, 1, 1, 2, 3, 5, 8, 13, 21, 34,

Вы также можете использовать рекурсию для печати последовательности Фибоначчи, так как числа Фибоначчи генерируются путем сложения двух предыдущих чисел в последовательности:

F(N) = F(N-1) + F(N-2)

Следующий пример класса показывает, как использовать рекурсию для вычисления последовательности Фибоначчи длиной 10 чисел.

public class PrintFibonacciRecursive {

    public static int fibonacci(int count) {
		if (count <= 1)
			return count;

		return fibonacci(count - 1) + fibonacci(count - 2);
	}

	public static void main(String args[]) {
    	int seqLength = 10;

    	System.out.print("A Fibonacci sequence of " + seqLength + " numbers: ");

    	for (int i = 0; i < seqLength; i++) {
      	    System.out.print(fibonacci(i) + " ");
    	}
  	}

}
Output
A Fibonacci sequence of 10 numbers: 0 1 1 2 3 5 8 13 21 34

6. Как проверить, содержит ли список целых чисел только нечетные числа в Java?

Вы можете использовать цикл for и проверить, является ли каждый элемент нечетным:

public static boolean onlyOddNumbers(List<Integer> list) {
	for (int i : list) {
		if (i % 2 == 0)
			return false;
	}

	return true;
}

Если список большой, вы можете использовать параллельный поток для более быстрой обработки, как показано в следующем примере кода:

public static boolean onlyOddNumbers(List<Integer> list) {
	return list
			.parallelStream() // параллельный поток для более быстрой обработки
			.anyMatch(x -> x % 2 != 0); // вернуться, как только найдены элементы, соответствующие условию
}

Чтобы узнать больше о математике, лежащей в основе определения, является ли число нечетным, обратитесь к операции модуля на Википедии.

7. Как проверить, является ли строка палиндромом в Java?

A palindrome string is the same string backwards or forwards. To check for a palindrome, you can reverse the input string and check if the result is equal to the input. The following example code shows how to use the String charAt(int index) method to check for palindrome strings:

boolean checkPalindromeString(String input) {
	boolean result = true;
	int length = input.length();

	for (int i = 0; i < length/2; i++) {
		if (input.charAt(i) != input.charAt(length - i - 1)) {
			result = false;
			break;
		}
	}

	return result;
}

8. Как удалить пробелы из строки в Java?

Приведенный ниже пример кода показывает один из способов удаления пробелов из строки с использованием метода Character.isWhitespace():

String removeWhiteSpaces(String input) {
	StringBuilder output = new StringBuilder();
	
	char[] charArray = input.toCharArray();
	
	for (char c : charArray) {
		if (!Character.isWhitespace(c))
			output.append(c);
	}
	
	return output.toString();
}

Узнайте больше о удалении пробелов и других символов из строки на языке Java.

9. Как удалить начальные и конечные пробелы из строки на языке Java?

Класс String содержит два метода для удаления начальных и конечных пробелов: trim() и strip(). Метод strip() был добавлен в класс String в Java 11. Метод strip() использует метод Character.isWhitespace() для проверки, является ли символ пробелом. Данный метод использует кодовые точки Unicode, в то время как метод trim() определяет любой символ с значением кодовой точки, меньшим или равным U+0020, как символ пробела.

Метод strip() является рекомендуемым способом удаления пробелов, поскольку он использует стандарт Unicode. Ниже приведен пример кода, демонстрирующий использование метода strip() для удаления пробелов:

String s = "  abc  def\t";
		
s = s.strip();
		
System.out.println(s);

Поскольку класс String является неизменяемым, результат работы метода strip() необходимо присвоить строке.

10. Как отсортировать массив в Java?

Утилитарный класс Arrays имеет множество перегруженных методов sort() для сортировки примитивных и объектных массивов. Если вы сортируете примитивный массив по естественному порядку, то вы можете использовать метод Arrays.sort(), как показано в следующем примере:

int[] array = {1, 2, 3, -1, -2, 4};

Arrays.sort(array);

System.out.println(Arrays.toString(array));

Однако, если вы хотите отсортировать массив объектов, то объект должен реализовывать интерфейс Comparable. Если вы хотите указать критерии сортировки, то вы можете передать Comparator для логики сортировки. Узнайте больше о Comparable и Comparator в Java.

11. Как создать программатически сценарий взаимной блокировки (deadlock) в Java?

Сценарий взаимной блокировки (deadlock) возникает в многопоточной среде Java, когда два или более потоков блокируются навсегда. Ситуация взаимной блокировки возникает, когда два или более потоков взаимно блокируют друг друга. В следующем примере кода создается сценарий взаимной блокировки:

public class ThreadDeadlock {

    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();
    
        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
        Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
        
        t1.start();
        Thread.sleep(5000);
        t2.start();
        Thread.sleep(5000);
        t3.start();        
    }

}

class SyncThread implements Runnable {

    private Object obj1;
    private Object obj2;

    public SyncThread(Object o1, Object o2) {
        this.obj1 = o1;
        this.obj2 = o2;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();

        System.out.println(name + " acquiring lock on " + obj1);
        synchronized (obj1) {
            System.out.println(name + " acquired lock on " + obj1);
            work();
            System.out.println(name + " acquiring lock on " + obj2);
            synchronized (obj2) {
                System.out.println(name + " acquired lock on " + obj2);
                work();
            }
            System.out.println(name + " released lock on " + obj2);
        }
        System.out.println(name + " released lock on " + obj1);
        System.out.println(name + " finished execution.");
    }

    private void work() {
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Все три потока смогут захватить блокировку на первом объекте. Однако они используют общие ресурсы и запускаются таким образом, что будут бесконечно ожидать захвата блокировки на втором объекте. Вы можете использовать потоковый дамп Java для обнаружения взаимоблокировки. Узнайте больше о взаимоблокировке в Java.

12. Как вы можете найти факториал целого числа на Java?

Факториал целого числа рассчитывается путем умножения всех чисел от 1 до заданного числа:

F(n) = F(1)*F(2)...F(n-1)*F(n)

Следующий примерный код показывает, как использовать рекурсию для нахождения факториала целого числа:

public static long factorial(long n) {
	if (n == 1)
		return 1;
	else
		return (n * factorial(n - 1));
}

13. Как перевернуть связанный список на Java?

LinkedList descendingIterator() возвращает итератор, который перебирает элементы в обратном порядке. Следующий примерный код показывает, как использовать этот итератор для создания нового связанного списка с элементами, перечисленными в обратном порядке:

LinkedList<Integer> ll = new LinkedList<>();

ll.add(1);
ll.add(2);
ll.add(3);

System.out.println(ll);

LinkedList<Integer> ll1 = new LinkedList<>();

ll.descendingIterator().forEachRemaining(ll1::add);

System.out.println(ll1);

Узнайте больше о обращении связного списка с точки зрения структур данных и алгоритмов.

14. Как реализовать бинарный поиск на Java?

Элементы массива должны быть отсортированы для реализации бинарного поиска. Бинарный поиск основан на следующих условиях:

  • Если ключ меньше среднего элемента, то теперь нужно искать только в первой половине массива.
  • Если ключ больше среднего элемента, то нужно искать только во второй половине массива.
  • Если ключ равен среднему элементу в массиве, то поиск завершается.
  • Наконец, если ключ не найден во всем массиве, то должно вернуться значение -1. Это указывает на то, что элемент отсутствует.

Ниже приведен пример кода, реализующего бинарный поиск:

public static int binarySearch(int arr[], int low, int high, int key) {
	int mid = (low + high) / 2;

	while (low <= high) {
		if (arr[mid] < key) {
			low = mid + 1;
		} else if (arr[mid] == key) {
			return mid;
		} else {
			high = mid - 1;
		}
		mid = (low + high) / 2;
	}

	if (low > high) {
		return -1;
	}

	return -1;
}

15. Напишите программу на Java, иллюстрирующую сортировку слиянием.

Сортировка слиянием – один из наиболее эффективных алгоритмов сортировки. Он основан на принципе “разделяй и властвуй”. Идея заключается в разделении списка на несколько подсписков до тех пор, пока каждый подсписок не будет состоять из одного элемента, а затем объединении этих подсписков таким образом, чтобы получить отсортированный список. Приведенный ниже пример кода показывает один из способов использования сортировки слиянием:

public class MergeSort {

	public static void main(String[] args) {
		int[] arr = { 70, 50, 30, 10, 20, 40, 60 };

		int[] merged = mergeSort(arr, 0, arr.length - 1);

		for (int val : merged) {
			System.out.print(val + " ");
		}
	}

	public static int[] mergeTwoSortedArrays(int[] one, int[] two) {
		int[] sorted = new int[one.length + two.length];

		int i = 0;
		int j = 0;
		int k = 0;

		while (i < one.length && j < two.length) {
			if (one[i] < two[j]) {
				sorted[k] = one[i];
				k++;
				i++;
			} else {
				sorted[k] = two[j];
				k++;
				j++;
			}
		}

		if (i == one.length) {
			while (j < two.length) {
				sorted[k] = two[j];
				k++;
				j++;
			}
		}

		if (j == two.length) {
			while (i < one.length) {
				sorted[k] = one[i];
				k++;
				i++;
			}
		}

		return sorted;
	}

	public static int[] mergeSort(int[] arr, int lo, int hi) {
		if (lo == hi) {
			int[] br = new int[1];
			br[0] = arr[lo];

			return br;
		}

		int mid = (lo + hi) / 2;

		int[] fh = mergeSort(arr, lo, mid);
		int[] sh = mergeSort(arr, mid + 1, hi);

		int[] merged = mergeTwoSortedArrays(fh, sh);

		return merged;
	}

}

16. Можете ли вы создать пирамиду символов на Java?

Паттерновые программы очень популярны на собеседованиях. Этот тип вопроса используется для оценки логического мышления кандидата. Смотрите Примеры программ паттернов пирамиды на Java для различных способов создания пирамидных паттернов.

17. Напишите программу на Java, которая проверяет, содержат ли два массива одинаковые элементы.

Чтобы проверить, содержат ли два массива одинаковые элементы, сначала нужно создать набор элементов из обоих массивов, а затем сравнить элементы в этих наборах, чтобы найти элемент, который отсутствует в обоих наборах. Приведенный ниже пример кода показывает, как проверить, содержат ли два массива только общие элементы:

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class ArraySameElements {

	public static void main(String[] args) {
		Integer[] a1 = {1,2,3,2,1};
		Integer[] a2 = {1,2,3};
		Integer[] a3 = {1,2,3,4};
		
		System.out.println(sameElements(a1, a2));
		System.out.println(sameElements(a1, a3));
	}

	static boolean sameElements(Object[] array1, Object[] array2) {
		Set<Object> uniqueElements1 = new HashSet<>(Arrays.asList(array1));
		Set<Object> uniqueElements2 = new HashSet<>(Arrays.asList(array2));
		
		// если размеры массивов разные, значит есть несоответствие
		if (uniqueElements1.size() != uniqueElements2.size()) return false;
		
		for (Object obj : uniqueElements1) {
			// элемент отсутствует в обоих наборах?
			if (!uniqueElements2.contains(obj)) return false;
		}
		
		return true;
	}

}
Output
true false

18. Как получить сумму всех элементов в целочисленном массиве в Java?

Вы можете использовать цикл for для итерации по элементам массива и их сложения, чтобы получить итоговую сумму:

int[] array = { 1, 2, 3, 4, 5 };

int sum = 0;

for (int i : array)
	sum += i;

System.out.println(sum);

19. Как найти второе наибольшее число в массиве в Java?

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

private static int findSecondHighest(int[] array) {
	int highest = Integer.MIN_VALUE;
	int secondHighest = Integer.MIN_VALUE;

	for (int i : array) {
		if (i > highest) {
			secondHighest = highest;
			highest = i;
		} else if (i > secondHighest) {
			secondHighest = i;
		}

	}
	return secondHighest;
}

20. Как перемешать массив в Java?

Следующий пример кода показывает, как использовать класс Random для генерации случайных индексов и перемешивания элементов:

int[] array = { 1, 2, 3, 4, 5, 6, 7 };

Random rand = new Random();

for (int i = 0; i < array.length; i++) {
	int randomIndexToSwap = rand.nextInt(array.length);
	int temp = array[randomIndexToSwap];
	array[randomIndexToSwap] = array[i];
	array[i] = temp;
}

System.out.println(Arrays.toString(array));

Вы можете запустить код перемешивания внутри другого цикла for, чтобы перемешать несколько раундов.

21. Как найти строку в текстовом файле в Java?

Следующий пример кода показывает, как использовать класс Scanner для построчного чтения содержимого файла, а затем использовать метод contains() класса String, чтобы проверить, содержится ли строка в файле:

boolean findStringInFile(String filePath, String str) throws FileNotFoundException {
	File file = new File(filePath);

	Scanner scanner = new Scanner(file);

	// читаем файл построчно
	while (scanner.hasNextLine()) {
		String line = scanner.nextLine();
		if (line.contains(str)) {
			scanner.close();
			return true;
		}
	}
	scanner.close();

	return false;
}

Обратите внимание, что примерный код предполагает, что строка, которую вы ищете в файле, не содержит символов новой строки.

22. Как распечатать дату в определенном формате в Java?

Следующий пример кода показывает, как использовать класс SimpleDateFormat для форматирования строки даты:

String pattern = "MM-dd-yyyy";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);

String date = simpleDateFormat.format(new Date());
System.out.println(date); // 06-23-2020

Узнайте больше о Java SimpleDateFormat.

23. Как объединить два списка в Java?

Следующий пример кода показывает, как использовать метод addAll() для объединения нескольких списков в Java:

List<String> list1 = new ArrayList<>();
list1.add("1");
List<String> list2 = new ArrayList<>();
list2.add("2");

List<String> mergedList = new ArrayList<>(list1);
mergedList.addAll(list2);
System.out.println(mergedList); // [1, 2]

24. Напишите программу на Java, которая сортирует HashMap по значению.

HashMap не является упорядоченной коллекцией. Следующий пример кода показывает, как отсортировать записи по значению и сохранить их в LinkedHashMap, который сохраняет порядок вставки:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class SortHashMapByValue {

	public static void main(String[] args) {
		Map<String, Integer> scores = new HashMap<>();

		scores.put("David", 95);
		scores.put("Jane", 80);
		scores.put("Mary", 97);
		scores.put("Lisa", 78);
		scores.put("Dino", 65);

		System.out.println(scores);

		scores = sortByValue(scores);

		System.out.println(scores);
	}

	private static Map<String, Integer> sortByValue(Map<String, Integer> scores) {
		Map<String, Integer> sortedByValue = new LinkedHashMap<>();

		// получить набор элементов
		Set<Entry<String, Integer>> entrySet = scores.entrySet();
		System.out.println(entrySet);

		// создать список, так как набор неупорядоченный
		List<Entry<String, Integer>> entryList = new ArrayList<>(entrySet);
		System.out.println(entryList);

		// отсортировать список по значению
		entryList.sort((x, y) -> x.getValue().compareTo(y.getValue()));
		System.out.println(entryList);

		// заполнить новую хеш-карту
		for (Entry<String, Integer> e : entryList)
			sortedByValue.put(e.getKey(), e.getValue());

		return sortedByValue;
	}

}

25. Как удалить все вхождения заданного символа из входной строки на Java?

В классе String нет метода для удаления символов. В следующем примере показано, как использовать метод replace() для создания новой строки без заданного символа:

String str1 = "abcdABCDabcdABCD";
		
str1 = str1.replace("a", ""); 

System.out.println(str1); // bcdABCDbcdABCD

Строка неизменяемая в Java. Все методы манипуляции со строками возвращают новую строку, поэтому вам нужно присвоить ее другой переменной. Узнайте больше о удалении символов из строки на Java.

26. Как получить отдельные символы и их количество в строке на Java?

Вы можете создать массив символов из строки. Затем перебирайте его и создайте HashMap с символом в качестве ключа и его количеством в качестве значения. В следующем примере показано, как извлечь и посчитать символы строки:

String str1 = "abcdABCDabcd";

char[] chars = str1.toCharArray();

Map<Character, Integer> charsCount = new HashMap<>();

for (char c : chars) {
	if (charsCount.containsKey(c)) {
		charsCount.put(c, charsCount.get(c) + 1);
	} else
		charsCount.put(c, 1);
}

System.out.println(charsCount); // {a=2, A=1, b=2, B=1, c=2, C=1, d=2, D=1}

27. Можете ли вы программно доказать, что объект String в Java является неизменяемым?

Следующий пример кода показывает, как доказать, что объект String является неизменяемым, и комментарии в коде объясняют каждый шаг:

String s1 = "Java"; // Переменная "Java" типа String создана в пуле и присвоена s1

String s2 = s1; // s2 также содержит ссылку на "Java" в пуле

System.out.println(s1 == s2); // доказательство того, что s1 и s2 имеют одинаковую ссылку

s1 = "Python"; 
// значение s1 было изменено выше, но как же String является неизменяемым?

// в этом случае создана новая строка "Python" в пуле
// s1 теперь ссылается на новую строку в пуле
// ОДНАКО, исходная строка "Java" остается неизменной и остается в пуле
// s2 все еще ссылается на исходную строку "Java" в пуле

// доказательство того, что s1 и s2 имеют разные ссылки
System.out.println(s1 == s2); 

System.out.println(s2); 
// выводит "Java", что подтверждает, что исходное значение строки неизменно, следовательно, String - неизменяемый

28. Можете ли вы написать код для демонстрации наследования в Java?

Следующий пример кода показывает, как использовать ключевое слово extends для создания подкласса класса Animal. Новый класс Cat наследует переменную от класса Animal и добавляет дополнительный код, принадлежащий только классу Cat.

class Animal {
	String color;
}

class Cat extends Animal {
	void meow() {
		System.out.println("Meow");
	}
}

29. Как вы показываете проблему алмаза с множественным наследованием в Java?

Проблема алмаза возникает, когда класс наследует от нескольких классов и возникает неоднозначность при определении, какой метод должен выполниться из какого класса. В Java нельзя наследовать от нескольких классов, чтобы избежать проблемы алмаза, что проиллюстрировано следующим примером:

interface I {
	void foo();
}
class A implements I {
	public void foo() {}
}

class B implements I {
	public void foo() {}
}

class C extends A, B { // не будет компилироваться
	public void bar() {
		super.foo();
	}
}

30. Как вы иллюстрируете пример try-catch в Java?

Следующий пример кода показывает пример использования try-catch:

try {
	FileInputStream fis = new FileInputStream("test.txt");
} catch(FileNotFoundException e) {
	e.printStackTrace();
}

Начиная с Java 7, вы также можете перехватывать несколько исключений в одном блоке catch, как показано в следующем примере. Это полезно, когда у вас есть одинаковый код во всех блоках catch.

public static void foo(int x) throws IllegalArgumentException, NullPointerException {
	// некоторый код
}

public static void main(String[] args) {
	try {
		foo(10);
	} catch (IllegalArgumentException | NullPointerException e) {
		System.out.println(e.getMessage());
	}
}

31. Напишите программу на Java, чтобы показать NullPointerException.

Если вы вызываете функцию на null, она вызовет исключение NullPointerException, как показано в следующем примере кода:

public static void main(String[] args) {
	printString(null, 3);
	
}

static void printString(String s, int count) {
	for (int i = 0; i < count; i++) {
		System.out.println(s.toUpperCase()); // Exception in thread "main" java.lang.NullPointerException
	}
}

Для ранней проверки следует использовать проверку на null, как показано в следующем примере кода:

static void printString(String s, int count) {
	if (s == null) return;
	for (int i = 0; i < count; i++) {
		System.out.println(s.toUpperCase());
	}
}

В зависимости от требований проекта также можно выбросить IllegalArgumentException.

32. Как создать запись (record) в Java?

Записи (records) были добавлены в стандартную библиотеку Java начиная с версии 16. Записи позволяют создавать классы POJO с минимальным кодом. Записи автоматически генерируют методы hashCode(), equals(), getter и toString() для класса. Записи являются финальными (final) и неявно наследуют класс java.lang.Record. В следующем примере кода показан один из способов создания записи:

import java.util.Map;
 
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
}

Узнайте больше о записях в Java. Подробности о POJO можно найти на странице Plain old Java object в Википедии.

33. Как создать текстовые блоки в Java?

В Java 15 добавлена функция текстовых блоков. Вы можете создавать многострочные строки с помощью текстовых блоков. Многострочная строка должна быть написана внутри тройных двойных кавычек, как показано в следующем примере:

String textBlock = """
		Hi
		Hello
		Yes""";

Это то же самое, что и создание строки, например, Hi\\nHello\\nYes.

34. Приведите пример выражений switch и множественных меток case в Java.

Выражения switch были добавлены как стандартная функция в Java 14. В следующих примерах показаны выражения switch, а также множественные метки case:

int choice = 2;

int x = switch (choice) {
    case 1, 2, 3:
	    yield choice;
    default:
	    yield -1;
};

System.out.println("x = " + x); // x = 2

Также можно использовать лямбда-выражения в выражениях switch.

String day = "TH";
String result = switch (day) {
    case "M", "W", "F" -> "MWF";
    case "T", "TH", "S" -> "TTS";

    default -> {
	    if (day.isEmpty())
		    yield "Please insert a valid day.";
	    else
		    yield "Looks like a Sunday.";
    }
};

System.out.println(result); // TTH

35. Как скомпилировать и запустить Java-класс из командной строки?

В данном примере используется следующий Java-файл:

public class Test {

public static void main(String args[]) {
		System.out.println("Hi");
	}

}

Вы можете скомпилировать его, используя следующую команду в терминале:

  1. javac Test.java

Для запуска класса используйте следующую команду в терминале:

  1. java Test

В последних версиях команда java также будет компилировать программу, если файл класса отсутствует. Если класс находится в пакете, например, com.example, то он должен находиться в папке com/example. Команда для компиляции и запуска выглядит следующим образом:

  1. java com/example/Test.java

Если вашему классу требуются дополнительные JAR-файлы для компиляции и запуска, вы можете использовать опцию java -cp. Например:

  1. java -cp .:~/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar com/example/Test.java

36. Как создать перечисление (enum) в Java?

Приведенный ниже пример кода показывает, как создать базовое перечисление (enum):

public enum ThreadStates {
	START,
	RUNNING,
	WAITING,
	DEAD;
}

ThreadStates – это перечисление с константными полями START, RUNNING, WAITING и DEAD. Все перечисления неявно расширяют класс java.lang.Enum и реализуют интерфейсы Serializable и Comparable. Перечисления также могут иметь методы. Узнайте больше о перечислениях в Java.

37. Как использовать метод forEach() в Java?

Метод forEach() предоставляет сокращенный способ выполнить действие для всех элементов перечисления. В следующем примере показано, как перебрать элементы списка и вывести их:

List<String> list = new ArrayList<>();

Iterator<String> it = list.iterator();

while (it.hasNext()) {
	System.out.println(it.next());
}

Вы можете использовать метод forEach() с лямбда-выражением для сокращения размера кода, как показано в следующем примере:

List<String> list = new ArrayList<>();

list.forEach(System.out::print);

38. Как написать интерфейс с методами default и static?

Java 8 ввела введение методов по умолчанию и статических методов в интерфейсы. Это сократило разрыв между интерфейсами и абстрактными классами. Приведенный ниже пример кода показывает один из способов написания интерфейса с использованием default и static методов:

public interface Interface1 {
	
	// обычный абстрактный метод
	void method1(String str);
	
	default void log(String str) {
		System.out.println("I1 logging::" + str);
	}
	
	static boolean isNull(String str) {
		System.out.println("Interface Null Check");

		return str == null ? true : "".equals(str) ? true : false;
	}

}

Узнайте больше о default и static методах в интерфейсах в изменениях интерфейса Java 8.

39. Как создать функциональный интерфейс?

Интерфейс с ровно одним абстрактным методом называется функциональным интерфейсом. Основное преимущество функциональных интерфейсов заключается в том, что вы можете использовать лямбда-выражения для их инстанцирования и избегать использования громоздкой анонимной реализации класса. Аннотация @FunctionalInterface указывает на функциональный интерфейс, как показано в следующем примере кода:

@FunctionalInterface
interface Foo {
	void test();
}

40. Приведите пример использования лямбда-выражений в Java.

Runnable – отличный пример функционального интерфейса. Вы можете использовать лямбда-выражения для создания запускаемого кода, как показано в следующем примере кода:

Runnable r1 = () -> System.out.println("My Runnable");

41. Покажите примеры перегрузки и переопределения в Java.

Когда у класса есть два или более метода с одинаковым именем, они называются перегруженными методами. В следующем примере кода показан перегруженный метод с именем print:

class Foo {
	void print(String s) {
		System.out.println(s);
	}

	void print(String s, int count) {
		while (count > 0) {
			System.out.println(s);
			count--;
		}
	}

}

Когда метод суперкласса также реализуется в дочернем классе, это называется переопределением. В следующем примере кода показано, как аннотировать метод printname(), который реализован в обоих классах:

class Base {
	void printName() {
		System.out.println("Base Class");
	}
}

class Child extends Base {
	@Override
	void printName() {
		System.out.println("Child Class");
	}
}

Узнайте больше о переопределении и перегрузке в Java.

42.-49. Угадайте вывод

Проверьте себя, угадывая вывод следующих кодовых фрагментов.


String s1 = "abc";
String s2 = "abc";

System.out.println("s1 == s2 is:" + s1 == s2);
Output
false

Вывод данного выражения false, потому что оператор + имеет более высокий приоритет, чем оператор ==. Таким образом, данное выражение вычисляется как “s1 == s2 is:abc” == “abc”, что является false.


String s3 = "JournalDev";
int start = 1;
char end = 5;

System.out.println(s3.substring(start, end));
Output
ourn

Вывод данного выражения – ourn. Первый символ автоматически приводится к типу int. Затем, так как индекс первого символа равен 0, он начинает печатать с символа o и продолжает до символа n. Обратите внимание, что метод String substring создает подстроку, начинающуюся с индекса start и расширяющуюся до символа с индексом end - 1.


HashSet shortSet = new HashSet();

	for (short i = 0; i < 100; i++) {
    shortSet.add(i);
    shortSet.remove(i - 1);
}

System.out.println(shortSet.size());
Output
100

Размер shortSet равен 100. В Java функция автоупаковки означает, что выражение i, имеющее примитивный тип short, преобразуется в объект типа Short. Аналогично, выражение i - 1 имеет примитивный тип int и автоматически упаковывается в объект типа Integer. Поскольку в HashSet нет объекта типа Integer, ничего не удаляется, и размер остается равным 100.


try {
	if (flag) {
  		while (true) {
   		}
   	} else {
   		System.exit(1);
   	}
} finally {
   	System.out.println("In Finally");
}
Output

Нет вывода. Этот код приводит к бесконечному циклу, если флаг равен true, и программа завершается, если флаг равен false. Блок finally никогда не будет достигнут.


String str = null;
String str1="abc";

System.out.println(str1.equals("abc") | str.equals(null));
Output
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "<local1>" is null

Данный оператор печати вызовет java.lang.NullPointerException, потому что логический оператор OR вычисляет оба операнда перед возвращением результата. Поскольку str равно null, метод .equals() вызовет исключение. Всегда рекомендуется использовать логические операторы с короткой цепочкой, такие как || и &&, которые вычисляют значения операндов слева направо. В этом случае, так как первый операнд вернет true, второй операнд будет пропущен.


String x = "abc";
String y = "abc";

x.concat(y);

System.out.print(x);
Output
abc

x.concat(y) создает новую строку, но не назначает ее x, поэтому значение x не изменяется.


public class MathTest {

 	public void main(String[] args) {  		
   		int x = 10 * 10 - 10;
   		
   		System.out.println(x);
   	}
   
}
Output
Error: Main method is not static in class MathTest, please define the main method as:
   public static void main(String[] args)

Хотя может показаться, что вопрос касается порядка выполнения математических операторов, на самом деле вопрос в том, чтобы заметить, что метод main не был объявлен static.


public class Test {
   
  	public static void main(String[] args) {
   		try {
   			throw new IOException("Hello");
   		} catch(IOException | Exception e) {
   			System.out.println(e.getMessage());
   		}
   	}
}
Output
Test.java:5: error: cannot find symbol
   			throw new IOException("Hello");
   			          ^
  symbol:   class IOException
  location: class Test
Test.java:6: error: cannot find symbol
   		}catch(IOException | Exception e) {
   		       ^
  symbol:   class IOException
  location: class Test
2 errors

Этот код приводит к ошибке времени компиляции. Исключение IOException уже перехвачено альтернативным исключением Exception.

50. Найдите 5 ошибок в следующем фрагменте кода.

package com.digitalocean.programming-interviews;

public class String Programs {

	static void main(String[10] args) {
		String s = "abc"
		System.out.println(s);
	}
}
Answers
  1. Имя пакета не может содержать дефисы.
  2. Имя класса не может содержать пробелы.
  3. Метод main не является public, поэтому он не будет выполняться.
  4. Аргумент метода main не должен указывать размер.
  5. В определении строки отсутствует точка с запятой.

Вывод

Этот набор из 50 вопросов по программированию на языке Java включает вопросы от начального до экспертного уровня, чтобы помочь вам подготовиться к собеседованию.

Рекомендуемая литература:

Source:
https://www.digitalocean.com/community/tutorials/java-programming-interview-questions