Menu

C# ou Java : syntaxe, runtime, génériques, LINQ et lequel apprendre

C# et Java se ressemblent et résolvent des problèmes similaires. Les vraies différences tiennent aux propriétés, aux types valeur, aux génériques, à LINQ face aux streams, à l'asynchrone, aux exceptions et aux écosystèmes. Une comparaison côte à côte avec du code.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

C# et Java sont de proches parents. Tous deux sont des langages orientés objet, à typage statique et à ramasse-miettes, avec une syntaxe de style C ; tous deux sont compilés en bytecode pour une machine virtuelle et servent à de grands systèmes backend. C# est sorti en 2002, en partie comme la réponse de Microsoft à Java, et en deux décennies les deux langages se sont emprunté des fonctionnalités (lambdas, génériques, records, pattern matching). Un développeur qui connaît l'un peut lire l'autre presque immédiatement.

Les différences qui comptent au quotidien sont plus petites et plus précises. Cette page les passe en revue avec du code : des extraits C# que vous pouvez exécuter, et du Java dans des blocs statiques pour comparer.

En un coup d'œil

C#Java
Créé parMicrosoft (2002)Sun Microsystems (1995), aujourd'hui Oracle
RuntimeCLR (.NET), compile l'IL en code natifJVM, compile le bytecode en code natif
PlateformesWindows, Linux, macOSWindows, Linux, macOS
PropriétésIntégrées : public int Age { get; set; }Méthodes getter et setter
Types valeur définis par l'utilisateurstructPas encore (Project Valhalla)
GénériquesRéifiés : les types existent à l'exécutionEffacés : les types disparaissent après compilation
Interroger des collectionsLINQAPI Streams
Asynchroneasync / awaitThreads virtuels (Java 21), CompletableFuture
Exceptions vérifiéesNonOui
Surcharge d'opérateursOuiNon
Sûreté vis-à-vis de nullTypes référence nullables (C# 8)Optional<T>, annotations
Usages principauxJeux Unity, ASP.NET Core, bureau Windows, AzureBackends d'entreprise, Android, big data

Syntaxe : presque identique

Les classes, méthodes, if, for, while, switch, try/catch se lisent presque de la même façon. Les différences visibles tiennent aux conventions de nommage et à quelques mots-clés : les méthodes C# sont en PascalCase (ToUpper, WriteLine), les méthodes Java en camelCase (toUpperCase, println) ; C# écrit string et bool, Java String et boolean ; l'héritage s'écrit class Dog : Animal en C# et class Dog extends Animal en Java.

// 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());
        }
    }
}

Sortie :

ANA
BEN

C# compare aussi les chaînes par valeur avec ==, ce qui élimine l'un des bugs de débutant classiques de Java : en Java, == sur deux objets String compare des références, donc deux chaînes égales construites à l'exécution (lues depuis une saisie, concaténées) peuvent être jugées différentes.

Des propriétés au lieu des getters et setters

Les classes Java exposent leur état via des méthodes getName() et setName(), souvent générées par un IDE ou Lombok. C# a des propriétés : des membres qui se lisent comme des champs mais exécutent du code.

// 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;
    }
}

Sortie :

Mug: 9.50

L'initialiseur d'objet new Product { Name = ..., Price = ... } définit les propriétés juste après la construction. Les records Java (Java 16) couvrent le cas des données immuables ; C# a aussi des records (C# 9), plus les propriétés pour tout le reste.

Les types valeur : les structs

En Java, chaque type défini par l'utilisateur est un type référence stocké sur le tas ; seuls les huit types primitifs (int, double, ...) sont des valeurs. C# permet de définir vos propres types valeur avec struct. Une struct est copiée à l'affectation et peut être stockée directement dans des tableaux et d'autres objets, sans allocation séparée sur le tas.

Sortie :

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

C'est important dans les jeux et le code numérique, où des millions de petits objets mettraient le ramasse-miettes sous pression. Voir structs.

Génériques : réifiés ou effacés

Java efface les arguments de type génériques à la compilation : à l'exécution, une List<Integer> n'est qu'une List, et List<int> n'est pas autorisé (on obtient des objets Integer boxés). C# conserve les arguments de type à l'exécution, donc List<int> stocke des ints bruts et le code peut demander ce qu'est T.

Sortie :

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

typeof(T) et new T() fonctionnent parce que le runtime connaît T. En Java, ce sont deux erreurs de compilation, et le contournement habituel consiste à faire circuler un objet Class<T>.

LINQ ou streams

Les deux langages ont une API fluide pour filtrer et transformer des collections. Celle de Java est l'API Streams (Java 8) ; celle de C# est LINQ (C# 3), qui a aussi une syntaxe de requête et fonctionne sur les bases de données via Entity Framework.

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

Sortie :

Lamp, Chair
Total: 126

Les opérations se correspondent une à une (filter est Where, map est Select, collect(toList()) est ToList()), et les versions C# n'ont besoin ni de stream() ni de collecteur. Les objets new { Name = ..., Price = ... } sont des types anonymes, qui n'ont pas d'équivalent direct en Java.

