C # -Entwickler, die Java lernen, was sind die größten Unterschiede, die man übersehen kann? [geschlossen]

87

Gibt es für C # -Entwickler, die Java lernen möchten, große Unterschiede zwischen den beiden Sprachen, auf die hingewiesen werden sollte?

Vielleicht nehmen einige Leute an, dass die Dinge gleich sind, aber es gibt einige wichtige Aspekte, die nicht übersehen werden sollten? (oder du kannst es wirklich vermasseln!)

Möglicherweise in Bezug auf OOP-Konstrukte, die Funktionsweise von GC, Referenzen, Bereitstellungsinformationen usw.

mrblah
quelle

Antworten:

122

Ein paar Fallstricke von meinem Kopf:

  • Java hat keine benutzerdefinierten Werttypen (Strukturen), suchen Sie also nicht nach ihnen
  • Java-Enums unterscheiden sich stark vom Ansatz "Camed Numbers" von C #. Sie sind mehr OO. Sie können sehr effektiv eingesetzt werden, wenn Sie vorsichtig sind.
  • byte ist in Java signiert (leider)
  • In C # werden Instanzvariableninitialisierer ausgeführt, bevor der Basisklassenkonstruktor dies tut. in Java werden sie danach ausgeführt (dh kurz vor dem Konstruktorkörper in "dieser" Klasse)
  • In C # sind Methoden standardmäßig versiegelt. In Java sind sie standardmäßig virtuell.
  • Der Standardzugriffsmodifikator in C # ist immer "der restriktivste Zugriff, der im aktuellen Kontext verfügbar ist". In Java ist es "Paket" -Zugriff. (Es lohnt sich, sich über die jeweiligen Zugriffsmodifikatoren in Java zu informieren.)
  • Verschachtelte Typen in Java und C # funktionieren etwas anders. insbesondere haben sie unterschiedliche Zugangsbeschränkungen, und wenn Sie den verschachtelten Typen sein deklarieren staticwird es einen impliziten Verweis auf eine Instanz der Klasse enthalten hat.
Jon Skeet
quelle
5
+1 Dies ist eine großartige Liste für den Anfang.
Jim Schubert
3
@ Jon Skeet: +1, und Sie würden wahrscheinlich Lambda und LINQ bis Java 7 vermissen?
Kb.
1
"In C # werden Instanzvariableninitialisierer ausgeführt, bevor der Basisklassenkonstruktor dies tut. In Java werden sie danach ausgeführt (dh kurz vor dem Konstruktorkörper in" dieser "Klasse)." - Könnten Sie dies näher erläutern? Ich bin mir nicht sicher, ob ich wirklich verstehe, was du sagst :)
cwap
7
@cwap: In C # lautet die Ausführungsreihenfolge "Instanzvariableninitialisierer, Basisklassenkonstruktor, Konstruktorkörper". In Java ist es "Superklassenkonstruktor, Instanzvariableninitialisierer, Konstruktorkörper". (Instanzvariablen-Initialisierer erhalten Sie, wenn Sie einer Instanzvariablen zum Zeitpunkt der Deklaration einen Wert zuweisen.)
Jon Skeet
1
@cwap: Ja, das meine ich - letzteres ist ein Objektinitialisierer .
Jon Skeet
17

Ich bin überrascht, dass niemand Eigenschaften erwähnt hat, was in C # ziemlich grundlegend ist, in Java jedoch fehlt. C # 3 und höher hat ebenfalls automatisch Eigenschaften implementiert. In Java müssen Sie GetX / SetX-Typmethoden verwenden.

Ein weiterer offensichtlicher Unterschied sind LINQ- und Lambda-Ausdrücke in C # 3, die in Java fehlen.

Es gibt ein paar andere einfache, aber nützliche Dinge, die in Java fehlen, wie wörtliche Zeichenfolgen (@ ""), Überladen von Operatoren, Iteratoren, die Yield verwenden, und Pre-Prozessor, die auch in Java fehlen.

Einer meiner persönlichen Favoriten in C # ist, dass Namespace-Namen nicht der physischen Verzeichnisstruktur folgen müssen. Diese Flexibilität gefällt mir sehr gut.

Softveda
quelle
10

