JavaとC#の違いをまとめる

比較的に似ていると言われるJavaとC#を実際に使用してみて、それぞれの違いについてちょっと戸惑ったところをまとめてみます。

## Javaについて
* 1996年にサン・マイクロシステムズによって市場リリースされ、2010年に同社がオラクルに吸収合併
* ランタイム環境はJava Runtime Environment (JRE)
* JVM（Java仮想マシン）上で動作し、プラットフォーム非依存
* 最新バージョン(2024年12月現在)　Java23

## C#について
* マイクロソフトが開発
* ランタイム環境は、Common Language Runtime (CLR)
* Windowsの.NET Framework上で動作することを前提として開発された言語であるが、現在はクロスプラットフォームな.NETランタイム上で動作
* 最新バージョン(2024年12月現在)　C#13(.NET9サポート)

***
ここからJavaとC#を使用してみて、戸惑ったことをまとめていきます。

# package(Java)とnamespace(C#)
どちらも、クラスやインターフェイスを整理する仕組みです。

**■ package**
関連するクラスやインターフェイスを物理的なディレクトリ構造に基づいてグループ化します。実際のファイルシステムの階層構造と一致させる必要があります。また、ソースファイルの最初に```package```キーワードを使い定義します。
他のパッケージに含まれるクラスやインターフェイスを使用する際は、```import```キーワードを使用します。
**■ namespace**
namespaceは、ファイルシステムとは直接関係がなく、プログラム内でのクラスやインターフェイスを整理する役割があります。
名前空間を宣言するには、```namespace```キーワードを使用します。```.```演算子を使用して区切ることも可能です。
別名前空間を呼び出す際は、```using```ディレクティブを使用します。

# クラスの継承
**■ Java**
```extends```キーワードを使用。
```Sample.java
public class Animal {
    public void eat() {
        System.out.println("Animal is eating.");
    }
}

public class Dog extends Animal {
    public void bark() {
        System.out.println("ワン");
    }
}
```

**■ C#**
```:```を使用。
```Sample.cs
public class Animal {
    public void Eat() {
        Console.WriteLine("Animal is eating.");
    }
}

public class Dog : Animal {
    public void Bark() {
        Console.WriteLine("ワン");
    }
}
```


# interfaceの実装
**■ Java**
```implements```キーワードを使用。
```Sample.java
public interface Animal {
    void bark();
}

public class Dog implements Animal {
    public void bark() {
        System.out.println("ワン");
    }
}
```

**■ C#**
```:```を使用。
```Sample.cs
public interface Animal{
    void bark();
}

}
public class Dog : Animal{
   public void bark()
   {
      Console.WriteLine("ワン");
   }
}
```

# アクセス修飾子の違い
**■ Java**
<table>
  <captionJavaのアクセス修飾子</caption>
  <thead>
    <tr>
      <th>アクセス修飾子</th> <th>説明</th>
    </tr>
  </thead>
  <tr>
    <td> public </td> <td>どのクラスからでもアクセス可能</td>
  </tr>
  <tr>
    <td> protected </td> <td>同一パッケージ内およびサブクラスからアクセス可能</td>
  </tr>
   <tr>
    <td> デフォルト（指定なし） </td> <td>同一パッケージ内からのみアクセス可能</td>
  </tr>
   <tr>
    <td> private </td> <td>同じクラス内からのみアクセス可能</td>
  </tr>
</table>

**■ C#**

<table>
  <captionJavaのアクセス修飾子</caption>
  <thead>
    <tr>
      <th>アクセス修飾子</th> <th>説明</th>
    </tr>
  </thead>
  <tr>
    <td> public </td> <td>どのクラスからでもアクセス可能</td>
  </tr>
  <tr>
    <td> protected </td> <td>同じクラスおよび派生クラス内からアクセス可能</td>
  </tr>
   <tr>
    <td> private </td> <td>同じクラス内のみアクセス可能</td>
  </tr>
   <tr>
    <td> internal </td> <td>同一アセンブリ内からのみアクセス可能</td>
  </tr>
   <tr>
    <td> protected internal </td> <td>同一アセンブリ内および派生クラスからアクセス可能</td>
  </tr>
   <tr>
    <td> private protected </td> <td>同じクラスと同じアセンブリ内の派生クラスからのみアクセス可能</td>
  </tr>
   <tr>
    <td> file </td> <td>宣言された型は現在のソース ファイルでのみ表示される</td>
  </tr>
</table>

C#では、アクセス修飾子が指定されていない場合は、既定のアクセシビリティが使用されます。
[Microsoft公式ドキュメント　アクセス修飾子](https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/access-modifiers)
[Microsoft公式ドキュメント　アクセシビリティ レベル](https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/accessibility-levels)

# プロパティ設定
**■ Java**
getter/setterメソッドを使用
```User.java
public class User {
    private String name;
    private String password;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
```
**■ C#**
get/setアクセサを使用
```User.cs
public class User
{
    public string Name { get; set; }
    public string Password { get; set; }
}
```
# 文字列型のStringとstring
**■ Java**
文字列型の変数を宣言する際は```String```を使用します。```string```では、エラー。

**■ C#**
```String```、```string```のどちらでも宣言可能ではあるが、2つには違いがあります。
```string```は、```System.String```のエイリアス（別名）として機能します。

・ **S**tring
```System.Stringクラス```を指す。大文字で始まる```String```は、C#内でクラス名として使用されます。

・ **s**tring
C#のキーワードであり、文字列型を表すために使用されます。小文字で始まる```string```は、C#の言語仕様において基本的なデータ型の一つとして扱われます。
```Sample.cs
String a = "aaa";
string b = "bbb";

String.IsNullOrEmpty(a);
string.IsNullOrEmpty(b);
```
どちらもエラーとはならないが、変数宣言の際は```string```、Stringクラスのstaticメソッドを使用する際は```String```を使用することが推奨されます。

https://clickan.click/string-difference/

https://kuroeveryday.blogspot.com/2014/09/string.html

# 拡張for文とforeach文
**■ Java**
```Sample.java
int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) {
    System.out.println(number);
}
```
**■ C#**
```Sample.cs
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
foreach (int number in numbers) {
    Console.WriteLine(number);
}
```

# 例外処理(チェック・非チェック例外)

**■ Java**
Javaには、```チェック例外(Checked Exceptions)```と```非チェック例外(Unchecked Exceptions)```の2つの分類があります。
**・チェック例外**
コンパイラによって強制される例外で、メソッドがスローする可能性のある例外を明示的に宣言する必要があります。呼び出し側はその例外を処理するための処理(**try-catch**や**throws**)を記述する必要があります。代表的なチェック例外には```IOException```や```SQLException```など。
**・非チェック例外**
RuntimeExceptionクラスのサブクラスであり、コンパイラによってチェックされない例外。必ずしも例外処理を記述する必要はないです。代表的な非チェック例外には```NullPointerException```や```ArrayIndexOutOfBoundsException```など。
```Sample.java
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class CheckedException {
    //IOExceptionは、チェック例外である為try-catchが必須（もしくはthrows句を記述）
    //行わない場合、コンパイルエラーとなる
    public static void main(String[] args) {
        File file = new File("sample.txt");
        FileReader fileReader = null;

        try {
            fileReader = new FileReader(file);
            int data;
            while ((data = fileReader.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // リソースを解放
            //finallyでもtry-catchが必要
            if (fileReader != null) {
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
```

https://qiita.com/omix222/items/eb3bcdd2fd98794d8a35


**■ C#**
C#では、全ての例外が非チェック例外として扱われます。その為、柔軟にエラー処理を行うことができます。

# 参考
https://mupiantech.com/%E3%80%90c%E3%80%91java%E3%81%A8c%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9%E3%81%AE%E9%81%95%E3%81%84/#index_id4