Menu

C# или Java: синтаксис, платформа, обобщения, LINQ и что учить

C# и Java похожи и решают похожие задачи. Настоящие различия в свойствах, типах значений, обобщениях, LINQ против стримов, async, исключениях и экосистемах вокруг них. Сравнение бок о бок с кодом.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

C# и Java близкие родственники. Оба статически типизированы, объектно-ориентированы, используют сборку мусора и синтаксис в стиле C, оба компилируются в байт-код для виртуальной машины и оба применяются в крупных серверных системах. C# вышел в 2002 году отчасти как ответ Microsoft на Java, и за двадцать с лишним лет языки заимствовали друг у друга возможности (лямбды, обобщения, записи, сопоставление с образцом). Разработчик, знающий один из них, почти сразу может читать другой.

Различия, важные в повседневной работе, меньше и конкретнее. На этой странице они разобраны с кодом: фрагменты на C# можно запустить, а Java показана в статичных блоках для сравнения.

Коротко

C#Java
СоздательMicrosoft (2002)Sun Microsystems (1995), сейчас Oracle
Среда выполненияCLR (.NET), компилирует IL в нативный кодJVM, компилирует байт-код в нативный код
ПлатформыWindows, Linux, macOSWindows, Linux, macOS
СвойстваВстроены в язык: public int Age { get; set; }Методы-геттеры и сеттеры
Пользовательские типы значенийstructПока нет (Project Valhalla)
ОбобщенияРеифицированные: типы существуют во время выполненияСтираемые: типы удаляются после компиляции
Запросы к коллекциямLINQStreams API
Асинхронностьasync / awaitВиртуальные потоки (Java 21), CompletableFuture
Проверяемые исключенияНетДа
Перегрузка операторовДаНет
Защита от nullСсылочные типы, допускающие null (C# 8)Optional<T>, аннотации
Основные областиИгры на Unity, ASP.NET Core, настольные приложения Windows, AzureКорпоративные бэкенды, Android, большие данные

Синтаксис: почти одинаковый

Классы, методы, if, for, while, switch, try/catch выглядят почти идентично. Видимые различия в соглашениях об именовании и нескольких ключевых словах: методы в C# пишутся в PascalCase (ToUpper, WriteLine), в Java в camelCase (toUpperCase, println); в C# пишут string и bool, в Java String и boolean; наследование в C# записывается как class Dog : Animal, а в Java как class Dog extends Animal.

// Java
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Ana");
        names.add("Ben");
        for (String n : names) {
            System.out.println(n.toUpperCase());
        }
    }
}

Вывод:

ANA
BEN

Кроме того, в C# == сравнивает строки по значению, что убирает одну из классических ошибок новичков в Java: там == для двух объектов String сравнивает ссылки, поэтому две равные строки, созданные во время выполнения (прочитанные из ввода или склеенные), могут оказаться неравными.

Свойства вместо геттеров и сеттеров

Классы Java открывают состояние через методы getName() и setName(), которые обычно генерирует IDE или Lombok. В C# есть свойства: члены, которые читаются как поля, но выполняют код.

// Java
public class Product {
    private double price;
    public double getPrice() { return price; }
    public void setPrice(double price) {
        if (price < 0) throw new IllegalArgumentException("negative");
        this.price = price;
    }
}

Вывод:

Mug: 9.50

Инициализатор объекта new Product { Name = ..., Price = ... } задаёт свойства сразу после создания. Записи в Java (Java 16) покрывают случай неизменяемых данных; в C# тоже есть записи (C# 9), а для всего остального свойства.

Типы значений: структуры

В Java каждый пользовательский тип является ссылочным и хранится в куче; значениями являются только восемь примитивов (int, double, ...). C# позволяет определять собственные типы значений через struct. Структура копируется при присваивании и может храниться прямо внутри массивов и других объектов без отдельного выделения в куче.

Вывод:

a = (1, 2)
b = (99, 2)
1000

Это важно в играх и численном коде, где миллионы маленьких объектов нагружали бы сборщик мусора. См. структуры.

Обобщения: реифицированные и стираемые

Java стирает аргументы обобщённых типов при компиляции: во время выполнения List<Integer> это просто List, а List<int> запрещён (вы получаете упакованные объекты Integer). C# сохраняет аргументы типов во время выполнения, поэтому List<int> хранит обычные int, а код может узнать, что такое T.

Вывод:

