JavaとC#の「int」の比較

2015/9/16 追記
この記事の最後の速度比較の結論には誤りがあります。
きちんとやれば、C#の結果はもっと速いものになります。

引用元のブログの方が検証されているので、リンクをさせていただきます。
http://crapp.hatenablog.com/entry/2015/01/17/230539

大変失礼をいたしました。

～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～

お疲れ様です！きうちです♪

今日は、JavaとC#の比較についてお話します！
ちなみに自分はどちらの言語も大好きで現場経験もあります＾＾

Javaをご存知でC#をご存知ない方の中には結構
「はっきり言って同じだ」
ということをご存知ない方も多いかと思います。
本題に入る前にここからいきましょうか。

ではまず、HelloWorldを比較してみます。

Java。

```java:HelloWorld.java

public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("Hello World!");
	}
}
```

C#。

```csharp:HelloWorld.cs
using System;

public class HelloWorld
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");
    }
}
```

表示方法が「System.out.println」と「Console.WriteLine」という風にクラス・メソッドが違いますが、雰囲気は一緒。
表示メソッドがstaticメソッドであるところも一緒。

Javaがjava.lang配下のクラスはをimportしなくてもいいのに対して、C#はSystemをusingしなきゃいけないところとかは違いますが、
Javaの「パッケージ」に対し、C#には「名前空間」というものがあるあたり共通しています。
ま、usingはクラスではなく名前空間を指定するんですが…。

あ、あと.NETには「メソッド名は大文字で始める」って命名ルールがあるからメソッド名が「Main」ってなってますが、字面は一緒。起動引数も一緒。

じゃあ、「1から20までの偶数の合計を計算してみます。」というと。

```From1To20.java
public class From1To20 {
	public static void main(String[] args) {
		int sum = 0;
		for (int i = 1; i <= 20; i++) {
			if (i % 2 == 0) {
				sum += i;
			}
		}
		System.out.println(sum);
	}
}
```

```csharp:From1To20.cs
using System;

public class From1To20
{
    public static void Main(string[] args)
    {
        int sum = 0;
        for (int i = 1; i <= 20; i++)
        {
            if (i % 2 == 0)
            {
                sum += i;
            }
        }
        Console.WriteLine(sum);
    }
}
```

本当はこのプログラム、iの初期値を2にしてi+=2すればif文いらなくなるんですが、まあ、if文の比較も見てほしいのであえてこれで＾＾

変数の宣言も、整数が「int」なのも、for文の書き方もif文の書き方も剰余演算の仕方もまったく一緒です。
あ、波括弧の書き方の標準的なお作法がちょっと違うかな。
ちなみにどちらも「110」と表示されます。

どちらもC言語がご先祖様だから、こうなっているのでしょうね。

せっかくなんで、C言語での「1から20の偶数の合計」も載せておきましょうか。

```c:From1To20.c
#include <stdio.h>

int main(int argc, char *argv[])
{
        int i;
        int sum = 0;
        for (i = 1; i <= 20; i++) {
            if (i % 2 == 0) {
                sum += i;
            }
        }
        printf("%d\n", sum);
}
```

閑話休題。

実はこの前調べ物をしていて偶然発見したブログで、気になる記述を見つけました。

* なぜJavaはC#と比べて駄目なのか - 29歳からのPG/SE人生
http://crapp.hatenablog.com/entry/2013/07/04/050930

この中に、プリミティブ型(intとかdoubleとかですね）の話題があって、
「Javaではintはオブジェクト扱いではなく、ヒープメモリにも行かない」というようなお話が書かれています。

たとえばint型変数を文字列化する場合、次のように違いますね。

```java:Java
int a = 256;
String b = Integer.toString(a);
```
```csharp:C#
int a = 256;
String b = a.ToString();
```

C#では、数字が発生した瞬間オブジェクトとみなされますから、

```csharp
String x = 1.ToString();
```
みたいな「Java人には気持ち悪い(笑)」書き方もできちゃいますね。
もっとも、JavaでもStringについてはこうだけど。

ところで上記記事、その項目の最後に

> ※ただし、仮にJavaのプリミティブ型がC#のデータ型よりも高速に機能するのであれば、この仕様は正当化されると思う。ベンチマークもないからなんとも言えんけど。

と気になることが書かれています。

そうか、ベンチマークはないのか。

では、作って検証してみよう！

と思って、作ってみました。

```java:TestOfInt.java
public class TestOfInt {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		int ans = 0;

		long start = System.currentTimeMillis();

		for(int j = 0; j < 50000; j++) {
			for(int i = 1; i <= 50000; i++) {
				ans += i;
			}

			for(int i = 1; i <= 50000; i++) {
				ans -= i;
			}
		}

		long end = System.currentTimeMillis();

		System.out.println(end - start + "ms.");
	}

}
```
```csharp:Program.cs
using System;
using System.Diagnostics;

namespace TestOfInt
{
    class Program
    {
        static void Main(string[] args)
        {
            int ans = 0;

            Stopwatch sw = new Stopwatch();
            sw.Start();

            for (int j = 0; j < 50000; j++)
            {
                for (int i = 1; i <= 50000; i++)
                {
                    ans += i;
                }

                for (int i = 1; i <= 50000; i++)
                {
                    ans -= i;
                }
            }

            sw.Stop();
            Console.WriteLine("{0}ms.", sw.ElapsedMilliseconds);

            Console.ReadKey();
        }
    }
}
```

上記は同じものをJavaとC#で書きました。
ある変数に１から50000までの数字を足し、しかる後に１から50000までの数字を引くということを５万回繰り返す、というシンプルかつ「すげー意味のねー」プログラムです。
まるで穴を掘って埋める作業を毎日やっているようです。
でも、動作速度を計るのには十分じゃろと。

あ、所要時間の計り方はまったく同じにはできないので、それぞれのやり方になっています。

結果ですが、

- Java : 2783ms.
- C# : 15236ms.

という結果が出ました！

使用したマシンは以下のとおり。

- CPU : Intel Core-i3 2120 3.30GHz
- MEM : 4.0GB
- OS : Windows 7 Professional SP1 (32bit)

どうやら、やはり「オブジェクトにしていない」のは伊達ではないようです。

★ ★ ★

JavaとC#には他にも「同じところ」「似たところ」や「細かく見ると違うところ」などたくさんありますが、そういう比較をしながらコーディングしてみるのもまた乙だなと思っています＾＾

以上、きうちでした。それではまた！

##2014/12/14 追記
C言語版の1から20の偶数の合計について、起動引数の型が間違っていたので修正しました。
##2015/9/16 追記
結論に誤りがある旨、冒頭に追記しました。