Java и C — два языка с похожим синтаксисом (фигурные скобки, for, if, типы int и long), но с разной моделью исполнения. Программа на C компилируется в машинный код конкретного процессора и сама управляет памятью. Программа на Java компилируется в байткод, который выполняет виртуальная машина JVM, а память освобождает сборщик мусора.
Содержание
- Короткий словарь перед сравнением
- Один пример на двух языках
- Отличие 1: память — вручную или сборщик мусора
- Отличие 2: проверка границ массива
- Отличие 3: машинный код и байткод
- Отличие 4: указатели и ссылки
- Таблица различий Java и C
- Что такое Java Core в вакансиях
- Выводы
- Где применяется / связь с практикой
- FAQ
Ниже разберем главные отличия на одном и том же примере, сведем их в таблицу и отдельно объясним, что работодатели имеют в виду под Java Core — это не отдельный язык, а обозначение базового уровня Java. Примеры проверены 23.09.2026: C — Apple clang 21 (macOS, arm64), Java — OpenJDK 25.0.4 (образ eclipse-temurin:25-jdk).
Короткий словарь перед сравнением
- Машинный код — инструкции конкретного процессора (x86-64, ARM64). Исполняемый файл под одну архитектуру и ОС на другой не запустится.
- Байткод — инструкции виртуальной машины Java, одинаковые для всех платформ. Файл
.classзапускается там, где есть JVM подходящей версии. - JVM, JRE, JDK — JVM исполняет байткод; JRE — JVM плюс стандартная библиотека для запуска; JDK — JRE плюс инструменты разработчика (компилятор
javac,javap,jar). Для разработки ставят JDK. - Указатель (C) — переменная, хранящая адрес в памяти, с которым можно делать арифметику. Ссылка (Java) — способ обратиться к объекту без доступа к адресу.
Один пример на двух языках
Задача: выделить массив из 5 чисел, заполнить квадратами индексов и посчитать сумму. Сначала C:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n = 5;
int *a = malloc(n * sizeof *a); /* память под 5 int - вручную */
if (a == NULL) {
return 1; /* malloc может вернуть NULL */
}
for (int i = 0; i < n; i++) {
a[i] = i * i;
}
long sum = 0;
for (int i = 0; i < n; i++) {
sum += a[i];
}
printf("sum = %ld\n", sum);
free(a); /* и освободить - тоже вручную */
return 0;
}
Сборка и запуск: cc -std=c17 -Wall -Wextra -o sum sum.c && ./sum. Программа выведет sum = 30 (0 + 1 + 4 + 9 + 16). Тот же алгоритм на Java:
public class Sum {
public static void main(String[] args) {
int n = 5;
int[] a = new int[n]; // память выделяет JVM
for (int i = 0; i < n; i++) {
a[i] = i * i;
}
long sum = 0;
for (int i = 0; i < n; i++) {
sum += a[i];
}
System.out.println("sum = " + sum);
} // free не нужен: объект соберет GC
}
Запуск: javac Sum.java && java Sum, результат тот же — sum = 30. Синтаксис почти совпадает, различия — вокруг кода.
Отличие 1: память — вручную или сборщик мусора
В C программист сам запрашивает память (malloc) и сам ее возвращает (free). Забыл free — утечка. Вызвал free дважды или обратился к памяти после free — неопределенное поведение: программа может упасть, а может работать и портить данные.
В Java объект создается через new, а освобождает память сборщик мусора (GC), когда на объект не осталось ссылок. Граница упрощения: утечки в Java тоже бывают — если объект держит, например, статическая коллекция, GC его не соберет. Java избавляет от ручного free, но не от необходимости думать о памяти.
Отличие 2: проверка границ массива
Внесем одну ошибку в оба примера — во втором цикле условие i <= n вместо i < n, то есть обращение к несуществующему a[5].
Результат в C (clang 21, macOS arm64, без дополнительных флагов): программа молча вывела sum = 30 и завершилась с кодом 0. Ошибка есть, но не видна: C не проверяет границы, чтение за концом массива — неопределенное поведение, и на другой машине или с другим компилятором результат может быть иным. Найти такую ошибку помогает сборка с санитайзером -fsanitize=address:
==91029==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000001c74 ...
READ of size 4 at 0x603000001c74 thread T0
#0 0x000100c5896c in main bad.c:15
Результат в Java — та же ошибка останавливает программу с понятным сообщением:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
at Sum.main(Sum.java:10)
Исправление в обоих языках — вернуть i < n. Разница в том, что JVM проверяет индекс при обращении к массиву, а C оставляет это программисту и инструментам.
Отличие 3: машинный код и байткод
Компилятор C превращает sum.c в исполняемый файл под конкретную платформу. Команда file sum на Mac с процессором Apple показывает Mach-O 64-bit executable arm64 — этот файл не запустится ни на Windows, ни на Linux x86-64. Исходник C переносим, если не использует платформенных API, но его надо пересобрать под каждую целевую систему.
javac создает Sum.class с байткодом. Посмотреть его можно командой javap -c Sum, начало метода main выглядит так:
public static void main(java.lang.String[]);
Code:
0: iconst_5
1: istore_1
2: iload_1
3: newarray int
Это инструкции JVM, а не процессора: тот же .class запускается на Windows, Linux и macOS с JVM подходящей версии. Внутри JVM байткод сначала интерпретируется, а часто исполняемые участки JIT-компилятор переводит в машинный код во время работы программы. Поэтому корректнее говорить не «Java интерпретируемая», а «Java компилируется в байткод, который JVM исполняет с JIT-компиляцией».
Отличие 4: указатели и ссылки
В C можно получить адрес переменной и изменить ее через этот адрес — так функция меняет значения вызывающего кода:
#include <stdio.h>
void swap(int *x, int *y) { /* получаем адреса переменных */
int t = *x;
*x = *y;
*y = t;
}
int main(void) {
int a = 1, b = 2;
swap(&a, &b); /* передаем адреса a и b */
printf("a = %d, b = %d\n", a, b);
return 0;
}
Вывод: a = 2, b = 1. В Java указателей нет: адрес объекта не получить, арифметику над ссылкой не сделать. Все аргументы передаются по значению, для объектов копируется ссылка. Поэтому метод может изменить поля объекта, но не может заменить сам объект у вызывающего:
public class Box {
int value;
static void set(Box b) { b.value = 42; } // меняем объект по ссылке
static void replace(Box b) { b = new Box(); b.value = 7; } // меняем копию ссылки
public static void main(String[] args) {
Box box = new Box();
set(box);
replace(box);
System.out.println(box.value);
}
}
Программа печатает 42: set изменил объект, а replace поменял только свою локальную копию ссылки. Написать swap для двух int на Java так, как в C, нельзя.
Таблица различий Java и C
| Критерий | C | Java |
|---|---|---|
| Результат компиляции | Машинный код под ОС и процессор | Байткод для JVM |
| Переносимость | Исходника — при пересборке; бинарника — нет | .class работает на любой JVM подходящей версии |
| Память | Вручную: malloc / free |
new + сборщик мусора |
| Указатели | Есть, с арифметикой | Нет, только ссылки на объекты |
| Границы массива | Не проверяются (неопределенное поведение) | Проверяются, ArrayIndexOutOfBoundsException |
Размер int |
Зависит от реализации (минимум 16 бит) | Всегда 32 бита |
| Парадигма | Процедурная, классов нет | Объектно-ориентированная, есть лямбды и Stream API |
| Обработка ошибок | Коды возврата, errno |
Исключения try / catch |
goto |
Есть | Зарезервированное слово, не используется |
| Типичные задачи | ОС, драйверы, встраиваемые системы, среды исполнения | Серверные приложения, корпоративные системы, Android, обработка данных |
Про скорость без абсолютов: у программы на C обычно меньше время старта и расход памяти, долго работающий сервис на Java после прогрева JIT часто приближается к нативному коду. Итог зависит от задачи, и его измеряют, а не выводят из названия языка.
Что такое Java Core в вакансиях
Java Core — неофициальное название базового уровня Java, которым пользуются работодатели и курсы. В документации Oracle такого термина нет: официально платформа называется Java SE (Standard Edition), корпоративные спецификации — Jakarta EE (раньше Java EE). «Знание Java Core» в вакансии обычно означает уверенную работу с языком и стандартной библиотекой без фреймворков.
Что под этим чаще всего проверяют на собеседовании:
| Блок | Что нужно уметь |
|---|---|
| Синтаксис и типы | Примитивы и ссылочные типы, String и его неизменяемость, equals / hashCode |
| ООП | Классы, интерфейсы, наследование, инкапсуляция, полиморфизм |
| Исключения | Checked и unchecked, try-with-resources |
| Коллекции | List, Set, Map, выбор реализации, обобщенные типы (generics) |
| Функциональный стиль | Лямбды, Stream API, Optional |
| Многопоточность | Thread, ExecutorService, синхронизация, java.util.concurrent |
| JVM | Стек и куча, сборка мусора на уровне понятий, путь от .java до .class |
Состав у компаний разный: где-то добавляют ввод-вывод и java.time, где-то многопоточность выносят отдельно. После Java Core обычно идут фреймворки (Spring), базы данных и сборка проекта (Maven, Gradle). Встречающееся в поиске сочетание «Java C» языком не является — так ищут либо сравнение Java и C, либо C#.
Выводы
- C компилируется в машинный код под конкретную платформу, Java — в байткод, который исполняет JVM с JIT-компиляцией.
- В C память освобождают вручную, в Java — сборщик мусора, но утечки через забытые ссылки в Java тоже возможны.
- C не проверяет границы массива и позволяет работать с адресами через указатели; Java проверяет индексы и дает только ссылки.
- Java Core — неофициальное название базового уровня Java SE: синтаксис, ООП, исключения, коллекции, лямбды и Stream API, многопоточность, основы JVM.
Где применяется / связь с практикой
Понимание, что делает за программиста JVM, помогает на собеседованиях и при поиске ошибок с памятью. Если цель — работать на Java, логичный старт — блоки из таблицы Java Core, закрепленные на небольших проектах. Подробнее о самом языке — в статье Java: что это за язык и зачем он нужен, а про то, как исходный код превращается в исполняемый, — в материале Компиляторы: этапы компиляции и виды.
Освойте тему на практике
Базу Java с практикой и проверкой заданий разбирают на курсе Java Developer. Basic. Чтобы сначала посмотреть формат, подойдут бесплатные открытые уроки Otus.
FAQ
Можно ли вызвать код на C из Java?
Да. Исторически для этого служит JNI, а в современных версиях есть Foreign Function & Memory API (финальный с Java 22), который позволяет вызывать нативные функции без написания C-оберток.
Нужно ли знать C, чтобы учить Java?
Нет, Java можно учить первым языком. Знание C помогает понять, что происходит с памятью и почему JVM проверяет границы массивов, но это не обязательное условие.
Java Core и Java SE — одно и то же?
Близко, но не совсем. Java SE — официальная платформа со всей стандартной библиотекой, а Java Core — разговорное обозначение той ее части, которую ждут от начинающего разработчика.



