Menu

C# vs Java: sintassi, runtime, generics, LINQ e quale imparare

C# e Java si assomigliano e risolvono problemi simili. Le differenze reali stanno in proprietà, tipi valore, generics, LINQ contro gli stream, async, eccezioni e negli ecosistemi che li circondano. Un confronto fianco a fianco con il codice.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

C# e Java sono parenti stretti. Entrambi sono linguaggi a tipizzazione statica, orientati agli oggetti, con garbage collector e sintassi in stile C, entrambi compilano in bytecode per una macchina virtuale ed entrambi si usano per grandi sistemi backend. C# è uscito nel 2002 in parte come risposta di Microsoft a Java, e in due decenni i due si sono presi a vicenda diverse funzionalità (lambda, generics, record, pattern matching). Chi conosce uno dei due riesce a leggere l'altro quasi subito.

Le differenze che contano nel lavoro di tutti i giorni sono più piccole e più specifiche. Questa pagina le passa in rassegna con il codice: snippet C# che puoi eseguire, e Java in blocchi statici per il confronto.

In sintesi

C#Java
Creato daMicrosoft (2002)Sun Microsystems (1995), ora Oracle
RuntimeCLR (.NET), compila IL in codice nativoJVM, compila bytecode in codice nativo
PiattaformeWindows, Linux, macOSWindows, Linux, macOS
ProprietàIntegrate: public int Age { get; set; }Metodi getter e setter
Tipi valore definiti dall'utentestructNon ancora (Project Valhalla)
GenericsReificati: i tipi esistono a runtimeCancellati: i tipi vengono rimossi dopo la compilazione
Interrogare collezioniLINQStreams API
Asyncasync / awaitVirtual thread (Java 21), CompletableFuture
Checked exceptionNoSì
Overload degli operatoriSìNo
Sicurezza rispetto a nullTipi riferimento nullable (C# 8)Optional<T>, annotazioni
Usi principaliGiochi con Unity, ASP.NET Core, desktop Windows, AzureBackend enterprise, Android, big data

Sintassi: quasi uguale

Classi, metodi, if, for, while, switch, try/catch si leggono in modo quasi identico. Le differenze visibili sono le convenzioni di denominazione e alcune parole chiave: i metodi C# sono in PascalCase (ToUpper, WriteLine), i metodi Java in camelCase (toUpperCase, println); C# scrive string e bool, Java String e boolean; l'ereditarietà è class Dog : Animal in C# e class Dog extends Animal in 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());
        }
    }
}

Output:

ANA
BEN

C# confronta inoltre le stringhe per valore con ==, il che elimina uno dei classici bug da principiante di Java: in Java, == tra due oggetti String confronta i riferimenti, quindi due stringhe uguali costruite a runtime (lette dall'input, concatenate) possono risultare diverse.

Proprietà invece di getter e setter

Le classi Java espongono lo stato tramite metodi getName() e setName(), di solito generati da un IDE o da Lombok. C# ha le proprietà: membri che si leggono come campi ma eseguono codice.

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

Output:

Mug: 9.50

L'inizializzatore di oggetto new Product { Name = ..., Price = ... } imposta le proprietà subito dopo la costruzione. I record di Java (Java 16) coprono il caso dei dati immutabili; anche C# ha i record (C# 9), più le proprietà per tutto il resto.

Tipi valore: le struct

In Java ogni tipo definito dall'utente è un tipo riferimento memorizzato nell'heap; solo gli otto tipi primitivi (int, double, ...) sono valori. C# ti permette di definire i tuoi tipi valore con struct. Una struct viene copiata nell'assegnazione e può vivere direttamente dentro array e altri oggetti, senza un'allocazione separata nell'heap.

Output:

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

Questo conta nei giochi e nel codice numerico, dove milioni di piccoli oggetti metterebbero sotto pressione il garbage collector. Vedi le struct.

Generics: reificati vs cancellati

Java cancella gli argomenti di tipo generici in fase di compilazione: a runtime una List<Integer> è solo una List, e List<int> non è ammessa (ottieni oggetti Integer con boxing). C# conserva gli argomenti di tipo a runtime, quindi List<int> memorizza int puri e il codice può chiedere cosa sia T.

Output:

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

typeof(T) e new T() funzionano perché il runtime conosce T. In Java sono entrambi errori di compilazione, e il workaround tipico è passare in giro un oggetto Class<T>.

LINQ vs stream

Entrambi i linguaggi hanno un'API fluente per filtrare e trasformare collezioni. Quella di Java è la Streams API (Java 8); quella di C# è LINQ (C# 3), che ha anche una sintassi di query e funziona sui database tramite Entity Framework.

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

Output:

Lamp, Chair
Total: 126

Le operazioni corrispondono una a una (filter è Where, map è Select, collect(toList()) è ToList()), e le versioni C# non hanno bisogno di stream() né di un collector. Gli oggetti new { Name = ..., Price = ... } sono tipi anonimi, per i quali Java non ha un equivalente diretto.

