В чем разница между List и IList в Java?

«В чем разница между List и IList в Java?» — вопрос из категории Java, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Java такого прямого разделения List vs IList нет. Вероятно, вопрос относится к C#/.NET. В Java аналогом будет разница между конкретной реализацией List (например, ArrayList) и интерфейсом List.

  • List<E> (интерфейс): Это контракт, который определяет, какие методы должны быть у списка (add(), get(), remove(), size() и т.д.). Он не содержит реализации.
  • ArrayList<E> (конкретная реализация): Это класс, который реализует интерфейс List с использованием динамического массива.

Практическое значение для тестирования в Java:

// Рекомендуемый подход: объявлять переменные через интерфейс.
// Это делает код гибким и упрощает мокирование в unit-тестах.
List<String> userNames = new ArrayList<>();

// В тестах мы можем легко подменить реализацию на заглушку (mock/stub).
@Test
public void testUserService() {
    // Создаем mock-список с помощью Mockito
    List<User> mockUserList = Mockito.mock(List.class);
    Mockito.when(mockUserList.size()).thenReturn(5);

    // Передаем mock в тестируемый сервис
    UserService service = new UserService(mockUserList);
    int count = service.getUserCount();

    assertEquals(5, count);
    Mockito.verify(mockUserList).size(); // Проверяем, что метод был вызван
}

// Другие реализации интерфейса List, полезные в тестах:
List<String> fixedList = Arrays.asList("A", "B", "C"); // Неизменяемый список
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>()); // Для многопоточных тестов

Итог: В Java мы почти всегда работаем с интерфейсом List в объявлениях типов. Это принцип "кодирования на уровне интерфейсов", который повышает гибкость кода и значительно облегчает его модульное тестирование, позволяя подменять реальные коллекции на контролируемые заглушки.