はじめに
この章では、カプセル化とアクセス修飾子について学習します。カプセル化はJava言語の3大要素(カプセル化、継承、ポリモーフィズム)の一つです。カプセル化によりオブジェクトの独立性を保つことができます。
また、mainメソッド、クラスとソースファイルの関係、クラスのインポートなどについても学習します。
これらの知識は、OCJPなどの試験でよく問われる内容です。しっかり理解するようにしましょう。
目次
- アクセス修飾子
- カプセル化
- mainメソッドの位置づけ
- Javaファイルの規則
- import文
- 章のまとめ
目標
- Javaの主な特徴であるカプセル化について理解する。
- クラスとソースファイルの関係、クラスのインポートの書き方について理解する。
アクセス修飾子
これまでのクラスや、クラスの構成要素であるメソッドに対して、先頭にpublicというキーワードを付加している場合としていない場合がありました。これらはアクセス修飾子というもので、付加した要素にアクセスできるかできないかを表します。
「アクセスできる」とは「見える(可視)」ということです。見えていればそれらを利用することができます。アクセス修飾子は、クラスやメンバ変数(フィールド)、メンバメソッド、コンストラクタに付加することができます。

Javaではクラスはそれぞれ特定のパッケージの中に配置されています。パッケージ内では、どのクラスも互いに「見える」状態です。つまり、アクセスできる状態が標準の状態です。これをデフォルトといい、アクセス修飾子が何も付加されていない状態をデフォルトアクセスといいます。デフォルトアクセスの場合、異なるパッケージからはアクセスすることができません。異なるパッケージからアクセスしたい場合は、public修飾子を付加します。
publicアクセス修飾子

classにpublic修飾子を付与すると、異なるパッケージから「見える(可視)」状態になり、他のクラスから利用することが可能になります。
アクセス修飾子を付与できるのは、classだけではなく、メンバ変数(フィールド)やコンストラクタ、メソッドなどに付加して、さらに細かいアクセス制御ができるようになっています。
ただし、classにpublicがついていない状態で、クラスの構成要素にpublicを付けても無駄です。
クラスそのものがパッケージを超えて見えない状態で、そのクラスの内部の構成要素が見えるはずはありません。
例題(publicアクセス修飾子(クラスにpublic修飾子が付加されていない場合))
以下は、publicがついていないクラスは、異なるパッケージのクラスからはアクセスできない例です。
以下のEmployeeクラスとEmpExecクラスを作成し、実行結果を確認してみましょう。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7A |
| クラス名 | Employee |
package chapter7A; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7B |
| クラス名 | EmpExec |
package chapter7B; |
コンパイル例:> javac chapter7A¥Employee.java
> javac chapter7B¥EmpExec.java
chapter7B/EmpExec.java:3: エラー: chapter7AのEmployeeはpublicではありません。パッケージ外からはアクセスできません
import chapter7A.Employee; //コンパイルエラーが発生する
^
chapter7B/EmpExec.java:17: エラー: chapter7AのEmployeeはpublicではありません。パッケージ外からはアクセスできません
Employee emp = new Employee(); //コンパイルエラーが発生する
^
chapter7B/EmpExec.java:17: エラー: chapter7AのEmployeeはpublicではありません。パッケージ外からはアクセスできません
Employee emp = new Employee(); //コンパイルエラーが発生する
^
エラー3個
上記、パッケージchapter7AのEmployeeクラスがデフォルトアクセスになっており、異なるパッケージのchapter7Bからはアクセスすることができない為、コンパイルエラーが発生します。
例題(publicアクセス修飾子(メソッドにpublic修飾子が付加されていない場合))
今度は、chapter7AのEmployeeクラスをpublicに修正し、disp()メソッドをデフォルトアクセスにして確認してみましょう。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7A |
| クラス名 | Employee |
package chapter7A; |
コンパイル例:> javac chapter7A¥Employee.java
> javac chapter7B¥EmpExec.java
chapter7B/EmpExec.java:20: エラー: Employeeのdisp()はpublicではありません。パッケージ外からはアクセスできません
emp.disp();
^
エラー1個
上記、パッケージchapter7AのEmployeeクラスのdisp()メソッドはデフォルトアクセスで、他のパッケージであるchapter7Bからはアクセスできない為、コンパイルエラーが発生します。
例題(publicアクセス修飾子(クラスおよびメソッドともにpublic修飾子が付加されている場合))
今度は、パッケージchapter7AのEmployeeクラスのdisp()メソッドを、public修飾子へ修正して確認してみましょう。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7A |
| クラス名 | Employee |
package chapter7A; |
コンパイル例:> javac chapter7A¥Employee.java
> javac chapter7B¥EmpExec.java
実行例:> java chapter7B.EmpExec
社員名:福山雅治
社員番号1000
privateアクセス修飾子
publicとは逆に、「見える(可視)」範囲を同じクラスの中だけに限定したいというときは、private修飾子を利用します。privateを付けると同じパッケージのクラスであっても見えなくなります。ただし、privateをclassに付けることはできません。classに付けることができるのはpublicだけです。