Es gibt viele Unterschiede, aber diese fallen mir ein:

  • Fehlende Operatorüberladung in Java. Beobachten Sie Ihre Instanz. Gleichungen (Instanz2) versus Instanz == Instanz2 (insbesondere mit Zeichenfolgen).
  • Gewöhnen Sie sich an Schnittstellen, denen KEIN I vorangestellt ist. Oft werden stattdessen Namespaces oder Klassen mit dem Suffix Impl angezeigt.
  • Das doppelt überprüfte Sperren funktioniert aufgrund des Java-Speichermodells nicht.
  • Sie können statische Methoden importieren, ohne ihnen den Klassennamen voranzustellen, was in bestimmten Fällen (DSLs) sehr nützlich ist.
  • Für Switch-Anweisungen in Java ist keine Standardeinstellung erforderlich, und Sie können keine Zeichenfolgen als Fallbezeichnungen (IIRC) verwenden.
  • Java-Generika werden Sie verärgern. Java-Generika existieren zur Laufzeit nicht (zumindest in Version 1.5), sondern sind ein Compiler-Trick, der Probleme verursacht, wenn Sie über die generischen Typen nachdenken möchten.
Sneal
quelle
4
Zuletzt habe ich überprüft, dass Zeichenfolgen NICHT überladen wurden ==, und ich habe auch nicht gehört, dass sie für Java 7 hinzugefügt wurden. Sie überladen jedoch + für die Verkettung von Zeichenfolgen.
Michael Madsen
3
Ja, der Vergleich von Zeichenfolgen mit == ist eine sehr häufige Gefahr für Neulinge. .equalsist das, was Sie verwenden müssen.
Michael Myers
Außerdem verstehe ich den Kommentar zu statischen Methoden nicht. Erlauben nicht so ziemlich alle Sprachen statische Methoden oder ähnliches?
Michael Myers
Ich habe das fast positiv bewertet, aber ich bin nicht einverstanden mit Generika. Ich mag die Art Löschung.
Finnw
2
"Switch-Anweisungen in Java erfordern keine Standardeinstellung" - und C # auch nicht.
RenniePet
8

.NET hat Generika reifiziert. Java hat Generika gelöscht.

Der Unterschied besteht darin, dass Sie ArrayList<String>in .NET (zur Laufzeit) feststellen können, dass das Objekt vom Typ ist ArrayList<String>, während in Java zur Laufzeit das Objekt vom Typ ist ArrayList. Das StringTeil ist verloren. Wenn Sie Nicht- StringObjekte in das Objekt einfügen ArrayList, kann das System dies nicht erzwingen, und Sie werden es erst erfahren, nachdem Sie versucht haben, das Objekt herauszuziehen, und die Besetzung schlägt fehl.

