見出し画像

Java SE11 Silver試験対策のアウトプット                 ~パッケージ、クラス、フィールド、メソッドの概要~


Java SE11 Silverの試験対策としてWebで学んだ内容と、「黒本」と言われている参考書を使って勉強したので、アウトプットとして学んだ内容をまとめていきたいと思います。

パッケージの3つの役割について


①名前空間(ネームスペース)を提供して、名前の衝突を防ぐ
システム開発は多種多様な部品を組み合わせて行われます。

その際は自身の作った部品だけでなく、以前に製作されたシステムの一部をコピーして使用したり、オープンソースから引っ張ってくることもある。
また、自身で作った部品であっても数が多くなると管理が困難になって同じ名前を使用してしまうケースがある。

ここで問題が発生する。例えば同じ名前のクラスやメソッドが複数あった場合にコンパイラであったりJVM(Java仮想マシン)はどれを使用すれば良いか分からなくなってしまい、コンパイルエラーが起きたり設計者の意図しない場所でクラスが使われてしまう。
そのため、コンパイラやJVMはクラス名をクラス名の場合『パッケージ名.クラス名』のように完全修飾クラス名で扱います。

また、パッケージ名は名前の衝突を防ぐ役割をもっていますが、パッケージ名自身は重複することができてしまうため、パッケージ名を一意なものにするため、慣習でドメイン名を逆にしたものが使われるようです。
例)xxx.co.jpであればパッケージ名はjp.co.xxxとする
ただ、これはあくまで慣習なので個人開発等であればパッケージ名は自由につけても特に問題ない。

Javaの場合パッケージ名とクラス名のどちらも被ってしまう事態が発生した場合はコンパイルエラーとなるが、名前空間を制御するパッケージはソースファイルのdirectory構造を表現する機能を兼ねているため、(OSの都合上、同一名を持つファイルを同一のフォルダには作成できないことから)起こりえないと考えてしまいがちであるが、jar化されたソースコードをlibraryとして使用したときには(同じdirectory構造をjar内部で持つことは可能なので)起こる可能性もある。

80~90年代にソフトウェアのオープンソース化の流れがあり、その際にいろいろなソフトウェア部品の名前が衝突してエラーが起きる事態が多発していたため、Javaの設計時にこのような仕掛けが考案された。

~おまけ~
C言語にはこの名前空間を管理する機能が提供されていないため、大企業の大きなシステムであってもその中でたった1つの同一の名前を持つ関数や
構造体でも存在したらcompile時エラーになってしまいます。
そのため必ず名前が一意となるように命名規則や管理台帳を作って対処する、ということをやっており、そのために関数や構造体の名前は物凄く長いものになってしまうことがあるそうです。

②アクセス修飾子と組み合わせてアクセス制御機能を提供する
クラスを複数のパッケージに分けることで、パッケージ単位でアクセス制御ができるようになります。
例えば、次のようにjp.co.xxxパッケージに属する2つのクラスがある場合、publicなSampleクラス(上の段)はほかのパッケージに属するクラスからも使えますが、publicではないTestクラス(下の段)は使うことができません。

package jp.co.xxx;
public class Sample {
    // any code
}
package jp.co.xxx;
class Test {
    // any code
}

★アクセス修飾子4種類を強制力のゆるい順番に紹介します
①public:外部のどのクラスからでも参照可能。
何でもかんでもpublicにしてしまうと、パッケージの中のクラスがどこまで影響するのか、影響範囲が分からなくなってしまうので注意すること。

②protected:同一packageの他クラスのほか、子クラス(継承関係で繋がってるいわゆる子孫のクラス)からも参照可能。

③無指定:同一packageの他クラスからも参照可能。※「package-private」という呼び方をされる。

④private:他クラスから参照不可能。
    
※特殊な例:同じファイルに複数のクラスを定義した場合は、private以外は、同じファイルに定義した他クラスからでも参照可能。

また、クラスに付けられるアクセス修飾子は、public、無指定、の2種類のみ。

③クラスの分類を可能にする
②のようにパッケージを使ったアクセス制御をすることで、パッケージ内のクラスを「公開するクラス」と「非公開(または一部公開)するクラス」に分類できます。

公開・非公開を使い分けることで、設計者の意図に反する形で不用意にクラスが使われる事態を防ぐことができます。

なお、あらゆるクラスは必ず何らかのパッケージに属しており、パッケージ宣言を省略した場合は無名パッケージ(デフォルトパッケージ)に所属するものと見なされます。

★パッケージ宣言について
今はIDEを使ってコードを書いている人が大半だとは思いますので、自動的に問題のない形でパッケージ宣言がされているとは思いますが、最後にパッケージ宣言のルールについても説明します。

// パッケージ宣言はコードの一番上に記述しなければなりません。
// ただし、コメント行だけは例外として認められています。
package sample;
public class Test {
    // any code
}


クラスについて

ここまで、何の気なしにクラスという言葉を使ってきてしまいましたが、クラスとはモノの概要を「属性(field)」と「操作(method)」という2つの観点で表した構造物である。