例題(privateアクセス修飾子1)
以下は、他クラスからprivateが付与している要素へアクセスした場合の例です。
新たにパッケージchapter7を作成し、EmployeeクラスとEmpExecクラスを作成し、実行結果を確認してみてください。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | Employee |
package chapter7; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | EmpExec |
package chapter7; |
コンパイル例:> javac chapter7A¥Employee.java
> javac chapter7B¥EmpExec.java
chapter7/EmpExec.java:20: エラー: empNameはEmployeeでprivateアクセスされます
emp.empName = "山田太郎"; //コンパイルエラーが発生
^
エラー1個
上記、Employeeクラスの構成要素であるメンバ変数empNameはprivateが付加されており、異なるクラスであるEmpExecクラスからはアクセスすることができない為、コンパイルエラーが発生します。
先ほど作成したEmployeeクラスとEmpExecクラスの以下の箇所を修正し、実行結果を確認してみてください。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | Employee |
package chapter7; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | EmpExec |
package chapter7; |
コンパイル例:> javac chapter7¥Employee.java
> javac chapter7¥EmpExec.java
実行例:> java chapter7.EmpExec
社員名:福山雅治
社員番号1000
アクセス修飾子の比較
アクセス修飾子をまとめると、以下です。
| アクセス修飾子 | アクセス修飾子による制限 |
|---|---|
| private | 同一クラス内に定義されたメソッドやコンストラクタからだけアクセスできる |
| デフォルドアクセス(修飾子なし) | 同一クラス内に定義されたメソッドやコンストラクタからアクセスできる他、他のクラスでもソースコードが同じパッケージ内にあれば、そのメソッドやコンストラクタからアクセスできる。 |
| public | 条件なし。自由にアクセスできる。 |
private修飾子を付けると自身のクラス内のメンバーだけがアクセスできるようになります。
またpublic修飾子を付けると外部の異なるパッケージのクラスからでもアクセスが可能になります。
カプセル化とデータ隠蔽
カプセル化とは
カプセル化とは、オブジェクト内に属性(メンバ変数)とその属性にアクセスする操作(メンバメソッド)を、1つのメソッドにまとめて定義するクラスの設計技法です。

カプセル化をおこなうことで、オブジェクトの独立性を確保することができます。
情報隠蔽とデータ隠蔽
カプセル化を実現するために、情報隠蔽とデータ隠蔽という2つの設計技法があります。
情報隠蔽とは、外部のオブジェクトに対して、公開するメンバと、非公開にするメンバを分けることをいいます。

データ隠蔽とは、オブジェクトの属性(メンバ変数)を隠蔽し、外部のオブジェクトに対しては、特定の操作手順のみを公開することをいいます。

具体的には、オブジェクトの属性(メンバ変数)をprivate修飾子を付与し、他のオブジェクトから直接アクセスできないようにします。
その代わり、メンバ変数の値を参照できたり、メンバ変数の値を設定するための専用のメソッドをpublic修飾子を付与し、他のオブジェクトからメソッドを通してメンバ変数へアクセスできるようにします。この専用のメソッドのことを、アクセサメソッドといいます。
アクセサメソッドには、値を取得するためのメソッド(ゲッター)と、値を設定するためのメソッド(セッター)があります。
カプセル化の定義方法
以下、カプセル化の定義です。

例題
先ほど作成した、EmployeeクラスとEmpExecクラスの以下の箇所を修正し、実行結果を確認してみてください。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | Employee |
package chapter7; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | EmpExec |
package chapter7; |
コンパイル例:> javac chapter7¥Employee.java
> javac chapter7¥EmpExec.java
実行例:> java chapter7.EmpExec
社員名:福山雅治
社員番号1000
empName:自身の名前
empNo:2000
上記、Employyeクラスをカプセル化しています。そして、アクセサメソッドを利用し、メンバ変数に値を設定や取得をおこなっています。カプセル化することで、メンバ変数の値を直接設定することを禁止し、代わりに、アクセサメソッドを利用して間接的にメンバ変数へアクセスすることが可能になります。
mainメソッドの位置づけ

メソッドにstatic修飾子が付与されるとクラスメソッドと呼ばれます。mainメソッドはstatic修飾子が付加されたクラスメソッドです。
クラスメソッドはプログラム実行開始直前にインスタンス化され、プログラムが終了するまで、そのまま存在し続けています。
常に存在しているので、いつでも実行できる状態にあります。これがstatic(静的)と呼ばれる由来です。
Java言語では、最初にmain()メソッドが呼ばれる仕組みになっています。main()メソッドが、staticが付加されたメソッド(クラスメソッド)でなければならないのは、実行開始直前に準備されている必要があるからです。
一方、static修飾子の付加された変数やメソッドは、new演算子によって実行開始後にインスタンス化されます。
これに対して、static修飾子の付加されたmainメソッドは、クラスの中ではstaticメンバという位置付けです。
プログラムの実行開始直前に、一度だけインスタンス化され、プログラム終了まで存在し続けます。
Javaファイルの規則
1つのファイルに1つのクラスを定義するのが基本ですが、現実には状況に合わせてオプションがあります。ここでは知っておかなければならないJava言語のオプションについて学習していきましょう。
クラス名とファイル名の規則

Java言語の規約では、ソースプログラムを書いたファイルの拡張子は「.java」とすると決まっています。また、クラス名とファイル名は、原則同じでなければなりません。クラス名が「Car」で定義した場合、それを保存するファイル名は「Car.java」でなければなりません。
クラスファイルの規則
エディタで書かれたプログラムはただの文字列です。エディタでJava言語で書いたプログラムはソースプログラムといいます。第1章で学習しましたとおり、動かす為にはソースプログラムをコンパイラによって、実行可能ファイル(Javaバイトコード)
に変換する必要があります。今までも以下のコマンドを実行し、コンパイルをおこなってきました。

コンパイラによって、コンパイルすると実行可能ファイル(Javaバイトコード)である.classファイルが生成されます。
この一連の作業のことを、一般的には「ビルド(build)する」といいます。
javaファイルの規則
一つのクラスを一つのソースファイル(.javaファイル)に書くのが原則ですが、一つのソースファイル(.javaファイル)にいくつものクラスを書くことができます。ただし、説明や学習時のために利用されるだけであって、一般的には推奨されていません。

ソースファイル(.javaファイル)をコンパイルすると、定義されているクラスごとに実行可能ファイル(.classファイル)が生成されます。
1つのファイルに複数のクラスを定義した場合には、ファイル名は以下のような制約があります。
public修飾子を付加したクラスがあれば、ソースファイル名はそのクラスと同じ名前にしなければならない。public修飾子を付加したクラスが1つもない場合には、ソースファイル名は何をつけても良い。
例題(複数のクラスを含むJavaファイル)
以下、一つのソースファイル(.javaファイル)に複数のクラスを定義した場合の例です。
AクラスとBクラスとCクラスを一つのファイルへ定義し、実行結果を確認してみてください。
| 項目 | 名前 | 備考 | |
|---|---|---|---|
| プロジェクト | alj_study | ALJEP研修用 | |
| パッケージ | chapter7 | 第7章 | |
| クラス名 | A | Aクラス | public |
| クラス名 | B | Bクラス | デフォルトアクセス |
| クラス名 | C | Cクラス | デフォルトアクセス |
| ソースファイル名 | A.java |
package chapter7; |
コンパイル例:> javac chapter7¥A.java
A.javaのソースファイルをコンパイルすると、A.class、B.class、C.classが生成されます。
実行例:> java chapter7.A
Aクラスです。
> java chapter7.B
Bクラスです。
> java chapter7.C
Cクラスです。
今回は全てのクラスでmain()メソッドを定義している為、Javaコマンドで実行することができます。
尚、通常は1つのファイルに1つのクラスを定義することが一般的です。
特に理由がない限り、1つのファイルに1つのクラスを定義するようにしましょう。
import文
第1章で学習しましたとおり、Javaプログラミングでは、クラスはパッケージに分けて作成します。異なるパッケージの機能を利用する場合、import作業が必要です。ここではimportについて解説します。
パッケージ管理
1つのパッケージには関係のあるクラスを集めて、パッケージ全体で意味のある機能を実現するようにします。この時、パッケージの中のクラスは、互いに違う名前でなければなりません。同じ名前のクラスは作れないルールになっています。パッケージが違えば、同じ名前のクラス名をつけることができます。

パッケージの命名規則

パッケージ名は、名前が衝突するのを避けなければなりません(ユニークな名前でなければならない)。
その為実務では、所属する企業のインターネットドメイン名を逆順にしたものを推奨しています。
尚、Java言語のクラスの正しい名前は、パッケージ名を含めた名前です。これを、完全修飾名といいます。
完全修飾名での呼び出し
完全修飾名(パッケージ名.クラス名)という形で、クラスを利用してみましょう。
今回は、java.utilパッケージにあるArraysクラスを完全修飾名
※Arraysクラスは JavaAPIで提供されているクラスです。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | ArrayExec1 |
package chapter7; |
しかしながら上記のように書くと、記述が長くなってとっても面倒です。
そこでJavaでは通常、他のパッケージのクラスを利用したい時はimport文を使います。
import文での呼び出し
import文の構文は以下です。
import パッケージ名.使用したいクラス名; |
先ほど、作成したArrayExec1クラスを以下のように修正してみましょう。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | ArrayExec1 |
package chapter7; |
コンパイル例:> javac chapter7¥ArrayExec1.java
実行例:> java chapter7.ArrayExec1
[100, 200, 300]
上記の様にプログラムの先頭で一度だけ、import文を使って完全修飾名でクラス名を登録しておけば、プログラムの中ではクラス名だけで指定できる様になります。
(import java.util.Arrays;がimport文です。)
import文でのアスタリスクの使用
パッケージ文でクラス名を指定する箇所をアスタリスク(*)で指定すると、そのパッケージ内のすべてのクラスが利用できます。
構文は以下です。import パッケージ名.*;
import static文
これまで、クラスメソッド(staticのメソッド)を利用する場合には以下の様に書いていました。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | ArrayExec1 |
package chapter7; |
コンパイル例:> javac chapter7¥ArrayExec1.java
実行例:> java chapter7.ArrayExec1
[100, 200, 300]
上記の場合、Arraysクラスのメソッドを使う時は、Arraysというクラス名を必ずつけていましたが、import static文を使うと、Arraysというクラス名を付けなくても、Arraysクラスで定義されているメソッド()が利用できます。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | ArrayExec1 |
package chapter7; |
コンパイル例:> javac chapter7¥ArrayExec1.java
実行例:> java chapter7.ArrayExec1
[100, 200, 300]
なお、import static文でメソッド名を指定する箇所をアスタリスク(*)で指定すると、そのパッケージ内のクラスの全てのstaticメソッドが利用できます。
import static パッケージ名.クラス名.*; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter7 |
| クラス名 | ArrayExec1 |
package chapter7; |
コンパイル例:> javac chapter7¥ArrayExec1.java
実行例:> java chapter7.ArrayExec1
[100, 200, 300]
まとめ
以下の要点を理解できたら次の章へ進んでください。
アクセス修飾子
- クラス、メンバ変数、コンストラクタ、メソッドには、アクセス条件を設定することができる
- アクセス条件を指定する場合には、アクセス修飾子を利用する。
デフォルドアクセス修飾子
- アクセス修飾子を付与しない場合、デフォルトアクセスが設定されている。
- デフォルトアクセスは、同じパッケージ内ではどのクラスも互いに「見える」状態である
(同じパッケージ内からアクセスできる状態である) - 異なるパッケージから利用可能にする場合は、classにpublic修飾子を付与する必要がある
public修飾子
- publicアクセス修飾子の場合、パッケージを超えても「見える」状態である
(同じパッケージ内+他のパッケージからアクセスできる状態である) - publicアクセス修飾子はクラス、メンバ変数、コンストラクタ、メソッドに付加できる
- クラスの構成要素(メンバ変数、コンストラクタ、メソッド)がpublicでも、クラス自身にpublicが付与されていないと、外部からのパッケージからは利用できないので注意が必要
private修飾子
- privateアクセス修飾子は、「見える」範囲が同じクラス内だけである
(同じクラス内の構成要素同士のみアクセスが可能) - privateアクセス修飾子は、メンバ変数、メンバメソッドに付加することができる
- クラスにprivateは付加することはできない
カプセル化
- カプセル化とは、オブジェクト内に属性(メンバ変数)とその属性にアクセスする操作(メンバメソッド)を、1つのメソッドにまとめて定義するクラスの設計技法のこと
- カプセル化を行うことで、オブジェクトの独立性を確保することができます
- 情報隠蔽とは、外部のオブジェクトに対して、公開するメンバと、非公開にするメンバを分けること
- データ隠蔽とは、オブジェクトの内部構造を隠蔽し、外部に対しては特定の操作手順のみを公開すること
- 属性(メンバ変数)へprivate修飾子を付与し、外部クラスからアクセスできないようにする
- アクセサメソッド(setterメソッド、getterメソッド)を定義する
mainメソッドの位置づけ
- static修飾子の付加されているメンバはプログラムの実行開始直前に、一度だけインスタンス化され、プログラム終了まで存在し続ける
- main()メソッドは、static修飾子が付与されているクラスメソッドである
- Java言語では、最初にmain()メソッドが呼ばれる仕組みになっている
Javaファイルの規則
- Java言語の規約では、ソースプログラムを書いたファイルの拡張子は「.java」とする
- クラス名とファイル名は、原則同じにする
- コンパイラ(javac)によって、コンパイルすると.classファイルが生成される
- 一連の作業のことを、ビルド(build)するといいます。
- ソースファイル名はpublic修飾子を付加したクラスと同じ名前にする
- public修飾子を付加したクラスが1つもない場合には、ソースファイル名は何をつけても良い
- コンパイルすると、ソースファイルに定義したクラスごとに.classファイルが生成される
import文
- パッケージには関係のあるクラスを集めて、パッケージ全体で意味のある機能を実現する
- 同じパッケージ内に、同じ名前のクラス名をつけることができない
- パッケージが異なれば、同じ名前のクラス名をつけることができる
- 実務では、所属する企業のインターネットドメイン名を逆順にしたものを推奨している
- 名前が衝突するのを避けなければならない(ユニークな名前でなければならない)
- Java言語のクラスの正しい名前はパッケージ名を含めた名前である(完全修飾名)
- 完全修飾名でメンバを呼び出す場合、「パッケージ名.クラス名 」で定義する
- 完全修飾名で指定した場合、import文は不要
- import文はpackage文の直後に書く
- import文で、パッケージ内の全てのクラスをimportする時はクラス名にアスタリスク( * )を指定する
- パッケージ名はドットで区切った名前で指定することもできる
- Eclipseの自動補完機能を利用すると自動でimport文を挿入できる
- import static文を定義すると、メンバ名のみで呼び出すことが可能
- import static文で、パッケージ内のクラスの全てをimportする時はメソッド名にアスタリスク( * )を指定する
- Eclipseの自動補完機能を利用すると自動でimport文を挿入できる