Async e concorrenza

C# ha introdotto async/await nel 2012: un metodo async restituisce un Task, e await lo sospende senza bloccare un thread. JavaScript, Python e Rust hanno poi adottato le stesse parole chiave. Java ha preso un'altra strada: catene di CompletableFuture e, da Java 21, i virtual thread che rendono economico il normale codice bloccante.

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

Entrambi gli approcci scalano su molte richieste concorrenti. C# rende visibile l'asincronia nelle firme dei metodi; Java la nasconde nel runtime.

Eccezioni, operatori e differenze minori

  • Checked exception. Java obbliga un metodo a dichiarare o catturare certe eccezioni (throws IOException). C# non ha alcuna checked exception.
  • Overload degli operatori. C# permette ai tipi di definire +, ==, < e simili, ed è per questo che l'aritmetica con decimal e DateTime si legge in modo naturale. Java no (BigDecimal.add).
  • Virtuale per impostazione predefinita. I metodi Java possono essere sovrascritti a meno che non siano marcati final; i metodi C# devono essere marcati virtual per poter essere sovrascritti, e l'override deve dire override.
  • Extension method. C# può aggiungere metodi a tipi esistenti ("text".IsPalindrome()); Java no.
  • Tipi valore nullable. int? in C# è un int che può essere null; Java usa l'Integer con boxing.
  • Tipi senza segno. C# ha uint, ulong, ushort e un byte senza segno; il byte di Java ha il segno e, a parte il char a 16 bit, Java non ha tipi interi senza segno.

Ecosistema, lavoro e quale imparare

L'ecosistema di Java è più ampio nel mondo open source lato server: Spring, Kafka, Spark, Hadoop, Elasticsearch e la maggior parte dei progetti Apache sono in Java. Le app Android si scrivono in Kotlin o Java. C# ha lo stack più integrato: un unico fornitore mantiene linguaggio, runtime, framework web (ASP.NET Core), ORM (Entity Framework) e l'IDE principale (Visual Studio), e Unity lo mette al centro dello sviluppo di videogiochi.

Entrambi i linguaggi hanno ampi mercati del lavoro, e l'equilibrio tra i due dipende dalla regione e dal settore. C# è forte nelle aziende basate su Microsoft e Azure, nel software per finanza e sanità e negli studi di videogiochi.

Scegli C# se vuoi creare giochi con Unity, sviluppare app desktop per Windows o lavorare in un'azienda .NET. Scegli Java se punti ad Android, ai big data o a un'azienda il cui backend gira sulla JVM. Entrambi ti insegnano i concetti che ti servono per l'altro: classi, interfacce, generics, collezioni, eccezioni e un runtime con garbage collector.

Domande frequenti

C# è simile a Java?

Sì, molto. Entrambi sono linguaggi a tipizzazione statica, orientati agli oggetti, con garbage collector e sintassi in stile C, che compilano in bytecode per una macchina virtuale. Uno sviluppatore Java riesce a leggere C# fin dal primo giorno. Le differenze stanno nei dettagli: C# ha proprietà, tipi valore definiti dall'utente, generics reificati, LINQ e async/await, mentre Java ha le checked exception e un ecosistema open source lato server più ampio.

Meglio imparare prima C# o Java?

Scegli in base a cosa vuoi costruire. C# per i giochi con Unity, le app desktop per Windows e le aziende basate su Microsoft e Azure. Java per Android (insieme a Kotlin), i grandi backend enterprise e gli strumenti per big data come Kafka e Spark. I linguaggi sono abbastanza vicini che passare dall'uno all'altro in seguito richiede settimane, non mesi.

C# è più veloce di Java?

Sono nella stessa fascia di prestazioni: entrambi compilano con il JIT in codice nativo e usano garbage collector generazionali. C# ti dà più controllo a basso livello tramite struct, Span<T> e generics sui tipi valore senza boxing, il che aiuta nel codice che alloca molto. Nei tipici carichi web il framework e il database contano molto più del linguaggio.

C# ha le checked exception come Java?

No. In C# nessun tipo di eccezione deve essere dichiarato o catturato; la firma di un metodo non elenca cosa lancia. I progettisti hanno giudicato che le checked exception portassero a blocchi catch vuoti e firme fragili. Le eccezioni si documentano invece con commenti XML /// <exception>.

C'è più lavoro per C# o per Java?

Entrambi hanno ampi mercati del lavoro, e quale abbia più annunci dipende dal paese e dal settore, quindi controlla le offerte dove vuoi lavorare. C# è forte nelle aziende enterprise basate su Microsoft, nella finanza, nella sanità e negli studi di videogiochi, Java nelle grandi banche, nelle telecomunicazioni, nei backend di e-commerce e su Android.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA