LoginSignup
20
16

More than 3 years have passed since last update.

C#とJavaの書き方の違いをまとめる

Last updated at Posted at 2020-02-09

前置き

いつもはC#で開発をしていますが、使用するAPIにC#用のインターフェースがまだ整っていなくJavaで開発を始めてみました。
あまりJavaは触ったことがなかったため、C#でいう「xxxx」はJavaでいう「xxxx」というのをまとめてみました。
私がよく使っている予約語、実装方法が中心となっています。そのため全ての違いが網羅できているわけではありません。

C#とJavaの予約語、実装方法の違い

予約語の違い

C#、Javaでの予約語の違い、変わらない点をまとめてみました。
同じ、似ていると思った項目を横並びにして比較してみます。

差異 C# Java 備考
namespace package
using import
なし class class
: extends クラス継承
なし interface interface
なし abstract abstract
virtual なし 継承先で関数をoverride可能にする場合、C#はvirtualを付与、Javaはなし
override @Override C#は定義に含めるが、Javaはアノテーション(C#で言う属性、Attribute)
readonly final 読み取り専用フィールド
const final 定数
sealed final クラス継承禁止、Javaは関数のoverride禁止としても使用する
なし Enum Enum 列挙型
struct なし 構造体

Javaには「struct」、「virtual」がありませんでした。
「struct」はclassでそれっぽく代用できるため問題なさそうですが、「virtual」は無いと少し困りそうです。
「virtual」については下記のタイトルでページの最後に掘り下げてみます。
・「C#のvirtualとJavaのfinal」

また、Javaの「final」がC#の複数の機能を含有しておりました。
それだけでなくJavaのみの使い方があるため、この違いについては下記タイトルでページの最後に掘り下げてみます。
・「定数の宣言、設定方法の違い」

実装方法の違い

C#での実装方法、Javaでの実装方法、どちらにしかない実装方法をまとめてみました。
こちらも同じ、似ていると思った項目を横並びにして比較してみます。

やりたいこと C# Java
属性自作 Attributeの継承 @interfaceでクラス定義
拡張メソッド public static class なし
interfaceのデフォルト実装 なし
C#8.0 (.NET Core 3.0)で追加
interfaceを継承し、メンバをdefaultで定義
リソースの自動解放 using(Stream stream = new Stream()) try-with-resources
型パラメータの制約 where T: int <T extends Number>
上記例)void Test<T>(T arg) void Test<T>(T arg) where T : int <T extends Number> void Test(T arg)
Null許容型宣言 Nullable<T>,T? Optional<T>
ラムダ式 ()=>{ } ()->{ }
コールバック引数なし Action Runnable
同上 引数1つ Action<T> Consumer<T>
同上 引数2つ Action<T1,T2> BiConsumer<T,U>(引数は2つまで)
同上 返り値あり Function<R> Supplier<T>
API仕様の関数型インターフェースを見る限りなし
同上 引数1つ、返り値あり Function<T,R> Function<T,R>
同上 引数2つ、返り値あり Function<T1,T2,R> BiFunction<T,U,R>(引数は2つまで)

今回挙げた機能については使い勝手は違えどC#、Javaの両方が同等の機能を持っていることがわかりました。

また、コメント欄でご指摘頂いている通り、C#にもinterfaceのデフォルト実装機能がC# 8.0より追加されています。
abstractとinterfaceで迷い後者で実装したけど、継承先で同じ実装を行った経験がある人はきっといるはず。私です
これは是非活用していきたいですね。

また、C#で言う「Action」、「Function」、いわゆるコールバックの使い勝手がかなり違いそうです。
「コールバック」については下記のタイトルでページの最後に掘り下げてみます。
・コールバックの使い方の違い

C#とJavaで似ているようで違う点を掘り下げる

「予約語の違い」、「実装方法の違い」で挙げた3つについて掘り下げていきます。

C#のvirtualとJavaのfinal

C#では「virtual」でoverrideを可能にし(正確には仮想メソッドとして実装)、Javaは「final」でoverrideを禁止します。
つまりJavaの関数に「final」を付けなかった場合、C#の感覚で言うと常に「virtual」での実装になります。
いつの間にかoverrideされてる!?といった状況になりたくなければ必ず「final」を付けたほうがよさそうですね。。

※追記
コメント欄でご指摘頂いているように「final」を付与しているかいないかで呼び出しコストが変わってきます。
シビアなメモリ、処理速度が求められる場合は是非付与していきましょう。

コールバックの使い方の違い

C#とJavaのコールバックの違いはざっくりとこんな感じです。
この違いを把握していればC#とJavaで混乱するとはなさそうです。

  • Javaのコールバックは引数の数に上限があり、C#は最大16個まで取れる。

  • Javaのコールバックで数値型を引数に取れないが、C#は全ての型を引数に取れる。(※1)

※1
今回記事に挙げたJavaのコールバックは参照型のみを引数に取れます。
そのためC#と違い、Javaでは数値型を引数に取ることができません。数値が設定できなくて困惑したのは私です
その代わりに数値型用のコールバックがあり下記の名前で定義されているためこちらを使います。
・「数値型」Consumer
・Obj「数値型」Consumer
・「数値型Function」
・To「数値型」Function
・To「数値型」BiFuction

定数の宣言、設定方法の違い

C#の「const」、「readonly」、Javaの「final」を定数、読み取り専用として使用する場合の違いをまとめました。

定数宣言、代入方法 const readonly final
定数フィールドでの宣言
定数フィールドへ宣言場所以外での代入 × 〇 ※1 ×
ローカル変数での宣言 ×
ローカル変数での宣言場所以外での代入 × ×
引数への付与 × ×
宣言時の型制限 あり ※2 なし なし

上記以外の違いとして「final」の機能はコメントでご指摘頂いている通り、再代入の禁止になります。
C#は基本的に宣言場所以外での代入をすることができないため、これに該当する機能はありません。
強いて言うのであれば、ローカル変数でも宣言できる「readonly」といったところでしょうか。
もちろんこんな機能はないため是非、C#にもほしい機能です。

※1 readonlyは宣言時以外、コンストラクタ内でのみ代入可能
※2 宣言できる型についてはこちらconst キーワード - C# リファレンス _ Microsoft Docs

参考にしたページ

Java(tm) Platform, Standard Edition 8 API仕様
Javaのfinalを大解剖 finalの全てがここにある!!

最後に

C#とJavaは言語のベースが同じだから似ていると聞いたことはありました。調べていく中で予約語に同じものが多かったりと確かに似ていると感じました。
また、実際にコードを書かないと気づけない違い(予約語が前後するなどの小さな違い)があったため、知識をため込むだけでなく、アウトプットのすることの大事さを改めて感じました。
ただ似た書き方をしていながら、異なる動きをする場合があるため、エラーが起きた場合に嵌らないようにしたいですね。

あと、何より情報のアップデート。。指摘して頂いた方々ありがとうございます。

20
16
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
16