Javaを学ぶC#開発者、見落としがちな最大の違いは何ですか?[閉まっている]


87

Javaを学びたいと考えているC#開発者にとって、指摘すべき2つの言語の間に大きな根本的な違いはありますか?

物事は同じだと思っている人もいるかもしれませんが、見逃してはならない重要な側面がいくつかありますか?(またはあなたは本当に台無しにすることができます!)

たぶん、OOP構造、GCの動作方法、参照、デプロイメント関連などの観点から。




また、見落とされがちなのは、独自の「C#の隠し機能」stackoverflow.com/questions/9033/hidden-features-of-c
John K

回答:


122

私の頭のてっぺんからいくつかの落とし穴:

  • Javaにはカスタム値型(構造体)がないので、わざわざそれらを探す必要はありません。
  • Java列挙型は、C#の「名前付き数値」アプローチとは大きく異なります。彼らはもっとOOです。注意すれば、それらは大きな効果に使用することができます。
  • byte Javaで署名されています(残念ながら)
  • C#では、インスタンス変数初期化子は基本クラスコンストラクターよりも先に実行されます。Javaでは、実行(つまり、「this」クラスのコンストラクター本体の直前)に実行されます。
  • C#では、メソッドはデフォルトで封印されています。Javaでは、デフォルトで仮想です。
  • C#のデフォルトのアクセス修飾子は、常に「現在のコンテキストで利用可能な最も制限の厳しいアクセス」です。Javaでは「パッケージ」アクセスです。(Javaの特定のアクセス修飾子について読む価値があります。)
  • JavaとC#のネストされた型は、動作が多少異なります。特に、それらには異なるアクセス制限があり、ネストされた型を宣言しない限り、staticそれを含むクラスのインスタンスへの暗黙の参照があります。

5
+1これは初心者にとって素晴らしいリストです。
ジムシューベルト

3
@Jon Skeet:+1、そしてJava 7まではLambdaとLINQを見逃すでしょう?
KB。

1
「C#では、インスタンス変数初期化子は基本クラスのコンストラクターよりも前に実行されます。Javaでは、インスタンス変数の初期化子は実行後に実行されます(つまり、「this」クラスのコンストラクター本体の直前)」-ええと、これについて詳しく説明していただけますか?あなたの言っていることが本当に理解できるかわかりません:)
cwap 2010年

7
@cwap:C#では、実行順序は「インスタンス変数初期化子、基本クラスコンストラクター、コンストラクター本体」です。Javaでは、「スーパークラスコンストラクター、インスタンス変数初期化子、コンストラクター本体」です。(インスタンス変数初期化子は、宣言の時点でインスタンス変数に値を割り当てるときに取得するものです。)
Jon Skeet

1
@cwap:はい、そういう意味です。後者はオブジェクト初期化子です。
Jon Skeet 2010年


17

プロパティについて誰も言及していないことに驚いています。これは、C#では非常に基本的なことですが、Javaにはありません。C#3以降では、プロパティも自動的に実装されています。Javaでは、GetX / SetXタイプのメソッドを使用する必要があります。

もう1つの明らかな違いは、JavaにはないC#3のLINQ式とラムダ式です。

逐語的な文字列(@ "")、演算子のオーバーロード、yieldを使用するイテレータ、プリプロセッサなど、Javaには他にもいくつかの単純ですが便利なものがありません。

C#での私の個人的なお気に入りの1つは、名前空間名が物理ディレクトリ構造に従う必要がないことです。私はこの柔軟性が本当に好きです。


10

多くの違いがありますが、これらは私にとって頭に浮かびます:

  • Javaでの演算子のオーバーロードの欠如。instance.Equals(instance2)とinstance == instance2(特に文字列付き)を監視します。
  • 接頭辞Iが付いていないインターフェースに慣れてください。代わりにImplという接頭辞が付いた名前空間またはクラスがよく見られます。
  • Javaメモリモデルのため、ダブルチェックロックは機能しません。
  • クラス名を前に付けずに静的メソッドをインポートできます。これは、特定の場合(DSL)で非常に役立ちます。
  • Javaのswitchステートメントはデフォルトを必要とせず、文字列をケースラベル(IIRC)として使用することはできません。
  • Javaジェネリックはあなたを怒らせるでしょう。Javaジェネリックは実行時に存在しません(少なくとも1.5では)。これらはコンパイラのトリックであり、ジェネリック型を反映したい場合に問題が発生します。

4
最後に確認したところ、文字列は==をオーバーロードせず、Java7にも追加されたとは聞いていません。ただし、文字列の連結のために+をオーバーロードします。
Michael Madsen

3
はい、文字列を==と比較することは、初心者にとって非常に一般的な落とし穴です。.equalsあなたが使わなければならないものです。
マイケル・マイヤーズ

また、静的メソッドについてのコメントがわかりません。ほとんどすべての言語で静的メソッドまたは同等のメソッドが許可されていませんか?
マイケル・マイヤーズ

私はこれにほぼ賛成しましたが、ジェネリックについては同意しません。型消去が好きです。
finnw 2010年

2
「Javaのswitchステートメントはデフォルトを必要としません」-C#も必要ありません。
RenniePet 2013

8

.NETはジェネリックを具体化しました。Javaはジェネリックを消去しました。

違いは次のとおりです。ArrayList<String>オブジェクトがある場合、.NETでは、オブジェクトの型が(実行時)であることがArrayList<String>わかりますが、Javaでは、実行時のオブジェクトの型はArrayList;です。String一部が失われます。非Stringオブジェクトをに入れた場合ArrayList、システムはそれを強制できず、アイテムを抽出しようとした後にのみそれを知ることができ、キャストは失敗します。


1
...Stringチェックされていないキャストをどこかに行わずにそのリストに非オブジェクトを入れることはできないことを追加する価値はありますが、コンパイラはその時点でコンパイラがジェネリック境界をチェックできなくなったことを正しく警告します。リストが常にの変数に格納されている限り、List<String>文字列以外のオブジェクトをリストに挿入しようとしてもコンパイルされません。
Andrzej Doyle

「文字列以外のオブジェクトをArrayListに追加すると、システムはそれを強制できません」:システムコンパイル時に強制することに注意してください。ただし、キャストする(またはジェネリックを使用しない)ことでこれを回避できます。次に、ランタイムチェックがそれをキャッチしますが、抽出する場合のみです。
sleske 2010年

1
@ Andrzej、@ sleske:私はランタイムについてのみ話している。リフレクションを介してオブジェクトを取得し、そのaddメソッドを呼び出したとします(ここでもリフレクションを介して)。システムは非Stringオブジェクトをすぐに拒否しますか、それとも結果をキャストするときにのみ拒否しますgetか?
クリスジェスター-若い

@sleske:しかし、IIRCでは、型チェックを回避するために暗黙のキャストのみが必要です。
ニキ

@Judah:タイプのオブジェクトを持つことができないので、私はあなたの変更をロールバックしました(はい、事実の1年後)ListList、like ArrayList、およびの子孫であるタイプのオブジェクトを持つことができますLinkedList。(それらを渡すときのList代わりに使用することが重要ですArrayListが、それはあなたが言うことができないという事実を変えませんnew List()。)
クリスジェスター-ヤング

6

JavaのC#で見逃していることの1つは、チェックされた例外の強制処理です。C#では、メソッドがスローする可能性のある例外に気づかず、それらを発見するためのドキュメントやテストに翻弄されることはよくあることです。チェックされた例外を除いて、Javaではそうではありません。


1
FWIW、これはC#の開発で考慮されており、それらを除外する理由は現実的です。artima.com/intv/handcuffs.htmlを検討してください。設計者がチェックされた例外に哲学的に反対しているわけではありません-むしろ、彼らはすべての厄介な欠点なしに同様の利点を提供するより良い技術を待っています。
グレッグD

はい、はい、非常に論争の的となる主題です...
sleske 2010年

2
C#が例外をチェックしていないという事実は気に入っていますが、これは違いを指摘する最初の投稿だったので、+ 1です。
ニック

5

Javaには、値型ではなくプリミティブの自動ボックス化機能があるためSystem.Int32[]、C#の値の配列ですInteger[]が、Integerオブジェクトへの参照の配列であるため、パフォーマンスの高い計算には適していません。


1
ピート:それは素晴らしい点であり、私が知らなかった、または少なくとも考えたことのない点です(C#開発者であり、Javaを初めて使用する)。
ジムシューベルト

4

デリゲートやイベントはありません。インターフェイスを使用する必要があります。幸い、クラスとインターフェイスの実装をインラインで作成できるので、これはそれほど大したことではありません。


3
「そんなに大したことではない」。正しい。そのためx => x.Foonew Bar() { public void M(SomeType x) { return x.Foo; } }コードを気には10倍短いこと- ?
Kirk Woll

2

Javaに組み込まれている日付/カレンダー機能は、System.DateTimeと比較してひどいものです。ここにはこれに関する多くの情報があります:Java Date&Time APIの何が問題になっていますか?

これらのいくつかは、C#開発者にとっての落とし穴になる可能性があります。

  • Java Dateクラスは変更可能であるため、日付の返却と受け渡しが危険になる可能性があります。
  • ほとんどのjava.util.Dateコンストラクターは非推奨です。日付をインスタンス化するだけではかなり冗長です。
  • java.util.DateクラスをWebサービスとうまく相互運用できるようにしたことはありません。ほとんどの場合、どちらかの側の日付は他の日付と時刻に乱暴に変換されました。

さらに、Javaには、GACや厳密な名前のアセンブリがもたらす機能と同じ機能がすべて備わっているわけではありません。 ジャーヘルは、外部ライブラリをリンク/参照するときに問題が発生する可能性があることを表す用語です。

パッケージング/展開に関する限り:

  • いくつかの異なるアプリケーションサーバー(Glassfish、Websphereなど)に実際にインストールして実行するWebアプリケーションをEAR / WAR形式でパッケージ化するのは難しい場合があります。
  • JavaアプリをWindowsサービスとしてデプロイするには、C#よりもはるかに多くの労力が必要です。これについて私が得た推奨事項のほとんどは、無料ではないサードパーティのライブラリに関するものでした
  • アプリケーションの構成は、プロジェクトにapp.configファイルを含めるほど簡単ではありません。java.util.Propertiesクラスがありますが、それほど堅牢ではなく、.propertiesファイルをドロップする適切な場所を見つけると混乱する可能性があります。

1

Javaにはデリゲートはありません。したがって、デリゲートがテーブルにもたらすすべての利点は別として、イベントの動作も異なります。メソッドを接続するだけでなく、インターフェイスを実装してアタッチする必要があります。


1

私のインタビューリストに載っているb / cから飛び出すことの一つは、メソッドを隠すための「新しい」キーワードアナログがJavaになく、「ここに新しいものを置くべきだ」というコンパイラ警告がないことです。オーバーライドしようとしたときに誤ってメソッドが非表示になると、バグが発生します。

(たとえば編集)例、BはAから派生します(C#構文を使用すると、Javaは前回チェックしたのと同じように動作しますが、コンパイラの警告は表示されません)。Aのfooが呼び出されますか、それともBのfooが呼び出されますか?(Aが呼び出され、おそらく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
Javaでインスタンスメソッドを誤って非表示にするにはどうすればよいですか?それらは最終的なものであるため、new意図的に非表示にするオーバーライドやメソッドはありません。または非最終的なものであるため、非表示ではなくオーバーライドされます。
ピートKirkham

例を追加しました。しばらくJavaでテストしていませんが、面接の質問は元々、前の会社のJavaグループからのものでした。C#では、コンパイラの警告は通常、ユーザーが名前を変更することを意味します。かなり奇妙なケースだと認めますが、OPは、言語を切り替えるときに問題を見つけるのが難しい可能性があることを求めているようです。
ジムL

1
ここでの違いは、Javaではすべてのメソッドが仮想である(Javaでは常に動的メソッドディスパッチを行うため、呼び出されるのはB.foo()になる)のに対し、C#ではデフォルトでメソッドは仮想ではない(およびA.foo) ()が呼び出されます)。Javaの多くのコーディングスタイルチェッカーは、Bが@Overrideアノテーションを使用する必要があることを示しています。
William Billingsley 2010年

1

JavaにはLINQがなく、ドキュメントは地獄です。Javaのユーザーインターフェイスは開発が面倒です。Microsoftが提供してくれたすべての優れた機能(WPF、WCFなど)は失われますが、使いにくく、ほとんど文書化されていない「API」になります。


0

C#からのJavaを使用するときにこれまでに遭遇した問題の1つは、例外とエラーが異なることです。

たとえば、catch(Exception e)を使用してメモリ不足エラーをキャッチすることはできません。

詳細については、以下を参照してください。

why-is-java-lang-outofmemoryerror-java-heap-space-not-caught


これは、アプリケーションプログラマーがそれを捕まえるのを思いとどまらせるために、意図的にそのように設計されています
finnw 2010年

確かにそうだったと思いますが、例外をキャッチすることだけを心配しなければならないC#側から来て、私をループに投げ込みました:)
Chris Persichetti 2010年

0

Javaを使用してからかなりの時間が経ちましたが、アプリケーション開発ですぐに気付いたのは、C#イベントモデル、C#ドラッグアンドドロップとSwingでのレイアウトマネージャーの使用(App devを実行している場合)、およびJavaは、例外をキャッチし、C#は不要であることを確認します。


0

タイトルの非常に直接的な質問への回答:

「Javaを学ぶC#開発者、見落としがちな最大の違いは何ですか?」

A:JavaはWindowsではかなり遅いという事実。


4
私はOpenSuSE64ビットとWindows7 64ビットを実行していますが、Eclipse IDEはWindowsの方が高速です(「そうです」)。あなたの答えは個人的な観察に基づいていますか、それとも実際のベンチマークに基づいていますか?
ジムシューベルト

0

Javaに切り替えたときの最も厄介な違いは、文字列宣言です。

stringJavaのC#(ほとんどの場合)String

とても簡単ですが、私を信じてください。そうしsない習慣があると、多くの時間を失うことになりますS

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.