Java'yı öğrenen C # geliştiricileri, gözden kaçabilecek en büyük farklar nelerdir? [kapalı]


87

Java öğrenmek isteyen c # geliştiricileri için, iki dil arasında dikkat edilmesi gereken büyük farklılıklar var mı?

Belki bazı insanlar şeylerin aynı olduğunu varsayabilir, ancak gözden kaçırılmaması gereken bazı önemli yönler var mı? (ya da gerçekten berbat edebilirsiniz!)

Belki OOP yapıları, GC'nin çalışma şekli, referanslar, dağıtımla ilgili vb.




Ayrıca muhtemelen kendi "C # Gizli Özellikleri" dir ardı edilecek stackoverflow.com/questions/9033/hidden-features-of-c
John K

Yanıtlar:


122

Kafamın üstünden birkaç serseri:

  • Java'nın özel değer türleri (yapıları) yoktur, bu yüzden onları aramakla uğraşmayın
  • Java numaralandırmaları, C # 'ın "adlandırılmış sayılar" yaklaşımından çok farklıdır; onlar daha çok OO. Dikkatli olursanız, büyük etki için kullanılabilirler.
  • byte Java'da imzalandı (maalesef)
  • C # 'da, örnek değişkeni başlatıcıları , temel sınıf yapıcısından önce çalışır ; Java'da ondan sonra çalışırlar (yani, "bu" sınıftaki yapıcı gövdesinden hemen önce)
  • C # yöntemlerinde varsayılan olarak mühürlenir. Java'da varsayılan olarak sanaldırlar.
  • C #'daki varsayılan erişim değiştiricisi her zaman "geçerli bağlamda bulunan en kısıtlayıcı erişimdir"; Java'da "paket" erişimdir. (Java'daki belirli erişim değiştiricileri okumaya değer.)
  • Java ve C # 'da iç içe geçmiş türler biraz farklı çalışır; özellikle farklı erişim kısıtlamalarına sahiptirler ve iç içe geçmiş türü belirtmediğiniz sürece static, kapsayıcı sınıfın bir örneğine örtük bir referansı olacaktır.

5
+1 Bu yeni başlayanlar için harika bir listedir.
Jim Schubert

3
@Jon Skeet: +1, Ve muhtemelen Java 7'ye kadar Lambda ve LINQ'u özlersiniz?
Kb.

1
"C # 'da, örnek değişken başlatıcıları temel sınıf kurucusundan önce çalışır; Java'da, ondan sonra çalışırlar (yani" bu "sınıftaki yapıcı gövdesinden hemen önce)" - Eeer, bunu detaylandırabilir misin? Ne dediğini gerçekten anladığımdan emin değilim :)
cwap

7
@cwap: C # 'da yürütme sırası "örnek değişken başlatıcıları, temel sınıf yapıcısı, yapıcı gövdesi" dir. Java'da "süper sınıf oluşturucu, örnek değişken başlatıcılar, yapıcı gövdesi" dir. (Örnek değişken başlatıcıları, bildirim noktasında bir örnek değişkenine bir değer atadığınızda elde edeceğiniz şeydir.)
Jon Skeet

1
@cwap: Evet, demek istediğim bu - ikincisi bir nesne başlatıcı.
Jon Skeet


17

Hiç kimsenin özelliklerden bahsetmemesine şaşırdım, C # 'da oldukça temel bir şey, ancak Java'da yok. C # 3 ve üzeri, özellikleri de otomatik olarak uygular. Java'da GetX / SetX türü yöntemleri kullanmanız gerekir.

Diğer bir belirgin fark, Java'da bulunmayan C # 3'teki LINQ ve lambda ifadeleridir.

Java'da eksik olan birkaç basit ama faydalı şey var, örneğin kelimesi kelimesine dizeler (@ ""), operatör aşırı yükleme, verim ve ön işlemci kullanan yineleyiciler de Java'da eksik.

C # 'daki kişisel favorilerimden biri, ad alanı adlarının fiziksel dizin yapısını takip etmek zorunda olmamasıdır. Bu esnekliği gerçekten seviyorum.


10

Çok fazla fark var ama aklıma bunlar geliyor:

  • Java'da operatör aşırı yükleme eksikliği. İnstance.Equals (instance2) ile instance == instance2 (özellikle w / string) karşılaştırmanızı izleyin.
  • I ile önekli OLMAYAN arabirimlere alışın. Genellikle bunun yerine Impl ile son eklenmiş ad alanları veya sınıflar görürsünüz.
  • İki kez kontrol edilmiş kilitleme, Java bellek modeli nedeniyle çalışmıyor.
  • Statik yöntemleri, belirli durumlarda (DSL'ler) çok yararlı olan sınıf adının önüne eklemeden içe aktarabilirsiniz.
  • Java'daki anahtar deyimleri varsayılan gerektirmez ve dizeleri büyük / küçük harf etiketleri (IIRC) olarak kullanamazsınız.
  • Java jenerikleri sizi kızdıracak. Java jenerikleri çalışma zamanında mevcut değildir (en azından 1.5'te), bunlar bir derleyici numarasıdır ve genel türler üzerinde düşünme yapmak istiyorsanız sorunlara neden olur.

4
Son kontrol ettiğimde, dizeler aşırı yüklenmedi == ve Java 7 için de eklendiğini duymadım. Ancak, dize birleştirme için + aşırı yük yaparlar.
Michael Madsen

3
Evet, dizeleri == ile karşılaştırmak yeni başlayanlar için çok yaygın bir tuzaktır. .equalskullanmak zorunda olduğun şey.
Michael Myers

Ayrıca, statik yöntemler hakkındaki yorumu anlamıyorum. Hemen hemen tüm diller statik yöntemlere veya eşdeğerlerine izin vermiyor mu?
Michael Myers

Neredeyse buna olumlu oy verdim, ancak jenerikler konusunda aynı fikirde değilim. Tip silmeyi seviyorum.
finnw

2
"Java'daki anahtar deyimleri bir varsayılan gerektirmez" - ne de C #.
RenniePet

8

.NET, jenerikleri yeniden tanımladı; Java jenerikleri sildi.

Aradaki fark şudur: ArrayList<String>.NET'te bir nesneniz varsa , nesnenin türüne sahip olduğunu (çalışma zamanında) söyleyebilirsiniz ArrayList<String>, oysa Java'da çalışma zamanında nesne türündedir ArrayList; Stringkısmı kaybolur. İçine Stringnesne ArrayListolmayanlar koyarsanız , sistem bunu uygulayamaz ve bunu yalnızca öğeyi dışarı çıkarmaya çalıştıktan sonra öğrenirsiniz ve döküm başarısız olur.


1
... Stringbu listeye nesne olmayanları bir yere denetlenmemiş bir dönüştürme yapmadan koyamayacağınızı eklemeye değer olsa da , derleyici sizi bu noktada derleyicinin artık genel sınırları kontrol edemeyeceği konusunda doğru bir şekilde uyaracaktır. Listeniz her zaman bir değişkeninde depolandığı sürece, List<String>içine String olmayan bir nesne ekleme girişimleri derlenmeyecektir.
Andrzej Doyle

"Dizge olmayan nesneler ArrayList'e, sistem bunu uygulayamaz": Sistemin bunu derleme zamanında uyguladığını unutmayın . Ancak bunu çevrim yaparak (veya jenerik kullanmayarak) aşabilirsiniz; daha sonra çalışma zamanı denetimi onu yakalayacaktır, ancak yalnızca ayıklama sırasında.
sleske

1
@Andrzej, @sleske: Ben sadece çalışma zamanından bahsediyorum. Nesneyi yansıtma yoluyla elde ettiğinizi ve addyöntemini çağırdığınızı (yine yansıma yoluyla) varsayalım. Sistem String, nesne olmayan bir şeyi hemen getmi yoksa sadece sonucunu oluştururken mi reddeder ?
Chris Jester-Young

@sleske: Ancak IIRC, tür kontrolünü atlatmak için yalnızca örtük bir atama yapmanız gerekir.
Niki

@Judah: Değişikliğinizi geri aldım (evet, bir yıl sonra), çünkü türden nesneleriniz olamaz List. Ve Listgibi türden nesnelere sahip olabilirsiniz . ( Onları dolaştırmak yerine kullanmak önemlidir , ancak söyleyemeyeceğiniz gerçeğini değiştirmez .)ArrayListLinkedListListArrayListnew List()
Chris Jester-Young

6

Java'dan C #'da kaçırdığım bir şey, kontrol edilen istisnaların zorunlu olarak ele alınmasıdır. C # 'da, bir yöntemin atabileceği istisnaların farkında olmaması ve bunları keşfetmek için belgelerin veya testlerin insafına kalması çok yaygındır. İşaretli istisnalarla Java'da böyle değildir.


1
FWIW, bu C # yokluğunda kabul edildi ve onları dışarıda bırakmanın mantığı gerçektir. Düşünün artima.com/intv/handcuffs.html . Tasarımcılar felsefi olarak kontrol edilen istisnalara karşı değiller - daha ziyade, tüm tüylü dezavantajlar olmadan benzer faydalar sunan daha iyi bir teknik bekliyorlar.
Greg D

Evet, evet, çok tartışmalı bir konu ...
sleske

2
C # 'ın istisnaları kontrol etmemiş olmasını seviyorum, ancak bu farkı gösteren ilk gönderiydi, yani +1.
Nick

5

Java, değer türleri yerine ilkel öğeler için otomatik kutulama özelliğine sahiptir, bu nedenle System.Int32[]C # ' Integer[]da bir değerler dizisi olmasına rağmen , Integernesnelere bir referans dizisidir ve bu nedenle daha yüksek performanslı hesaplamalar için uygun değildir.


1
Pete: Bu harika bir nokta ve hiç bilmediğim veya en azından hiç düşünmediğim bir nokta (bir C # geliştiricisi ve Java'da yeni olmak).
Jim Schubert

4

Temsilci veya etkinlik yok - arayüzler kullanmanız gerekiyor. Neyse ki, satır içi sınıflar ve arayüz uygulamaları oluşturabilirsiniz, bu yüzden bu o kadar da önemli değil


3
"o kadar da önemli değil". Sağ. Çünkü x => x.Foovs. new Bar() { public void M(SomeType x) { return x.Foo; } }- kodun 10 kat daha kısa olması kimin umurunda?
Kirk Woll

2

Java'daki yerleşik tarih / takvim işlevi, System.DateTime ile karşılaştırıldığında korkunçtur. Burada bununla ilgili pek çok bilgi var: bununla Java Tarih ve Saat API'sinin sorunu nedir?

Bunlardan bazıları bir C # geliştiricisi için geçerli olabilir:

  • Java Date sınıfı değiştirilebilir, bu da geri dönme ve geçme tarihlerini tehlikeli hale getirebilir.
  • Java.util.Date yapıcılarının çoğu kullanımdan kaldırılmıştır. Sadece bir tarihi örneklemek oldukça ayrıntılıdır.
  • Web hizmetleriyle iyi bir şekilde birlikte çalışmak için java.util.Date sınıfını hiç almadım. Çoğu durumda, her iki taraftaki tarihler çılgınca başka bir tarih ve saate dönüştürüldü.

Ek olarak, Java, GAC ve kesin olarak adlandırılmış derlemelerin sağladığı tüm özelliklere sahip değildir. Jar Hell , harici kitaplıkları bağlarken / referans verirken neyin yanlış gidebileceğini ifade eden bir terimdir.

Paketleme / dağıtım söz konusu olduğunda:

  • Web uygulamalarını, birkaç farklı uygulama sunucusunda (Glassfish, Websphere, vb.) kurulan ve çalıştıran bir EAR / WAR formatında paketlemek zor olabilir.
  • Java uygulamanızı bir Windows hizmeti olarak dağıtmak, C # 'dan çok daha fazla çaba gerektirir. Bunun için aldığım önerilerin çoğu ücretsiz olmayan bir 3. taraf kitaplığı içeriyordu
  • uygulama yapılandırması, projenize bir app.config dosyası eklemek kadar kolay değildir. Bir java.util.Properties sınıfı var, ancak bu sınıf o kadar sağlam değil ve .properties dosyanızı bırakmak için doğru yeri bulmak kafa karıştırıcı olabilir

1

Java'da delege yok. Bu nedenle, delegelerin masaya getirdiği tüm faydaların yanı sıra etkinlikler de farklı işler. Bir yöntemi bağlamak yerine, bir arayüz uygulamanız ve bunun yerine onu eklemeniz gerekir.


1

Röportaj listemde göze çarpan bir şey, Java'da yöntem gizleme için "yeni" anahtar kelime benzeri olmaması ve bu nedenle "buraya yeni koymalısınız" uyarısı olmamasıdır. Geçersiz kılmak istediğinizde yanlışlıkla saklanan yöntem hatalara yol açar.

(örneğin düzenleyin) Örnek, B, A'dan türemiştir (C # sözdizimini kullanarak, Java son kontrol ettiğim şekilde davranır, ancak derleyici uyarısı vermez). A'nın foo'su çağrılır mı, yoksa B'nin foo mu? (A'lar çağrılır, muhtemelen B'yi uygulayan geliştiriciyi şaşırtır).

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
Java'da bir örnek yöntemini yanlışlıkla nasıl gizlersiniz? ya nihaidirler - yani geçersiz kılma ya da newkasıtlı olarak gizleme yöntemi yoktur - ya da gizli değil, dolayısıyla geçersiz kılınmışlardır.
Pete Kirkham

Örnek eklendi. Bir süredir Java'da test etmedim, ancak mülakat sorusu aslen önceki şirketimden Java grubundan geldi. C # 'da derleyici uyarısı genellikle insanların adı değiştirdiği anlamına gelir. Oldukça tuhaf bir durum olduğunu kabul ediyorum, ancak OP dilleri değiştirirken sorun bulması zor olabilecek şeyler arıyor gibiydi.
Jim L

1
Buradaki fark, Java'da tüm yöntemlerin sanal olmasıdır (yani Java'da, çağrılan B.foo () olacaktır çünkü Java her zaman dinamik yöntem gönderimi yapar), oysa C # yöntemlerinde varsayılan olarak sanal değildir (ve A.foo () çağrılacaktır). Java için birçok kodlama stili denetleyicisi size B'nin @Override notunu kullanması gerektiğini söyleyecektir.
William Billingsley'in

1

Java'da LINQ yok ve belgeler cehennem gibi. Java'daki kullanıcı arayüzleri geliştirmek zordur, Microsoft'un bize verdiği tüm iyi şeyleri (WPF, WCF, vb.) Kaybedersiniz, ancak kullanımı zorlaşır, neredeyse belgelenmemiş "API'ler".


0

C # 'dan gelen Java ile çalışırken şu ana kadar karşılaştığım tek sorun İstisnalar ve Hatalar farklıdır.

Örneğin catch (Exception e) kullanarak yetersiz bellek hatasını yakalayamazsınız.

Daha fazla ayrıntı için aşağıdakilere bakın:

neden-java-lang-outofmemoryerror-java-yığın-alanı-yakalanmadı


Uygulama programcısını yakalamasından caydırmak için kasıtlı olarak tasarlandı
finnw

Evet, eminim öyledir, ancak endişelenmeniz gereken tek şey istisnaları yakalamak olan C # tarafından geliyor, beni bir döngü için fırlattı :)
Chris Persichetti

0

Java'da bulunmayalı çok uzun zaman oldu, ancak uygulama geliştirmede hemen fark ettiğim şeyler C # olay modeli, C # sürükle ve bırak ile Swing'de Düzen Yöneticilerini kullanma (Uygulama geliştirme yapıyorsanız) ve istisna yönetimi oldu. Java, bir istisna yakalamanızı sağlar ve C # gerekli değildir.


0

Başlığınızdaki çok doğrudan sorunuza yanıt olarak:

"Java'yı öğrenen C # geliştiricileri, gözden kaçabilecek en büyük farklar nelerdir?"

C: Java'nın Windows'ta oldukça yavaş olduğu gerçeği.


4
OpenSuSE 64bit ve Windows 7 64bit çalıştırıyorum ve Eclipse IDE Windows'ta daha hızlı ("görünüyor"). Cevabınız kişisel gözlemlere mi yoksa gerçek ölçütlere mi dayanıyor?
Jim Schubert

0

Java'ya geçiş yaptığımda benim için en rahatsız edici fark, dize bildirimi.

stringJava'da C # (çoğu zaman)String

Oldukça basit, ama güven bana, bu size alışkanlığı var ne zaman çok fazla zaman kaybetmek yapar sdeğil S!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.