3
1

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

【Java】クラスの定義場所によって指定できるアクセス修飾子が違うって知らなかった

Last updated at Posted at 2023-07-03

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

この記事を読んでわかること

  • Javaのアクセス修飾子の種類
  • クラスに対するアクセス制御(トップレベルクラス、インナークラス)
  • 1つのファイルに対して複数のクラスを宣言する方法とその特徴

Javaのアクセス修飾子

以下の4つがあります。

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

メンバにはこの4つのアクセス修飾子を指定することができます。
(メンバは、クラスを構成する変数やメソッドなどのこと)

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

トップレベルクラスとは、ネストされていない一番外側のクラスのことです。反対はインナークラスになります。
トップレベルクラスに対するアクセス制御のレベルとしてはpublicかprotected2つのみです。
なので、クラスを宣言するときは、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です。javacすると、Hoge.class, Fuga.class, Piyo.classができます。

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つとも言えます。
また、使用できるアクセス修飾子に関して、冒頭に説明したトップレベルクラスと違うので注意が必要です。これについてもそれぞれのインナークラスの特徴のところで説明をします。
インナークラスは以下の3つです。

  • メンバクラス(非static)
  • ローカルクラス
  • 匿名クラス

メンバクラスの特徴

  • クラスブロックの内部で宣言される
  • 非static
    • 外部クラスのstaticでないメンバにもアクセスできる
    • 外部クラスのインスタンスを生成してからでないと利用できない
    • 利用するときは Outer o = new Outer; Outer.Inner i = o.new Inner();
  • static
    • 外部クラスのstaticなメンバにのみアクセスできる
    • 利用するときは、 Outer.Inner oi = new Outer.Inner();
    • staticなメンバクラスは、インナークラスに含まれません(参考)。しかし、「入れ子構造にして宣言するクラス」の一種ではあるため、紹介することにしました
  • アクセス修飾子について
    • 4つ全てを使うことができる
    • 「メンバクラス」という名前の通り、メンバ変数やメンバメソッドと同じような扱いであるため

ローカルクラスの特徴

  • クラスの中のメソッドの中で宣言される(そのメソッド内でのみ利用可能)
  • 利用するときは(宣言されたメソッド内で)Inner i = new Inner();
  • アクセス修飾子
    • 何もつけない
    • その「メソッド」内でのみ使われるクラスなので、どのクラスからとかどのパッケージからとかを指定する必要はないため
    • 一般に、アクセス修飾子を何もつけない=package privateとなるが、ローカルクラスにのみ限定していうと、そういう意味ではない。ローカルクラスの寿命は定義されたメソッド内のみであるため、package privateという概念は適用されない
    • ちなみに、ローカルクラスに何らかのアクセス修飾子をつけてjavacすると エラー: 式の開始が不正ですと怒られる

匿名クラスの特徴

  • 文の中で(式の一部として)宣言(と利用)される
  • 利用するときはObject o = new Object() { ... }
  • アクセス修飾子
    • そもそもクラスの宣言をしないので、何も指定しない

参考

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1