プログラムを実装する際、曖昧に設定しがちなアクセス修飾子ですがみなさんは適切に定義出来ているでしょうか?
本記事ではアクセス修飾子の中でも特に曖昧となりがちな「protected」の使い方についてご紹介していきます。
目次
Javaのアクセス修飾子protectedとは

Javaにはクラスやフィールド、メソッドを定義する際に記述するアクセス修飾子という概念があります。
本記事のテーマである「protected」はアクセス修飾子の1つですが、まず基本的な考え方についてご紹介します。
アクセス修飾子についてまずは理解しよう!
Javaにはアクセス修飾子という考え方があり、クラスや定義されたフィールド・メソッドがアクセス可能な範囲を定義することが出来るものです。
「public」「private」「protected」「定義しない(デフォルト)」の4種類から記述することが可能です。
アクセス修飾子「protected」の役割は?
Javaのアクセス修飾子「protected」の説明として用いられるのは「同一パッケージまたはサブクラスからは参照可能」との表現です。
具体的には同一パッケージ内の「自クラス」「サブクラス」「他クラス」と他パッケージの「サブクラス」から参照が可能ということです。
Javaのサンプルコードでprotectedの使い方を確認しよう

ここからはサンプルコードを掲載しながら実際にJavaのプログラムでprotectedがどのように使用されるのか確認していきたいと思います。
同一パッケージの自クラスから参照する場合
下記のコードは同一パッケージ内の自クラスから各アクセス修飾子で定義したフィールドの値を出力するサンプルです。
import java.util.*;
public class Main {
public static String publicStr = "publicのフィールドです。";
private static String privateStr = "privateのフィールドです。";
protected static String protectedStr = "protectedのフィールドです。";
static String defaultStr = "defaultのフィールドです。";
public static void main(String[] args) throws Exception {
System.out.println(publicStr);
System.out.println(privateStr);
System.out.println(protectedStr);
System.out.println(defaultStr);
}
}
サンプルコードを実行した結果は下記の通りとなります。
publicのフィールドです。 privateのフィールドです。 protectedのフィールドです。 defaultのフィールドです。
同一パッケージ内の同一クラスからは問題なく「protected」の値を呼び出すことが可能であることをご確認いただけます。
同一パッケージ内のサブクラスから参照する場合
次にサブクラスからそれぞれのアクセス修飾子のフィールドを参照した場合のサンプルコードです。
import java.util.*;
public class Main extends SubClass {
public static void main(String[] args) throws Exception {
SubClass subClass = new SubClass();
System.out.println(subClass.publicStr);
// System.out.println(subClass.privateStr); サブクラスのprivateフィールドは参照不可
System.out.println(subClass.protectedStr);
System.out.println(subClass.defaultStr);
}
}
class SubClass {
public static String publicStr = "publicのフィールドです。";
private static String privateStr = "privateのフィールドです。";
protected static String protectedStr = "protectedのフィールドです。";
static String defaultStr = "defaultのフィールドです。";
}
サンプルコードを実行した結果は下記の通りとなります。
privateで定義したフィールドに関してはエラーとなるためコメントアウトしています。
publicのフィールドです。 protectedのフィールドです。 defaultのフィールドです。
異なるパッケージのサブクラスから参照する場合
別パッケージのサブクラスから参照する場合のサンプルは下記の通りとなります。
「同一パッケージのサブクラスから参照する場合」でのサンプルコードをファイル分割したものとなります。
「Main.java」でファイルを作成しています。
package sample;
import java.util.*;
import test.SubClass;
public class Main extends SubClass {
public static void main(String[] args) throws Exception {
SubClass subClass = new SubClass();
System.out.println(subClass.publicStr);
// System.out.println(subClass.privateStr); サブクラスのprivateフィールドは参照不可
System.out.println(subClass.protectedStr);
// System.out.println(subClass.defaultStr); サブクラスのデフォルトフィールドは参照不可
}
}
「SubClass.java」でファイルを作成しています。
package test;
public class SubClass {
public static String publicStr = "publicのフィールドです。";
private static String privateStr = "privateのフィールドです。";
protected static String protectedStr = "protectedのフィールドです。";
static String defaultStr = "defaultのフィールドです。";
}
サンプルコードを実行した結果は下記の通りとなります。
publicのフィールドです。 protectedのフィールドです。
別パッケージに作成した「SubClass」ですが、「Main.java」で継承しているため「protected」のフィールドの値が出力されることを確認出来ます。
異なるパッケージの他クラスから参照しようとした場合
では継承を使用せずに別パッケージの他クラスから参照しようとした場合はどうなるのでしょうか?
答えはコンパイルエラーとなり、実行する事が出来ません。
下記のサンプルコードで確認してみてください。
「Main.java」でファイルを作成しています。
package sample;
import java.util.*;
import test.SubClass;
public class Main {
public static void main(String[] args) throws Exception {
SubClass subClass = new SubClass();
System.out.println(subClass.publicStr);
// System.out.println(subClass.privateStr); サブクラスのprivateフィールドは参照不可
System.out.println(subClass.protectedStr);
// System.out.println(subClass.defaultStr); サブクラスのデフォルトフィールドは参照不可
}
}
「SubClass.java」でファイルを作成しています。
package test;
public class SubClass {
public static String publicStr = "publicのフィールドです。";
private static String privateStr = "privateのフィールドです。";
protected static String protectedStr = "protectedのフィールドです。";
static String defaultStr = "defaultのフィールドです。";
}
サンプルコードをコンパイルしようとすると下記のようなエラーが表示されます。
sample/Main.java:15: エラー: protectedStrはSubClassでprotectedアクセスされます
System.out.println(subClass.protectedStr);
上記のコンパイルエラーは、アクセス修飾子「protected」が許可している範囲外(他パッケージのサブクラス以外)からアクセスしようとしているため、コンパイルエラーとなっています。
さいごに:Javaのアクセス修飾子protectedを理解してオブジェクト指向をより深く理解しよう!
本記事では、Javaのアクセス修飾子「protected」の使い方についてご紹介してきました。
オブジェクト指向をうまく活用してプログラムを組んでいくためにはアクセス修飾子「protected」の理解は欠かせません。
ぜひ、実用的で可読性の高いプログラムを実装するために、アクセス修飾子「protected」を理解し、Javaのオブジェクト指向をより深く理解してみてください。
他パッケージに定義されたサブクラス以外のクラスからは参照することが出来ません。