Asynchrone et concurrence

C# a introduit async/await en 2012 : une méthode async renvoie une Task, et await la suspend sans bloquer de thread. JavaScript, Python et Rust ont ensuite adopté les mêmes mots-clés. Java a pris une autre voie : les chaînes de CompletableFuture et, depuis Java 21, les threads virtuels qui rendent peu coûteux le code bloquant ordinaire.

// 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()));
}

Les deux approches tiennent la charge de nombreuses requêtes concurrentes. C# rend l'asynchronisme visible dans les signatures de méthode ; Java le cache dans le runtime.

Exceptions, opérateurs et petites différences

  • Exceptions vérifiées. Java oblige une méthode à déclarer ou intercepter certaines exceptions (throws IOException). C# n'a aucune exception vérifiée.
  • Surcharge d'opérateurs. C# permet aux types de définir +, ==, < et compagnie, c'est pourquoi l'arithmétique sur decimal et DateTime se lit naturellement. Java ne le permet pas (BigDecimal.add).
  • Virtuel par défaut. Les méthodes Java peuvent être redéfinies sauf si elles sont marquées final ; les méthodes C# doivent être marquées virtual pour être redéfinissables, et la redéfinition doit indiquer override.
  • Méthodes d'extension. C# peut ajouter des méthodes à des types existants ("text".IsPalindrome()) ; Java ne le peut pas.
  • Types valeur nullables. int? en C# est un int qui peut valoir null ; Java utilise le type boxé Integer.
  • Types non signés. C# a uint, ulong, ushort et un byte non signé ; le byte de Java est signé et, à part le char 16 bits, Java n'a pas de type entier non signé.

Écosystème, emploi et lequel apprendre

L'écosystème de Java est plus vaste dans le monde serveur open source : Spring, Kafka, Spark, Hadoop, Elasticsearch et la plupart des projets Apache sont en Java. Les applications Android s'écrivent en Kotlin ou en Java. C# a la pile la plus intégrée : un seul éditeur maintient le langage, le runtime, le framework web (ASP.NET Core), l'ORM (Entity Framework) et l'IDE principal (Visual Studio), et Unity le place au centre du développement de jeux.

Les deux langages ont de grands marchés de l'emploi, et l'équilibre entre eux dépend de la région et du secteur. C# est fort dans les entreprises bâties sur Microsoft et Azure, dans les logiciels de finance et de santé, et dans les studios de jeux vidéo.

Choisissez C# si vous voulez créer des jeux avec Unity, construire des applications de bureau Windows ou travailler dans une entreprise .NET. Choisissez Java si vous visez Android, le big data ou une entreprise dont le backend tourne sur la JVM. L'un comme l'autre enseigne les concepts dont vous aurez besoin pour le second : classes, interfaces, génériques, collections, exceptions et un runtime à ramasse-miettes.

Questions fréquentes

C# ressemble-t-il à Java ?

Oui, beaucoup. Tous deux sont des langages orientés objet, à typage statique et à ramasse-miettes, avec une syntaxe de style C, et compilés en bytecode pour une machine virtuelle. Un développeur Java peut lire du C# dès le premier jour. Les différences sont dans les détails : C# a les propriétés, les types valeur définis par l'utilisateur, les génériques réifiés, LINQ et async/await, tandis que Java a les exceptions vérifiées et un écosystème serveur open source plus vaste.

Faut-il apprendre C# ou Java en premier ?

Choisissez selon ce que vous voulez construire. C# pour les jeux Unity, les applications de bureau Windows et les entreprises bâties sur Microsoft et Azure. Java pour Android (avec Kotlin), les gros backends d'entreprise et les outils big data comme Kafka et Spark. Les langages sont assez proches pour que passer de l'un à l'autre plus tard prenne des semaines, pas des mois.

C# est-il plus rapide que Java ?

Ils sont dans la même catégorie de performances : les deux compilent en code natif via un JIT et utilisent des ramasse-miettes générationnels. C# offre plus de contrôle bas niveau grâce aux structs, à Span<T> et aux génériques sur des types valeur sans boxing, ce qui aide dans le code qui alloue beaucoup. Pour une application web typique, le framework et la base de données comptent bien plus que le langage.

C# a-t-il des exceptions vérifiées comme Java ?

Non. En C#, aucun type d'exception ne doit être déclaré ou intercepté ; la signature d'une méthode n'indique pas ce qu'elle lève. Les concepteurs ont estimé que les exceptions vérifiées menaient à des blocs catch vides et à des signatures fragiles. On documente les exceptions avec des commentaires XML /// <exception> à la place.

Qui offre le plus d'emplois, C# ou Java ?

Les deux ont de grands marchés de l'emploi, et celui qui compte le plus d'offres dépend du pays et du secteur ; regardez donc les annonces là où vous voulez travailler. C# est fort dans les entreprises Microsoft, la finance, la santé et les studios de jeux vidéo, Java dans les grandes banques, les télécoms, les backends e-commerce et Android.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER