Sviluppatori C # che imparano Java, quali sono le maggiori differenze che si possono trascurare? [chiuso]


87

Per gli sviluppatori c # che stanno iniziando a imparare Java, ci sono grandi differenze di fondo tra i due linguaggi che dovrebbero essere evidenziate?

Forse alcune persone potrebbero presumere che le cose siano le stesse, ma ci sono alcuni aspetti importanti che non dovrebbero essere trascurati? (o puoi davvero sbagliare!)

Forse in termini di costrutti OOP, il modo in cui funziona GC, riferimenti, distribuzione correlata, ecc.




È probabile che vengano trascurate anche le nostre "Funzionalità nascoste di C #" stackoverflow.com/questions/9033/hidden-features-of-c
John K

Risposte:


122

Alcuni trucchi dalla cima della mia testa:

  • Java non ha tipi di valore personalizzati (strutture), quindi non preoccuparti di cercarli
  • Le enumerazioni Java sono molto diverse dall'approccio "numeri con nome" di C #; sono più OO. Possono essere usati con grande effetto, se stai attento.
  • byte è firmato in Java (purtroppo)
  • In C #, gli inizializzatori di variabili di istanza vengono eseguiti prima del costruttore della classe di base; in Java vengono eseguiti dopo (cioè appena prima del corpo del costruttore in "questa" classe)
  • In C # i metodi sono sigillati per impostazione predefinita. In Java sono virtuali per impostazione predefinita.
  • Il modificatore di accesso predefinito in C # è sempre "l'accesso più restrittivo disponibile nel contesto corrente"; in Java è l'accesso "pacchetto". (Vale la pena leggere i particolari modificatori di accesso in Java.)
  • I tipi annidati in Java e C # funzionano in modo leggermente diverso; in particolare hanno restrizioni di accesso differenti e, a meno che non si dichiari il tipo annidato static, avrà un riferimento implicito a un'istanza della classe contenitore.

5
+1 Questa è un'ottima lista per i principianti.
Jim Schubert

3
@ Jon Skeet: +1, e probabilmente ti mancheranno Lambda e LINQ fino a Java 7?
Kb.

1
"In C #, gli inizializzatori di variabili di istanza vengono eseguiti prima del costruttore della classe base; in Java vengono eseguiti dopo di esso (cioè appena prima del corpo del costruttore in" questa "classe)" - Eeer, potresti elaborarlo? Non sono sicuro di aver capito bene cosa stai dicendo :)
cwap

7
@cwap: in C #, l'ordine di esecuzione è "inizializzatori di variabili di istanza, costruttore della classe base, corpo del costruttore". In Java è "costruttore di superclassi, inizializzatori di variabili di istanza, corpo del costruttore". (Gli inizializzatori di variabili di istanza sono ciò che ottieni quando assegni un valore a una variabile di istanza al momento della dichiarazione.)
Jon Skeet

1
@cwap: Sì, questo è ciò che intendo - quest'ultimo è un inizializzatore di oggetti .
Jon Skeet


17

Sono sorpreso che nessuno abbia menzionato le proprietà, qualcosa di abbastanza fondamentale in C # ma assente in Java. Anche C # 3 e versioni successive hanno implementato automaticamente le proprietà. In Java devi usare metodi di tipo GetX / SetX.

Un'altra evidente differenza è rappresentata da LINQ e dalle espressioni lambda in C # 3 assenti in Java.

Ci sono alcune altre cose semplici ma utili che mancano in Java come le stringhe verbatim (@ ""), il sovraccarico degli operatori, gli iteratori che utilizzano il rendimento e il pre processore mancano anche in Java.

Uno dei miei preferiti personali in C # è che i nomi degli spazi dei nomi non devono seguire la struttura della directory fisica. Mi piace molto questa flessibilità.


10

Ci sono molte differenze, ma queste mi vengono in mente:

  • Mancanza di sovraccarico dell'operatore in Java. Guarda il tuo instance.Equals (instance2) rispetto a instance == instance2 (specialmente con stringhe).
  • Abituati a interfacce che NON hanno il prefisso I. Spesso invece vedi spazi dei nomi o classi con suffisso Impl.
  • Il doppio blocco controllato non funziona a causa del modello di memoria Java.
  • È possibile importare metodi statici senza aggiungere il prefisso al nome della classe, il che è molto utile in alcuni casi (DSL).
  • Le istruzioni Switch in Java non richiedono un valore predefinito e non è possibile utilizzare stringhe come etichette maiuscole (IIRC).
  • I generici Java ti faranno arrabbiare. I generici Java non esistono in fase di runtime (almeno nella 1.5), sono un trucco del compilatore, che causa problemi se si desidera riflettere sui tipi generici.

4
L'ultima volta che ho controllato, le stringhe NON hanno sovraccaricato == e non ho sentito nemmeno che sia stato aggiunto per Java 7. Tuttavia, sovraccaricano + per la concatenazione di stringhe.
Michael Madsen