Chris Jester-Young
quelle
1
... obwohl es erwähnenswert ist, dass Sie keine Nicht- StringObjekte in diese Liste aufnehmen können, ohne irgendwo eine ungeprüfte Umwandlung vorzunehmen , und der Compiler Sie an dieser Stelle korrekt warnt, dass der Compiler die generischen Grenzen nicht mehr überprüfen kann. Solange Ihre Liste immer in einer Variablen von gespeichert ist List<String>, werden Versuche, ein Nicht-String-Objekt einzufügen, nicht kompiliert.
Andrzej Doyle
"Nicht-String-Objekte in der ArrayList, das System kann dies nicht erzwingen": Beachten Sie, dass das System dies zur Kompilierungszeit erzwingt. Sie können dies jedoch umgehen, indem Sie Casting verwenden (oder keine Generika verwenden). dann fängt die Laufzeitprüfung es ab, aber nur beim Extrahieren.
Sleske
1
@Andrzej, @sleske: Ich spreche nur von Laufzeit. Angenommen, Sie erhalten das Objekt über Reflexion und rufen seine addMethode auf (erneut über Reflexion). Wird das System ein Nicht- StringObjekt sofort ablehnen oder nur, wenn das Ergebnis von getgewirkt wird?
Chris Jester-Young
@sleske: Aber IIRC benötigen Sie nur eine implizite Besetzung, um die Typprüfung zu umgehen.
Niki
@Judah: Ich habe Ihr Wechselgeld zurückgesetzt (ja, ein Jahr später), weil Sie keine Objekte vom Typ haben können List. Sie können Objekte von Typen haben, die von List, wie ArrayListund absteigen LinkedList. (Es ist wichtig zu verwenden, Listanstatt ArrayListsie new List()
Chris Jester-Young
6

Eine Sache, die ich in C # von Java vermisse, ist die erzwungene Behandlung geprüfter Ausnahmen. In C # ist es weit verbreitet, dass man sich der Ausnahmen, die eine Methode auslösen kann, nicht bewusst ist und Sie der Dokumentation oder den Tests ausgeliefert sind, um sie zu entdecken. Nicht so in Java mit aktivierten Ausnahmen.

Sean
quelle
1
FWIW, dies wurde in der Entwicklung von C # berücksichtigt und die Gründe für das Auslassen sind real. Betrachten Sie artima.com/intv/handcuffs.html . Es ist nicht so, dass die Designer philosophisch gegen geprüfte Ausnahmen sind - vielmehr warten sie auf eine bessere Technik, die ähnliche Vorteile ohne all die haarigen Nachteile bietet.
Greg D
Ja, ja, ein sehr umstrittenes Thema ...
Sleske
2
Ich mag die Tatsache, dass C # keine Ausnahmen überprüft hat, aber dies war der erste Beitrag, der sogar auf den Unterschied hinwies, also +1.
Nick
5

Java verfügt über Autoboxing für Grundelemente und nicht für Werttypen. Obwohl System.Int32[]es sich um ein Array von Werten in C # handelt, Integer[]handelt es sich um ein Array von Verweisen auf IntegerObjekte und ist daher nicht für Berechnungen mit höherer Leistung geeignet.

Pete Kirkham
quelle
1
Pete: Das ist ein ausgezeichneter Punkt, den ich nie gekannt oder zumindest nie in Betracht gezogen habe (ein C # -Entwickler und neu in Java).
Jim Schubert
4

Keine Delegierten oder Ereignisse - Sie müssen Schnittstellen verwenden. Glücklicherweise können Sie Klassen und Schnittstellenimplementierungen inline erstellen, sodass dies keine große Sache ist

thecoop
quelle
3
"ist nicht so eine große Sache". Richtig. Weil x => x.Foovs. new Bar() { public void M(SomeType x) { return x.Foo; } }- wen interessiert es, dass der Code zehnmal kürzer ist?
Kirk Woll
2

Die in Java integrierte Datums- / Kalenderfunktion ist im Vergleich zu System.DateTime schrecklich. Hier gibt es viele Informationen dazu: Was stimmt nicht mit der Java Date & Time API?

Einige davon können Fallstricke für einen C # -Entwickler sein:

  • Die Java Date-Klasse ist veränderbar, wodurch das Zurückgeben und Weitergeben von Daten gefährlich werden kann.
  • Die meisten Konstruktoren von java.util.Date sind veraltet. Ein Datum einfach zu instanziieren ist ziemlich ausführlich.
  • Ich habe die Klasse java.util.Date noch nie für eine gute Zusammenarbeit mit Webdiensten erhalten. In den meisten Fällen wurden die Daten auf beiden Seiten wild in ein anderes Datum und eine andere Uhrzeit umgewandelt.

Darüber hinaus verfügt Java nicht über dieselben Funktionen wie das GAC und stark benannte Assemblys. Jar Hell ist der Begriff für das, was beim Verknüpfen / Referenzieren externer Bibliotheken schief gehen kann.

In Bezug auf Verpackung / Bereitstellung:

  • Es kann schwierig sein, Webanwendungen in einem EAR / WAR-Format zu verpacken, die tatsächlich auf mehreren verschiedenen Anwendungsservern (Glassfish, Websphere usw.) installiert und ausgeführt werden.
  • Das Bereitstellen Ihrer Java-App als Windows-Dienst erfordert viel mehr Aufwand als in C #. Die meisten Empfehlungen, die ich dafür erhielt, betrafen eine nicht kostenlose Bibliothek von Drittanbietern
  • Die Anwendungskonfiguration ist bei weitem nicht so einfach wie das Einfügen einer app.config-Datei in Ihr Projekt. Es gibt eine java.util.Properties-Klasse, die jedoch nicht so robust ist. Es kann verwirrend sein, den richtigen Ort zum Löschen Ihrer .properties-Datei zu finden
inOrbit
quelle
1

In Java gibt es keine Delegierten. Abgesehen von all den Vorteilen, die Delegierte mitbringen, funktionieren Veranstaltungen daher auch anders. Anstatt nur eine Methode anzuschließen, müssen Sie eine Schnittstelle implementieren und diese stattdessen anhängen.

BKostenlos
quelle
1

Eine Sache, die b / c auf meiner Interviewliste herausspringt, ist, dass es in Java kein "neues" Schlüsselwortanalogon zum Ausblenden von Methoden gibt und daher keine Compiler-Warnung "Sie sollten hier etwas Neues einfügen". Das versehentliche Ausblenden einer Methode, die Sie überschreiben wollten, führt zu Fehlern.

(zum Beispiel bearbeiten) Beispiel: B leitet sich von A ab (unter Verwendung der C # -Syntax verhält sich Java genauso, wie ich es zuletzt überprüft habe, gibt jedoch keine Compiler-Warnung aus). Wird A's Foo genannt oder B's Foo? (A wird aufgerufen, was wahrscheinlich den Entwickler überrascht, der B implementiert hat).

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();
}
Jim L.
quelle
2
Wie können Sie versehentlich eine Instanzmethode in Java ausblenden? Sie sind entweder endgültig - also keine Überschreibung oder newMethode zum absichtlichen Ausblenden - oder nicht endgültig, also überschrieben und nicht verborgen.
Pete Kirkham
Beispiel hinzugefügt. Ich habe es eine Weile nicht mehr in Java getestet, aber die Interviewfrage stammte ursprünglich von der Java-Gruppe meiner vorherigen Firma. In C # bedeutet die Compiler-Warnung normalerweise, dass Benutzer den Namen ändern. Ich gebe zu, dass es ein ziemlich seltsamer Fall ist, aber OP schien nach Dingen zu fragen, die beim Wechsel von langs möglicherweise schwer zu finden sind.
Jim L
1
Der Unterschied besteht darin, dass in Java alle Methoden virtuell sind (in Java wird also B.foo () aufgerufen, da Java immer den dynamischen Methodenversand ausführt), während in C # -Methoden standardmäßig nicht virtuell sind (und A.foo () würde aufgerufen werden). Viele Codierungsstilprüfer für Java sagen Ihnen, dass B die Annotation @Override verwenden sollte.
William Billingsley
1

Java hat kein LINQ und die Dokumentation ist die Hölle. Die Entwicklung von Benutzeroberflächen in Java ist schwierig. Sie verlieren alle guten Dinge, die Microsoft uns gegeben hat (WPF, WCF usw.), erhalten jedoch schwer zu verwendende, kaum dokumentierte "APIs".

Turing abgeschlossen
quelle
0

Das einzige Problem, auf das ich bisher gestoßen bin, wenn ich mit Java aus C # arbeite, sind Ausnahmen und Fehler, die unterschiedlich sind.

Beispielsweise können Sie mit catch (Ausnahme e) keinen Speicherfehler abfangen.

Weitere Informationen finden Sie im Folgenden:

Warum-ist-Java-lang-outofmemoryerror-Java-Heap-Space-nicht-gefangen

Chris Persichetti
quelle
Es wurde absichtlich so entworfen, um den Anwendungsprogrammierer davon
abzuhalten
Ja, ich bin mir sicher, dass es so war, aber von der C # -Seite zu kommen, wo alles, worüber Sie sich Sorgen machen müssen, Ausnahmen zu fangen, warf mich für eine Schleife :)
Chris Persichetti
0

Es ist so lange her, dass ich in Java war, aber die Dinge, die mir auf Anhieb bei der Anwendungsentwicklung aufgefallen sind, waren C # -Ereignismodell, C # Drag & Drop im Vergleich zur Verwendung von Layout-Managern in Swing (wenn Sie App-Entwickler sind) und Ausnahmebehandlung mit Java stellt sicher, dass Sie eine Ausnahme abfangen und C # nicht erforderlich ist.

Jason Too Cool Webs
quelle
0

Als Antwort auf Ihre sehr direkte Frage in Ihrem Titel:

"C # -Entwickler, die Java lernen, was sind die größten Unterschiede, die man übersehen kann?"

A: Die Tatsache, dass Java unter Windows erheblich langsamer ist.


quelle
4
Ich verwende OpenSuSE 64bit und Windows 7 64bit und Eclipse IDE ist ("scheint") in Windows schneller. Beruht Ihre Antwort auf persönlicher Beobachtung oder auf tatsächlichen Benchmarks?
Jim Schubert
0

Der größte Unterschied für mich, wenn ich zu Java wechsle, ist die String-Deklaration.

in C # string(meistens) in JavaString

Es ist ziemlich einfach, aber glauben Sie mir, es macht Sie so viel Zeit verlieren , wenn Sie die Gewohnheit haben , snicht S!

iChaib
quelle