1. メモリの仕組み
すべてのコンピュータには メインメモリ があります。これは何で、どんな性質があり、そして何よりも私たちにとってどんな利点があるのでしょうか。
あらゆるプログラム(Java で書かれたプログラムも含む)は、実行の前にメインメモリに読み込まれます。メインメモリには、プログラムのコード(プロセッサが実行するもの)と、プログラムのデータ(プログラム自身がメモリに配置するもの)が存在します。
では、メインメモリとは何で、何に似ているのでしょうか?
Excel を想像してみてください 😎 Excel のシートはセルで構成され、各セルにはその一意の番号があります(A1、A2、... B1、B2)。セル番号が分かっていれば、そのセルに値を書き込んだり、そこに保存されている値を取得したりできます。コンピュータのメモリもこれに似ています。

プログラムとそのデータは実行中、メモリに保存されます。コンピュータのメモリ全体は小さなセル – バイトとして表されます。各セルには一意の番号があり、0、1、2、3、...(番号付けは 0 から)となっています。セルの番号が分かっていれば、そのセルに何らかのデータを保存したり、そこから取り出したりできます。あるセルにはプログラムのコード – プロセッサへの命令の集合が、別のセルにはそのプログラムのデータが格納されます。セルの番号はセルのアドレスとも呼ばれます。
プロセッサは、メモリに読み込まれたプログラムの命令を実行できます。ほとんどすべての命令は、いくつかのセルからデータを取り出す → それに何か処理を行う → 結果を別のセルに格納する、というものです。
数百の単純な命令を組み合わせることで、複雑で有用な処理が実現します。
プログラムのコードで変数を宣言すると、未使用のメモリの一部がそのために割り当てられます。通常は数バイトです。変数を宣言する際には、その変数に保存する情報の型(数値、テキスト、その他)を必ず指定します。型が分からなければ、変数にどれだけのメモリ領域を割り当てるべきか判断できないからです。
コンピュータ黎明期には、プログラムはメモリセルの番号だけを扱っていました。しかし後に、プログラマの利便性のためにセルに名前を付けるようになりました。変数の一意な名前は、まず何よりもプログラマのためのものです。実行時のプログラムにとっては番号だけでも問題なく処理できます。
2. メモリ上の変数
Java には、整数を保存するための基本的なデータ型が 4 つあります。これは byte、short、int、long です。
| 型 | サイズ(バイト) | 名称の由来 |
|---|---|---|
|
|
Byte(1 バイトのメモリを占有するため) |
|
|
Short Integer の略 |
|
|
Integer の略 |
|
|
Long Integer の略 |
また、Java には浮動小数点数の型が 2 つあります — float と double:
| 型 | サイズ(バイト) | 名称の由来 |
|---|---|---|
|
|
Floating Point Number の略 |
|
|
Double Float の略 |
プログラムの実行が変数の作成命令に到達するたびに、その変数のための小さなメモリ領域が割り当てられます(サイズは変数の型に依存します)。
変数のアドレスとは、その変数に割り当てられたメモリブロックの先頭セルのアドレスを指します。
Java のプログラムはメモリに直接アクセスすることを禁止されています。メモリ操作はすべて Java 仮想マシン(JVM) を介してのみ行われます。
3. メモリにおける String 型
String 型は大量のデータを保持できるため、単なるデータ型ではなく完全なオブジェクトです。
String 型のデータ(テキスト)は専用のオブジェクトに格納され、そのためのメモリが確保されます。そして、そのオブジェクトのアドレスが変数に入れられ、変数自身にもメモリが割り当てられます。

- 変数 a(int 型)は4バイトを占有し、値 1 を保持します。
- 変数 b(int 型)は4バイトを占有し、値 10,555 を保持します。ここでのカンマは小数点ではなく桁区切りです。小数部はピリオドで区切ります。
- 変数 d(double 型)は8バイトを占有し、値 13.001 を保持します。
- 変数 str(String 型)は、D12 という値、すなわちテキストを含むオブジェクトの先頭セルのアドレスを保持します。
オブジェクト(テキストを含む)である String は、別個のメモリブロックに格納されます。その先頭セルのアドレスが変数 str に保存されています。
4. 代入すると何が起こるか
もう一つ重要なのは、代入がどのように機能するかです。例えば:
int a = 10;
int b = a;
b = 20;
System.out.println(a); // 10
この例では、メモリに 2 つのセルが作られます。1 つは a、もう 1 つは b のためです。b = a; と書くと、コピーされるのは値(10)であって、「箱」そのものではありません。したがって、b を変更しても a には影響しません。
次に、同様のことを文字列で見てみます:
String s1 = "Hello";
String s2 = s1;
s2 = s2 + " World";
System.out.println(s1); // "Hello"
System.out.println(s2); // "Hello World"
ここでは、変更が行われるまでは s1 と s2 の両方が同じ文字列 "Hello" を参照しています。しかし、s2 = s2 + " World"; を実行すると、s2 には新しい文字列 "Hello World" が作られ、s1 は引き続き古い文字列 "Hello" を指します。
5. なぜプログラミングでは多くが 0 から番号付けされるのか
なぜプログラミングではほとんどの場合 0 から数えるのか、不思議に思う人は少なくありません。実は、0 から数える方が便利な場面が非常に多いからです(もちろん、1 から数える方が都合のよい場合もあります)。
比喩で考えてみましょう。あなたは店で長い行列に並んでいます。レジ係が、すべての購入者は20番目から第二レジへ、と言いました。彼らの番号はどうなるでしょうか。20、21、22、23、...。自然です。では 20 番目を基準にした相対番号では? 0、1、2、3、...
集合を「最初の要素の番号」+「個数」で与えると、集合内の相対インデックスは +0、+1、+2、... になります。
プログラミングでも同じです。もし変数に 100 バイトのメモリが割り当てられ、先頭バイトのアドレスが X なら、すべてのバイトのアドレスは X+0、X+1、X+2、...、X+99 となります。つまり、インデックス 0、1、2、99 を持つバイトの集合が得られるわけです。
データブロック内部の相対アドレスで考えると、番号付けは常に 0 から始まります。これが、0 始まりの数え方の第一の、そして最も一般的な理由です。
GO TO FULL VERSION