3
Sì, confrontare le stringhe con == è una trappola molto comune per i neofiti. .equalsè quello che devi usare.
Michael Myers

Inoltre, non capisco il commento sui metodi statici. Quasi tutti i linguaggi non consentono metodi statici o equivalenti?
Michael Myers

Ho quasi votato in alto, ma non sono d'accordo sui generici. Mi piace il tipo di cancellazione.
finnw

2
"Le istruzioni Switch in Java non richiedono un valore predefinito" - né C #.
RenniePet

8

.NET ha reificato i generici; Java ha cancellato i generici.

La differenza è questa: se hai un ArrayList<String>oggetto, in .NET, puoi dire (in runtime) che l'oggetto ha tipo ArrayList<String>, mentre in Java, in runtime, l'oggetto è di tipo ArrayList; la Stringparte è persa. Se inserisci non Stringoggetti in ArrayList, il sistema non può imporlo e lo saprai solo dopo aver provato a estrarre l'oggetto e il cast fallisce.


1
... anche se vale la pena aggiungere che non puoi mettere Stringoggetti non- oggetti in quella lista senza fare un cast non controllato, da qualche parte , e il compilatore ti avviserà correttamente a quel punto che il compilatore non può più controllare i limiti generici. Finché il tuo elenco è sempre memorizzato in una variabile di List<String>, i tentativi di inserire un oggetto non String in esso non verranno compilati.
Andrzej Doyle

"Oggetti non String in ArrayList, il sistema non può imporlo": Notare che il sistema lo impone in fase di compilazione. Puoi comunque aggirare questo problema con il casting (o non usando i generici); quindi il controllo di runtime lo rileverà, ma solo durante l'estrazione.
sleske

1
@Andrzej, @sleske: parlo solo di runtime. Supponiamo di ottenere l'oggetto tramite la riflessione e invocare il suo addmetodo (di nuovo, tramite la riflessione). Il sistema rifiuterà un non Stringoggetto immediatamente o solo quando proietterà il risultato di get?
Chris Jester-Young

@sleske: Ma IIRC ti serve solo un cast implicito per aggirare il controllo del tipo.
Niki

@Judah: ho annullato il tuo cambiamento (sì, un anno dopo il fatto), perché non puoi avere oggetti di tipo List. Puoi avere oggetti di tipi che discendono da List, come ArrayListe LinkedList. (È importante usarli al Listposto di ArrayListquando li si passa in giro, ma non cambia il fatto che non si possa dire new List().)
Chris Jester-Young,

6

Una cosa che mi manca in C # di Java è la gestione forzata delle eccezioni controllate. In C # è molto comune che non si sia a conoscenza delle eccezioni che un metodo può generare e che si sia in balia della documentazione o dei test per scoprirle. Non così in Java con eccezioni controllate.


1
FWIW, questo è stato considerato nel dev't di C # e la logica per lasciarli fuori è reale. Considera artima.com/intv/handcuffs.html . Non è che i designer siano filosoficamente contrari alle eccezioni controllate, piuttosto, stanno aspettando una tecnica migliore che offra vantaggi simili senza tutti gli inconvenienti pelosi.
Greg D

Sì, sì, un argomento molto controverso ...
sleske

2
Mi piace il fatto che C # non abbia verificato le eccezioni, ma questo è stato il primo post a sottolineare la differenza, quindi +1.
Nick

5

Java ha l'autoboxing per le primitive piuttosto che per i tipi di valore, quindi sebbene System.Int32[]sia un array di valori in C #, Integer[]è un array di riferimenti a Integeroggetti e come tale non è adatto per calcoli con prestazioni più elevate.


1
Pete: questo è un punto eccellente, che non ho mai conosciuto o almeno non ho mai considerato (essendo uno sviluppatore C # e nuovo di Java).
Jim Schubert

4

Nessun delegato o evento: devi usare le interfacce. Fortunatamente, puoi creare classi e implementazioni dell'interfaccia inline, quindi non è un grosso problema


3
"non è un grosso problema". Destra. Perché x => x.Foovs. new Bar() { public void M(SomeType x) { return x.Foo; } }- a chi importa che il codice sia 10 volte più breve?
Kirk Woll

2

La funzionalità data / calendario incorporata in Java è orribile rispetto a System.DateTime. Ci sono molte informazioni su questo qui: Cosa c'è di sbagliato con Java Date & Time API?

Alcuni di questi possono essere trucchi per uno sviluppatore C #:

  • La classe Java Date è modificabile, il che può rendere pericolose le date di ritorno e di passaggio.
  • La maggior parte dei costruttori java.util.Date sono deprecati. La semplice istanza di una data è piuttosto prolissa.
  • Non ho mai ottenuto la classe java.util.Date per interagire bene con i servizi web. Nella maggior parte dei casi le date su entrambi i lati sono state trasformate selvaggiamente in un'altra data e ora.

Inoltre, Java non ha tutte le stesse funzionalità offerte dalla GAC ​​e dagli assembly con nomi forti. Jar Hell è il termine per ciò che può andare storto quando si collega / si fa riferimento a librerie esterne.

Per quanto riguarda il packaging / la distribuzione:

  • può essere difficile creare un pacchetto di applicazioni web in un formato EAR / WAR che effettivamente si installano ed eseguono in diversi server di applicazioni (Glassfish, Websphere, ecc.).
  • La distribuzione della tua app Java come servizio Windows richiede molto più impegno rispetto a C #. La maggior parte dei consigli che ho ricevuto per questo riguardava una libreria di terze parti non libera
  • la configurazione dell'applicazione non è così semplice come includere un file app.config nel progetto. Esiste una classe java.util.Properties, ma non è così robusta e trovare il punto giusto in cui rilasciare il file .properties può creare confusione

1

Non ci sono delegati in Java. Pertanto, a parte tutti i vantaggi che i delegati portano in tavola, anche gli eventi funzionano in modo diverso. Invece di collegare semplicemente un metodo, è necessario implementare un'interfaccia e collegarla invece.


1

Una cosa che salta fuori b / c è nella mia lista di interviste è che non c'è una parola chiave analoga "nuova" in Java per nascondere il metodo e quindi nessun avvertimento del compilatore "dovresti mettere nuovo qui". Il metodo accidentale che si nasconde quando si intendeva sovrascrivere porta a bug.

(modifica ad esempio) Esempio, B deriva da A (usando la sintassi C #, Java si comporta allo stesso modo in cui ho controllato l'ultima volta ma non emette un avviso del compilatore). Viene chiamato foo di A o foo di B? (A viene chiamato, probabilmente sorprendendo lo sviluppatore che ha implementato B).

class A 
{
public void foo() {code}
}

class B:A
{
public void foo() {code}
}    

void SomeMethod()
{
A a = new B(); // variable's type is declared as A, but assigned to an object of B.
a.foo();
}

2
Come nascondi accidentalmente un metodo di istanza in Java? sono o finali, quindi nessuna sostituzione o newmetodo per nascondere intenzionalmente, o non finali, quindi sovrascritti piuttosto che nascosti.
Pete Kirkham

Aggiunto esempio. Non l'ho testato in Java da un po ', ma la domanda dell'intervista proveniva originariamente dal gruppo Java della mia precedente azienda. In C #, l'avviso del compilatore di solito indica che le persone cambiano il nome. Ammetto che sia un caso piuttosto strano, ma OP sembrava chiedere cose che sarebbero state potenzialmente difficili da trovare problemi quando si cambia lingua.
Jim L

1
La differenza qui è che in Java tutti i metodi sono virtuali (quindi in Java, sarà B.foo () a essere chiamato perché Java esegue sempre l'invio dinamico del metodo), mentre in C # i metodi non sono virtuali per impostazione predefinita (e A.foo () verrebbe chiamato). Molti controllori dello stile di codifica per Java ti diranno che B dovrebbe usare l'annotazione @Override.
William Billingsley

1

Java non ha LINQ e la documentazione è un inferno. Le interfacce utente in Java sono un problema da sviluppare, perdi tutte le cose buone che Microsoft ci ha dato (WPF, WCF, ecc ...) ma diventi "API" difficili da usare e poco documentate.


0

L'unico problema che ho riscontrato finora quando lavoro con Java proveniente da C # è che le eccezioni e gli errori sono diversi.

Ad esempio, non è possibile rilevare un errore di memoria insufficiente utilizzando catch (eccezione e).

Vedere quanto segue per maggiori dettagli:

perché-java-lang-outofmemoryerror-java-heap-space-not-catch


È intenzionalmente progettato in questo modo per scoraggiare il programmatore dell'applicazione dal prenderlo
finnw

Sì, sono sicuro che lo fosse, ma provenendo dal lato C #, dove tutto ciò di cui ti devi preoccupare è catturare le eccezioni, mi ha fatto fare un giro :)
Chris Persichetti

0

È passato così tanto tempo da quando sono stato in Java, ma le cose che ho notato subito nello sviluppo di applicazioni sono state il modello di eventi C #, il trascinamento della selezione C # rispetto all'utilizzo di Gestori layout in Swing (se stai facendo lo sviluppo di app) e la gestione delle eccezioni con Java assicurandosi di catturare un'eccezione e C # non richiesto.


0

In risposta alla tua domanda molto diretta nel titolo:

"Sviluppatori C # che imparano Java, quali sono le differenze maggiori che si possono trascurare?"

R: Il fatto che Java sia notevolmente più lento su Windows.


4
Eseguo OpenSuSE a 64 bit e Windows 7 a 64 bit, e Eclipse IDE è ("sembra") più veloce in Windows. La tua risposta è basata sull'osservazione personale o su benchmark reali?
Jim Schubert

0

La differenza più fastidiosa per me quando passo a java è la dichiarazione della stringa.

in C # string(la maggior parte delle volte) in JavaString

È abbastanza semplice, ma credimi, ti fa perdere così tanto tempo quando hai l'abitudine di snon farlo S!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.