3 items of type Int32
1 items of type String
List`1

typeof(T) и new T() работают, потому что среда выполнения знает T. В Java и то и другое вызывает ошибку компиляции, а обычный обходной путь передавать повсюду объект Class<T>.

LINQ и стримы

В обоих языках есть текучий API для фильтрации и преобразования коллекций. В Java это Streams API (Java 8), в C# это LINQ (C# 3), у которого есть ещё и синтаксис запросов и который работает с базами данных через Entity Framework.

// Java
List<String> expensive = products.stream()
    .filter(p -> p.getPrice() > 20)
    .sorted(Comparator.comparing(Product::getPrice))
    .map(Product::getName)
    .collect(Collectors.toList());

Вывод:

Lamp, Chair
Total: 126

Операции соответствуют друг другу один к одному (filter это Where, map это Select, collect(toList()) это ToList()), а версиям на C# не нужны ни stream(), ни коллектор. Объекты new { Name = ..., Price = ... } это анонимные типы, у которых нет прямого аналога в Java.

Асинхронность и конкурентность

C# представил async/await в 2012 году: метод async возвращает Task, а await приостанавливает его, не блокируя поток. Позже те же ключевые слова переняли JavaScript, Python и Rust. Java пошла другим путём: цепочки CompletableFuture, а начиная с Java 21 виртуальные потоки, которые делают обычный блокирующий код дешёвым.

// C#
async Task<string> LoadAsync(HttpClient http, string url)
{
    string body = await http.GetStringAsync(url);
    return body.Substring(0, 100);
}
// Java 21 with virtual threads: plain blocking code on a cheap thread
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> client.send(request, BodyHandlers.ofString()));
}

Оба подхода масштабируются на множество одновременных запросов. C# делает асинхронность видимой в сигнатурах методов, а Java прячет её в среде выполнения.

Исключения, операторы и мелкие различия

  • Проверяемые исключения. Java заставляет метод объявлять или перехватывать определённые исключения (throws IOException). В C# проверяемых исключений нет вообще.
  • Перегрузка операторов. C# позволяет типам определять +, ==, < и другие операторы, поэтому арифметика с decimal и DateTime читается естественно. В Java этого нет (BigDecimal.add).
  • Виртуальность по умолчанию. Методы Java можно переопределять, если они не помечены final; методы C# нужно пометить virtual, чтобы их можно было переопределить, а переопределение должно содержать override.
  • Методы расширения. C# может добавлять методы к существующим типам ("text".IsPalindrome()); Java не может.
  • Типы значений, допускающие null. int? в C# это int, который может быть null; в Java используется упакованный Integer.
  • Беззнаковые типы. В C# есть uint, ulong, ushort и беззнаковый byte; в Java byte знаковый, и, кроме 16-битного char, беззнаковых целых типов нет.

Экосистема, вакансии и что учить

Экосистема Java больше в мире открытого серверного ПО: Spring, Kafka, Spark, Hadoop, Elasticsearch и большинство проектов Apache написаны на Java. Приложения для Android пишут на Kotlin или Java. У C# более цельный стек: один производитель поддерживает язык, среду выполнения, веб-фреймворк (ASP.NET Core), ORM (Entity Framework) и основную IDE (Visual Studio), а Unity ставит его в центр разработки игр.

У обоих языков большой рынок труда, а баланс между ними зависит от региона и отрасли. C# силён в компаниях на Microsoft и Azure, в финансовом и медицинском ПО и в игровых студиях.

Выбирайте C#, если хотите делать игры на Unity, настольные приложения для Windows или работать в компании на .NET. Выбирайте Java, если цель Android, большие данные или компания с бэкендом на JVM. Любой из них научит понятиям, которые нужны для другого: классам, интерфейсам, обобщениям, коллекциям, исключениям и среде выполнения со сборкой мусора.

Часто задаваемые вопросы

Похож ли C# на Java?

Да, очень. Оба языка статически типизированы, объектно-ориентированы, используют сборку мусора, имеют синтаксис в стиле C и компилируются в байт-код для виртуальной машины. Разработчик на Java может читать код на C# с первого дня. Различия в деталях: в C# есть свойства, пользовательские типы значений, обобщения, сохраняющие типы во время выполнения, LINQ и async/await, а в Java есть проверяемые исключения и более крупная экосистема открытых серверных проектов.

Что учить первым, C# или Java?

Выбирайте по тому, что хотите делать. C# для игр на Unity, настольных приложений для Windows и компаний, построенных на Microsoft и Azure. Java для Android (вместе с Kotlin), крупных корпоративных бэкендов и инструментов больших данных вроде Kafka и Spark. Языки настолько близки, что переход потом займёт недели, а не месяцы.

C# быстрее Java?

Они в одном классе производительности: оба JIT-компилируются в нативный код и используют сборщики мусора с поколениями. C# даёт больше низкоуровневого контроля через структуры, Span<T> и обобщения над типами значений без упаковки, что помогает в коде с большим количеством выделений памяти. В типичных веб-нагрузках фреймворк и база данных значат гораздо больше, чем язык.

Есть ли в C# проверяемые исключения, как в Java?

Нет. В C# ни одно исключение не обязательно объявлять или перехватывать; сигнатура метода не перечисляет, что он выбрасывает. Авторы языка решили, что проверяемые исключения приводят к пустым блокам catch и хрупким сигнатурам. Вместо этого исключения документируют XML-комментариями /// <exception>.

Где больше вакансий, в C# или в Java?

У обоих языков большой рынок труда, а то, где вакансий больше, зависит от страны и отрасли, поэтому смотрите объявления там, где хотите работать. C# силён в корпоративных компаниях на стеке Microsoft, в финансах, медицине и игровых студиях, Java в крупных банках, телекоме, бэкендах интернет-магазинов и Android.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