Programiści C # uczący się języka Java, jakie są największe różnice, które można przeoczyć? [Zamknięte]

87

W przypadku programistów C #, którzy chcą nauczyć się języka Java, czy są jakieś duże różnice między tymi dwoma językami, na które należy zwrócić uwagę?

Może niektórzy ludzie zakładają, że jest tak samo, ale są pewne ważne aspekty, których nie należy przeoczyć? (albo możesz naprawdę schrzanić!)

Może pod względem konstrukcji OOP, sposobu działania GC, referencji, związanych z wdrażaniem itp.

mrblah
źródło

Odpowiedzi:

122

Kilka kłopotów z mojej głowy:

  • Java nie ma niestandardowych typów wartości (struktur), więc nie przejmuj się ich wyszukiwaniem
  • Wyliczenia Java bardzo różnią się od podejścia „nazwanych liczb” języka C #; są bardziej OO. Jeśli będziesz ostrożny, można je wykorzystać z doskonałym efektem.
  • byte jest podpisany w Javie (niestety)
  • W języku C # inicjatory zmiennych instancji są uruchamiane przed wykonaniem tego konstruktora klasy bazowej; w Javie są uruchamiane po tym (tj. tuż przed treścią konstruktora w „tej” klasie)
  • W C # metody są domyślnie zapieczętowane. W Javie są one domyślnie wirtualne.
  • Domyślny modyfikator dostępu w języku C # to zawsze „najbardziej restrykcyjny dostęp dostępny w bieżącym kontekście”; w Javie jest to dostęp do pakietu. (Warto poczytać o poszczególnych modyfikatorach dostępu w Javie).
  • Zagnieżdżone typy w Javie i C # działają nieco inaczej; w szczególności mają różne ograniczenia dostępu i jeśli nie zadeklarujesz zagnieżdżonego typu, będzie staticon miał niejawne odwołanie do wystąpienia klasy zawierającej.
Jon Skeet
źródło
5
+1 To świetna lista na początek.
Jim Schubert,
3
@Jon Skeet: +1, I prawdopodobnie tęskniłbyś za Lambdą i LINQ do Java 7?
Kb.
1
„W C # inicjatory zmiennych instancji są uruchamiane przed wykonaniem konstruktora klasy bazowej; w Javie działają one po tym (tj. Tuż przed treścią konstruktora w„ tej ”klasie)” - Eeer, czy mógłbyś to rozwinąć? Nie jestem pewien, czy naprawdę rozumiem, co mówisz :)
cwap
7
@cwap: W języku C # kolejność wykonywania to „inicjatory zmiennych wystąpienia, konstruktor klasy bazowej, treść konstruktora”. W Javie jest to „konstruktor nadklasy, inicjatory zmiennych instancji, treść konstruktora”. (Instancja inicjalizatory zmienne są tym, co można dostać po przypisaniu wartości do zmiennej instancji w punkcie deklaracji.)
Jon Skeet
1
@cwap: Tak, to właśnie mam na myśli - ten ostatni jest inicjatorem obiektu .
Jon Skeet,
17

Dziwię się, że nikt nie wspomniał o właściwościach, czymś dość podstawowym w C #, ale nieobecnym w Javie. C # 3 i nowsze wersje mają również automatycznie implementowane właściwości. W Javie musisz używać metod typu GetX / SetX.

Inną oczywistą różnicą są wyrażenia LINQ i lambda w C # 3, których nie ma w Javie.

W Javie brakuje kilku innych prostych, ale użytecznych rzeczy, takich jak ciągi dosłowne (@ ""), przeciążanie operatorów, iteratory używające wydajności i preprocesora, których również brakuje w Javie.

Jednym z moich ulubionych w C # jest to, że nazwy przestrzeni nazw nie muszą być zgodne z fizyczną strukturą katalogów. Bardzo podoba mi się ta elastyczność.

softveda
źródło
10

Jest wiele różnic, ale przychodzą mi na myśl:

  • Brak przeciążenia operatorów w Javie. Obserwuj swoją instancję. Równania (instancja2) kontra instancja == instancja2 (szczególnie w / strings).
  • Przyzwyczaj się do interfejsów, które NIE są poprzedzone literą I. Często zamiast tego widzisz przestrzenie nazw lub klasy z sufiksem Impl.
  • Podwójnie zaznaczone blokowanie nie działa z powodu modelu pamięci Java.
  • Możesz importować metody statyczne bez poprzedzania ich nazwą klasy, co jest bardzo przydatne w niektórych przypadkach (DSL).
  • Instrukcje Switch w Javie nie wymagają wartości domyślnych i nie można używać łańcuchów jako etykiet wielkości liter (IIRC).
  • Generyczne programy Java będą cię zdenerwować. Typy generyczne Java nie istnieją w czasie wykonywania (przynajmniej w 1.5), są sztuczką kompilatora, która powoduje problemy, jeśli chcesz zastanowić się nad typami rodzajowymi.
Sneal
źródło
4
Kiedy ostatnio sprawdzałem, ciągi znaków NIE przeładowały się == i nie słyszałem o dodaniu ich do Java 7. Jednak powodują przeciążenie + konkatenacji ciągów.
Michael Madsen,
3
Tak, porównywanie łańcuchów z == jest bardzo częstą pułapką dla początkujących. .equalsjest tym, czego musisz użyć.
Michael Myers
Nie rozumiem też komentarza na temat metod statycznych. Czy prawie wszystkie języki nie pozwalają na metody statyczne lub ich odpowiedniki?
Michael Myers
Prawie to zagłosowałem, ale nie zgadzam się co do leków generycznych. Podoba mi się wymazywanie typu.
finnw
2
„Instrukcje przełączania w Javie nie wymagają wartości domyślnych” - podobnie jak C #.
RenniePet
8

.NET zreifikował typy generyczne; Java usunęła typy generyczne.

Różnica jest następująca: jeśli masz ArrayList<String>obiekt, w .NET możesz powiedzieć (w czasie wykonywania), że obiekt ma typ ArrayList<String>, podczas gdy w Javie, w czasie wykonywania, obiekt jest typu ArrayList; Stringczęść jest tracona. Jeśli umieścisz Stringobiekty niebędące obiektami w ArrayList, system nie może tego wymusić, a dowiesz się o tym dopiero po próbie wyodrębnienia przedmiotu, a rzucanie się nie powiedzie.

Chris Jester-Young
źródło
1
... chociaż Warto dodać, że nie można umieścić innych niż Stringobiekty w tym wykazie, bez dokonywania niezaznaczone obsady, gdzieś , a kompilator będzie prawidłowo ostrzec cię w tym momencie, że kompilator nie może sprawdzić ogólnych granic. Dopóki lista jest zawsze przechowywana w zmiennej typu List<String>, próby wstawienia do niej obiektu innego niż łańcuch nie będą się kompilować.
Andrzej Doyle
„non-String obiektów w ArrayList, system nie może wymusić, że”: Uwaga, że system nie egzekwować je w czasie kompilacji. Możesz jednak to obejść, przesyłając (lub nie używając typów generycznych); wtedy sprawdzanie środowiska wykonawczego złapie go, ale tylko podczas wypakowywania.
sleske
1
@Andrzej, @sleske: Mówię tylko o runtime. Powiedzmy, że otrzymujesz obiekt przez odbicie i wywołaj jego addmetodę (ponownie, przez odbicie). Czy system odrzuci Stringobiekt niebędący przedmiotem od razu, czy tylko podczas rzucania wyniku get?
Chris Jester-Young
@sleske: Ale IIRC potrzebujesz tylko niejawnego rzutowania, aby ominąć sprawdzanie typu.
Niki,
@Judah: Cofnąłem twoją zmianę (tak, rok po fakcie), ponieważ nie możesz mieć obiektów typu List. Możesz mieć obiekty o typach od List, takich jak ArrayListi LinkedList. (Ważne jest, aby używać Listzamiast ArrayListpodczas przekazywania ich, ale nie zmienia to faktu, że nie można powiedzieć new List().)
Chris Jester-Young
6

Jedną rzeczą, której brakuje mi w C # w Javie, jest wymuszona obsługa sprawdzonych wyjątków. W języku C # często zdarza się, że ktoś nie jest świadomy wyjątków, które metoda może rzucać, i jest zdany na łaskę dokumentacji lub testów, aby je odkryć. Inaczej jest w Javie z zaznaczonymi wyjątkami.

Sean
źródło
1
FWIW, zostało to rozważone w opracowaniu C # i uzasadnienie dla ich pominięcia jest prawdziwe. Rozważ artykuł artima.com/intv/handcuffs.html . Nie chodzi o to, że projektanci filozoficznie sprzeciwiają się sprawdzonym wyjątkom - raczej czekają na lepszą technikę, która oferuje podobne korzyści bez wszystkich włochatych wad.
Greg D,
Tak, tak, bardzo kontrowersyjny temat ...
sleske
2
Podoba mi się fakt, że C # nie ma sprawdzonych wyjątków, ale to był pierwszy post, który nawet wskazał różnicę, więc +1.
Nick,
5

Java ma autoboxing dla prymitywów, a nie typów wartości, więc chociaż System.Int32[]jest tablicą wartości w C #, Integer[]jest tablicą odwołań do Integerobiektów i jako taka nie nadaje się do obliczeń o wyższej wydajności.

Pete Kirkham
źródło
1
Pete: to doskonała uwaga, której nigdy nie znałem lub przynajmniej nigdy nie brałem pod uwagę (będąc programistą C # i nowicjuszem w Javie).
Jim Schubert
4

Żadnych delegatów ani wydarzeń - musisz używać interfejsów. Na szczęście możesz tworzyć klasy i implementacje interfejsów w tekście, więc nie jest to taka wielka sprawa

thecoop
źródło
3
„nie jest taka wielka sprawa”. Dobrze. Bo x => x.Fooczy new Bar() { public void M(SomeType x) { return x.Foo; } }- kogo obchodzi, żeby kod był 10 razy krótszy?
Kirk Woll,
2

Wbudowana funkcja daty / kalendarza w Javie jest okropna w porównaniu z System.DateTime. Jest tutaj wiele informacji na ten temat: Co jest nie tak z Java Date & Time API?

Niektóre z nich mogą być pułapkami dla programisty C #:

  • Klasa Java Date jest zmienna, co może powodować, że zwracanie i przekazywanie dat jest niebezpieczne.
  • Większość konstruktorów java.util.Date jest przestarzała. Samo utworzenie wystąpienia daty jest dość rozwlekłe.
  • Nigdy nie otrzymałem klasy java.util.Date do dobrej współpracy z usługami sieciowymi. W większości przypadków daty po obu stronach zostały dziko przekształcone w inną datę i godzinę.

Ponadto Java nie ma wszystkich tych samych funkcji, które zapewniają GAC i zestawy o silnych nazwach. Jar Hell to termin określający, co może pójść nie tak podczas łączenia / odwoływania się do zewnętrznych bibliotek.

Jeśli chodzi o pakowanie / wdrażanie:

  • może być trudne spakowanie aplikacji internetowych w formacie EAR / WAR, które faktycznie instalują się i działają na kilku różnych serwerach aplikacji (Glassfish, Websphere itp.).
  • wdrażanie aplikacji Java jako usługi systemu Windows wymaga znacznie więcej wysiłku niż w języku C #. Większość zaleceń, które otrzymałem, dotyczyła niewolnej biblioteki innej firmy
  • konfiguracja aplikacji nie jest tak łatwa, jak włączenie pliku app.config do projektu. Istnieje klasa java.util.Properties, ale nie jest ona tak solidna, a znalezienie odpowiedniego miejsca do usunięcia pliku .properties może być mylące
intoOrbit
źródło
1

W Javie nie ma delegatów. Dlatego oprócz wszystkich korzyści, jakie delegaci wnoszą do stołu, zdarzenia działają również inaczej. Zamiast po prostu podłączać metodę, musisz zaimplementować interfejs i dołączyć go.

BFree
źródło
1

Jedyną rzeczą, która wyskakuje b / c, jest na mojej liście wywiadów, jest to, że w Javie nie ma "nowego" odpowiednika słowa kluczowego do ukrywania metod i dlatego nie ma ostrzeżenia kompilatora "powinieneś umieścić tutaj nowe". Przypadkowe ukrycie metody, gdy chcesz zastąpić, prowadzi do błędów.

(na przykład edytuj) Przykład, B pochodzi od A (używając składni C #, Java zachowuje się tak samo, jak ostatnio sprawdzałem, ale nie emituje ostrzeżenia kompilatora). Czy dzwoni foo A, czy foo B? (Wzywa się A, prawdopodobnie zaskakując programistę, który zaimplementował 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();
}
Jim L.
źródło
2
Jak przypadkowo ukryć metodę instancji w Javie? są albo ostateczne - więc nie ma nadpisania ani newmetody celowego ukrycia - albo nie ostateczne, więc są zastępowane, a nie ukrywane.
Pete Kirkham
Dodano przykład. Od jakiegoś czasu nie testowałem tego w Javie, ale pytanie do wywiadu pochodziło pierwotnie od grupy Java z mojej poprzedniej firmy. W C # ostrzeżenie kompilatora zwykle oznacza, że ​​ludzie zmieniają nazwę. Przyznaję, że to dość dziwny przypadek, ale OP wydawał się prosić o rzeczy, które potencjalnie byłyby trudne do znalezienia podczas zmiany języków.
Jim L
1
Różnica polega na tym, że w Javie wszystkie metody są wirtualne (więc w Javie zostanie wywołana B.foo (), ponieważ Java zawsze wykonuje dynamiczne wysyłanie metod), podczas gdy w C # metody nie są domyślnie wirtualne (i A.foo () zostanie wywołana). Wiele narzędzi sprawdzających styl kodowania dla Javy powie, że B powinien używać adnotacji @Override.
William Billingsley,
1

Java nie ma LINQ, a dokumentacja to piekło. Tworzenie interfejsów użytkownika w Javie jest trudne, tracisz wszystkie dobre rzeczy, które dał nam Microsoft (WPF, WCF itp.), Ale otrzymujesz trudne w użyciu, mało udokumentowane „interfejsy API”.

Turing Complete
źródło
0

Jedynym problemem, na który natknąłem się do tej pory podczas pracy z Javą pochodzącą z C #, są wyjątki i błędy.

Na przykład nie można złapać błędu braku pamięci za pomocą catch (wyjątek e).

Więcej informacji znajdziesz poniżej:

dlaczego jest-java-lang-outofmemoryerror-java-heap-space-not-catch

Chris Persichetti
źródło
Jest celowo zaprojektowany w ten sposób, aby zniechęcić programistę aplikacji do złapania go
finnw
Tak, jestem pewien, że tak, ale jadąc od strony C #, gdzie
jedyne
0

Minęło tak dużo czasu, odkąd pracowałem w Javie, ale podczas tworzenia aplikacji zauważyłem od razu model zdarzeń w języku C #, przeciąganie i upuszczanie w języku C # w porównaniu z Menedżerami układów w Swing (jeśli robisz programowanie aplikacji) oraz obsługę wyjątków w Java upewniająca się, że wychwycisz wyjątek i C # nie jest wymagane.

Jason Too Cool Webs
źródło
0

W odpowiedzi na bardzo bezpośrednie pytanie w tytule:

„Programiści C # uczący się języka Java, jakie są największe różnice, które można przeoczyć?”

Odp .: Fakt, że Java jest znacznie wolniejsza w systemie Windows.


źródło
4
Używam OpenSuSE 64bit i Windows 7 64bit, a Eclipse IDE jest ("wydaje się") szybsze w Windows. Czy Twoja odpowiedź opiera się na osobistych obserwacjach czy na rzeczywistych punktach odniesienia?
Jim Schubert
0

Najbardziej wstrząsającą różnicą dla mnie, kiedy przełączam się na java, jest deklaracja ciągu.

w C # string(przez większość czasu) w JavieString

Jest to dość proste, ale uwierzcie mi, to sprawia, że można stracić tyle czasu, gdy masz zwyczaj snie S!

iChaib
źródło