また、Javaでは主にオブジェクトはクラスとインスタンスのことを指し、クラスはコピー元、インスタンスはコピー先のイメージを持っていると分かりやすいと思います。

クラスの具体的な定義方法
まずは1行目でパッケージ宣言を行い、ライブラリを使用する場合はインポートする。
そのうえで

[アクセス修飾子] [その他の修飾子] class [class名]

のように記述する。

・クラス名の命名規則は慣習で大文字始まりのCamelCaseです。
これに関しては、慣習とはいえ外しているケースを見かけたことがないのでしっかり覚えましょう。


フィールドについて

・クラスの属性で、例えばHumanクラスを定義したら名前(name)や年齢(age)などいろいろな属性を持たせることができる。
直後の中括弧の間に定義する。
・具体的な書き方は

[アクセス修飾子] [その他の修飾子] [型] [フィールド名];



メソッドについて

メソッドとはクラスが実行可能な「操作」のことで、具体的な書き方は原則以下の通りです。

[アクセス修飾子] [各種修飾子] [戻り値の型] [method名]([引数列]) {
    [methodの実装]
}


ただ、特殊なmethodの場合は一部不要になったり、各内容が指示されることもあります。

また、メソッド名は動詞にする慣習がありますが、これはメソッドが「操作」を表すものであることを考えれば割と自然に受け入れられると思います。

他にも、booleanを返すメソッドの名前はis~やhas~のような形であるべき
という慣習もありますが、これはif文とつなげた場合にif ~isUnder20~のよ
うに、英文として自然に読めるからと考えられます。

ここから先は3種類のメソッドについて説明をしていきます。

①コンストラクタ
クラスをインスタンス化するための特殊なメソッド。
コンストラクタを書かなかった場合は自動的に引数なしのコンストラクタ(デフォルトコンストラクタ)が生成される。
そのため、デフォルトコンストラクタ意外にコンストラクタがいらないなら、コンストラクタは書く必要がない。
具体的な書き方は以下のとおり
 

[アクセス修飾子] コンストラクタ名 {
    [コンストラクタの実装]
}

★コンストラクタの命名はクラスメイト同じ名前でなければなりません。
また、アクセス修飾子以外の修飾子と戻り値を書かない。
コンストラクタの場合、戻り値は必ずインスタンスの参照値となるため余計な記述をすると通常のメソッド扱いになります。

②mainメソッド
クラスには複数のメソッドを定義できます。このとき、どのメソッドから処理を始めるのかが決まっていなくてはいけません。処理を始めるためのメソッドのことを、一般的にエントリーポイントと呼びます。

Javaでは、エントリーポイントとなるメソッド(mainメソッド)の定義が次のように決められています。

public static void main(String[] args) {
    // any code
}

決められてはいるのですが、「args」の部分だけは単なる引数(変数)の宣言なので変更が可能となっています。

mainメソッドの記述ルールをまとめると
・公開されていること(publicであること)

・インスタンスを生成しなくても実行できること(staticであること)

・戻り値は戻せない(voidであること)

・メソッド名はmainであること

・引数はString配列型を1つ受けとること。

『publicでstaticでvoid、引数はString配列1つ』といったところでしょうか。

また、あまり使わないとは思いますが一ひねり入れて以下のような記述も可能です。

public static void main(String... args) {

}

これに関しては、可変長の引数はコンパイル時に配列型の引数に変換されるため、結果としてString配列型となるためです。

③普通のメソッド
コンストラクタやmainメソッド以外は通常のメソッドで、staticを付ければインスタンスを生成していなくても呼び出しが可能なstaticメソッド、staticが無ければインスタンスを生成しないと呼び出されないインスタンスメソッドとなります。


まとめ

クラス、フィールド、メソッドのまとめとして、以下のコードを残します。

class Person {
    
    // Personクラスの固有のフィールド(staticフィールド)を定義する
    public static String shuzoku = "人間";

    // 以下はインスタンスフィールド(各インスタンスに持たせる情報)
    /** 姓 */
    public String sei;
    /** 名 */
    public String mei;
    /** 歳 */
    public int age;

    // 「Person - コンストラクター」を選択して、下記のコンストラクタを作成すること。
    public Person() {
        // 何もしない
    }

    
     // 姓、名、歳を引数で設定してinstance化するためのコンストラクタ
    public Person(String sei, String mei, int age) {
        this.sei = sei;
        this.mei = mei;
        this.age = age;
    }

    // 自己紹介をするメソッド
    // 種族の部分はPersonクラス固有のshuzoku=人間 で固定されている。
    public void doJikoshoukai() {
        String jikoshoukai = "私の名前は" + sei + " " + mei + "、" + age + "歳の" + shuzoku + "です。";
        System.out.println(jikoshoukai);
    }
}

エンジニアファーストの会社
株式会社CRE-CO niwatori-program

この記事が気に入ったらサポートをしてみませんか?