🐣

Javaのクラスのアクセス制御と複数クラスの宣言

2023/01/06に公開1

Javaを基礎から復習していて、クラスについて理解が曖昧だった部分があったのでまとめておきます!
注意して書いているつもりですが、誤りがあればご指摘いただければと思います🙇‍♂️

クラスに対するアクセス制御レベル

クラスに対するアクセス制御のレベルとしては2つのみです。(⚠️メンバに対しては4つある)
以下にまとめます。

名前 指定方法 アクセス許可の範囲
package private 何も書かない 自分と同じパッケージに属するクラス
public public どこからでも

なので、クラスを宣言するときは、publicをつけるか何もつけないかの2択になります。
クラスだけでなく、列挙型であるenumを宣言するときも同じです。
private class Hoge とかやってjavacすると、

修飾子privateをここで使用することはできません

って怒られます。

1つのファイルに複数のクラスを宣言する

1つのファイルに複数のクラスを宣言するとき、大きく分けて2つ方法があります。

  • 入れ子構造にせずに宣言する
  • 入れ子構造にして宣言する

まず入れ子構造にせずに宣言する方から。

入れ子構造にせずに宣言する

Javaのルールとして、

  • 1つのファイルに1つのpublicクラス
  • ファイル名 = publicクラス名

があります。
なので、これを守っていれば1つのファイルに複数のクラスを宣言することができます。

いくつか例を見ます。


以下のような、public classが1つ、package private class が複数あるHoge.javaはOKです。

Hoge.java
public class Hoge {} // public class

class Fuga {} // package private class 

class Piyo {} // package private class


以下のようなpublic class が1つのファイルに複数あるファイルはNGです。

クラス Fugaはpublicであり、ファイルFuga.javaで宣言する必要があります

とエラーが出ます。
publicなenumとpublicなclassを1つのファイルに同居させるのもNGです。

public class Hoge {} // public class

public class Fuga {} // ⚠️public class2つめ!

class Piyo {} // package private class


以下のようなpublic classが1つもなく、package private class が複数あるファイルは…OKです!
しかも、ファイル名は自由に決められます!Hoge.javaでもFuga.javaでもYakiniku.javaでもOKです!
ただこのケースはあまり一般的ではないと思います!!

class Hoge {} // package private class

class Fuga {} // package private class

class Piyo {} // package private class

入れ子構造にして宣言する

入れ子構造にして複数クラスを宣言する方法は3つあります。またクラスの内部に宣言されたクラスのことをインナークラスと呼びます。
なので、インナークラスの種類が3つとも言えます。

  • メンバクラス(staticあり、staticなし)
  • ローカルクラス
  • 匿名クラス

インナークラスはあまり登場頻度が高くないらしいので特徴をちょろっと箇条書きしておくにとどめておきます。

メンバクラスの特徴

  • クラスブロックの内部で宣言される
  • staticありで宣言した場合
    • 外部クラスのstaticなメンバにのみアクセスできる
    • 利用するときは、 Outer.Inner oi = new Outer.Inner();
  • staticなしで宣言した場合
    • 外部クラスのstaticでないメンバにもアクセスできる
    • 外部クラスのインスタンスを生成してからでないと利用できない
    • 利用するときは Outer o = new Outer; Outer.Inner i = o.new Inner();

ローカルクラスの特徴

  • クラスの中のメソッドの中で宣言される(そのメソッド内でのみ利用可能)
  • 利用するときは(宣言されたメソッド内で)Inner i = new Inner();

匿名クラスの特徴

  • 文の中で(式の一部として)宣言(と利用)される
  • 利用するときはObject o = new Object() { ... }

終わり

以上です。
何か誤りがあれば教えていただけると嬉しいです🙇‍♂️

Discussion

yukimaruyukimaru

入れ子構造であればprivateできます!
LinkedListのNodeクラスが良い例かもですね

public class LinkedList {
    // Nodeクラスをprivateなインナークラスとして定義
    private class Node {
        int data;
        Node next;