やあ!今日のレッスンでは、アクセス修飾子の概念を理解し、それらを使用する方法の例を検討します。もちろん、「よく知る」という言い方は完全に正しくありません。あなたは前のレッスンでそれらのほとんどをすでによく知っています。念のため、最も重要な点を思い出してみましょう。修飾子アクセスは、ほとんどの場合、コードのさまざまな部分へのアクセスを制御するキーワードです。なぜ「最も頻繁に」なのか? そのうちの 1 つはキーワードを使用せずにデフォルトで設定されているため :) Java には 4 つのアクセス修飾子があります。最も制限的なものから最も「寛容」なものまでの順にリストします。
privateは最も制限的なアクセス修飾子です。データとメソッドの可視性を単一クラス内に制限します。この修飾子は、ゲッターとセッターに関するレッスンで知っています。この例を覚えていますか?
アクセス修飾子でマークされたフィールドとメソッドが表示されます。
インターフェイスについてのレッスンを学習したので、その目的は明らかです :) 結局のところ、public修飾子はユーザーに何かを与えるために作成されました。たとえば、プログラムのインターフェイスです。ロシア語のテキストを英語に翻訳できる翻訳プログラムを作成したとします。必要なロジックをすべて実装するtranslate(String textInRussian)メソッドを作成しました。このメソッドにpublicという単語を付けたので、これがインターフェースの一部になりました。
- プライベート;
- デフォルト (パッケージが表示される);
- 保護されています。
- 公共。
プライベート修飾子

public class Cat {
public String name;
public int age;
public int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
}
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";
cat.age = -1000;
cat.weight = 0;
}
}
前回のレッスンで検討しました。私たちはここで重大な間違いを犯しました。私たちはデータを公開しているため、他のプログラマーがフィールドに直接アクセスしてその値を変更することができました。さらに…これらの値は何のチェックも行われずに割り当てられました。これは、プログラムが年齢 -1000 歳、体重 0 の「」という名前の猫を作成できることを意味します。この問題を解決するために、ゲッターとセッターを使用し、さらにプライベート修飾子を使用してデータへのアクセスを制限しました。
public class Cat {
private String name;
private int age;
private int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
public String getName() {
return name;
}
public void setName(String name) {
// input parameter check
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
// input parameter check
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
// input parameter check
this.weight = weight;
}
}
基本的に、フィールドへのアクセスを制限し、ゲッターとセッターを実装することは、プライベートな 方法の最も一般的な例です。実際の仕事でも使われるでしょう。言い換えれば、この修飾子の主な目的は、プログラム内でカプセル化を実現することです。ちなみに、これはフィールドだけに当てはまるわけではありません。プログラムに非常に複雑な機能を実装するメソッドがあると想像してください。例として何を提案できますか? readDataFromCollider() メソッドがデータ アドレスを入力として受け取り、バイト形式でラージ ハドロン衝突型加速器からデータを読み取り、このデータをテキストに変換し、ファイルに書き込んで印刷するとします。コードは言うまでもなく、メソッドの説明ですら怖く見えます:) コードを読みやすくするには、メソッドの複雑なロジックをすべて 1 か所に書かないほうがよいでしょう。代わりに、機能を個別のメソッドに分割する必要があります。たとえば、readByteData()メソッドはデータの読み取りを担当し、convertBytesToSymbols()メソッドはコライダーから読み取ったデータをテキストに変換し、saveToFile()メソッドは受信したテキストをファイルに保存し、printColliderData()メソッドはデータ ファイルを出力します。最終的に、readDataFromCollider()メソッドははるかに単純になります。
public class ColliderUtil {
public void readDataFromCollider(Path pathToData) {
byte[] colliderData = readByteData(pathToData);
String[] textData = convertBytesToSymbols(colliderData);
File fileWithData = saveToFile(textData);
printColliderData(fileWithData);
}
public byte[] readByteData(Path pathToData) {
// Reads data in bytes
}
public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
// Converts bytes to characters
}
public File saveToFile(String[] colliderData) {
// Saves read data to a file
}
public void printColliderData(File fileWithColliderData) {
// Prints data from the file
}
}
ただし、インターフェイスに関するレッスンで覚えているように、ユーザーは外部インターフェイスにのみアクセスできます。そして、私たちの 4 つのメソッドはその一部ではありません。これらはヘルパー メソッドです。コードの読みやすさを向上させるため、および 4 つの異なるタスクを 1 つのメソッドに詰め込まないようにするために作成されました。ユーザーにこれらのメソッドへのアクセス権を与える必要はありません。ユーザーがコライダーを操作するときにConvertBytesToSymbols()メソッドにアクセスできる場合、おそらく単にこのメソッドに混乱し、それが何のためのものなのか疑問に思うでしょう。どのバイトが変換されるのでしょうか? 彼らはどこから来ましたか?なぜテキストに変換するのでしょうか? このメソッドで実行されるロジックは、ユーザーに公開されるインターフェイスの一部ではありません。readDataFromCollider()のみメソッドはインターフェイスの一部です。では、これら 4 つの「内部」メソッドを使って何をするのでしょうか? 右!これらへのアクセスを制限するには、private修飾子を使用します。これにより、ユーザーを混乱させることなく、クラス内で平和的に作業を実行できるようになり、個々のメソッドのロジックを知る必要がなくなりました。
public class ColliderUtil {
public void readDataFromCollider(Path pathToData) {
byte[] colliderData = readByteData(pathToData);
String[] textData = convertBytesToSymbols(colliderData);
File fileWithData = saveToFile(textData);
printColliderData(fileWithData);
}
private byte[] readByteData(Path pathToData) {
// Reads data in bytes
}
private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
// Converts bytes to characters
}
private File saveToFile(String[] colliderData) {
// Saves read data to a file
}
private void printColliderData(File fileWithColliderData) {
// Prints data from the file
}
}
保護された修飾子
次に制限的な修飾子がprotectedです。 protected
- 私たちのものと同じパッケージに含まれるすべてのクラス内。
- 私たちのクラスを継承するすべてのクラス内で。
public abstract class AbstractSecretAgent {
public static int agentCount = 0;
}
しかし、私たちのエージェントは秘密です!これは、それらが何個存在するかを彼らだけでなく他の誰も知る必要がないことを意味します。protected修飾子をagent_counterフィールドに簡単に追加できます。その後、他のシークレット エージェント クラスや、top_secretパッケージにある他のクラスのインスタンスがその値を取得できるようになります。
public abstract class AbstractSecretAgent {
protected static int agent_counter = 0;
}
そして、それはprotected修飾子 を必要とする特殊なタスクです:)
パッケージ可視修飾子
リストの次はデフォルトのモディファイアで、パッケージ表示モディファイアとも呼ばれます。Java はデフォルトでキーワードをすべてのフィールドとメソッドに適用するため、これはキーワードによって示されません。コードに次のように記述すると、次のようになります。int x = 10
x 変数には、このパッケージへの可視アクセス権が与えられます。何をするのか覚えておくのは簡単です。基本的に、default = protected継承 :) protected修飾子と同様に、その用途は制限されています。ほとんどの場合、デフォルトのアクセスは、パッケージ内の他のすべてのクラスの機能を実装していないいくつかのユーティリティ クラスを含むパッケージで使用されます。例を挙げてみましょう。「サービス」パッケージがあると想像してください。データベースを操作するさまざまなクラスが含まれています。たとえば、データベースからユーザー データを読み取るUserServiceクラス、 CarServiceがあります。同じデータベースから車のデータを読み取るクラスと、その他のクラスです。それぞれが特定の種類のオブジェクトを処理し、データベースから対応するデータを読み取ります。
package services;
public class UserService {
}
package services;
public class CarService {
}
しかし、データベース内のデータがある形式であり、それを別の形式で必要とすることは簡単です。データベース内のユーザーの生年月日が <TIMESTAMP WITH TIME ZONE> として保存されていると想像してください...
2014-04-04 20:32:59.390583+02
...代わりに、最も単純なオブジェクトであるjava.util.Dateが必要です。この問題を解決するには、サービスパッケージ内で特別なMapperクラスを作成します。これは、データベースのデータを使い慣れた Java オブジェクトに変換する役割を果たします。単純なヘルパークラス。通常、すべてのクラスをpublic class ClassNameとして宣言しますが、これは必須ではありません。ヘルパー クラスを単純にclass Mapperとして宣言できます。この場合、サービスは引き続き機能しますが、サービスパッケージの外部には表示されません。
package services;
class Mapper {
}
package services;
public class CarService {
Mapper mapper;
}
基本的な理由は次のとおりです。なぜ、パッケージの外部にいる人が、そのパッケージ内のクラスでのみ機能するヘルパー クラスを参照する必要があるのでしょうか?
public 修飾子
そして最後になりましたが、public修飾子です。この修飾子は、CodeGym での学習初日に初めてpublic static void main(String[] args)を実行したときに出会いました。
public class Translator {
public String translate(String textInRussian) {
// Translates text from Russian to English
}
}
このメソッドを画面上の「翻訳」ボタンにバインドすれば完了です。誰でも使用できます。public修飾子でマークされたコード部分は、エンド ユーザーを対象としています。実際の例を挙げると、プライベートはテレビ内で発生するすべてのプロセスを表しますが、パブリックはテレビの管理に使用されるリモコンのボタンを表します。さらに、ユーザーはテレビがどのように構築され、どのように機能するかを知る必要はありません。リモート コントロールは、パブリックメソッドのセットです: on()、off()、nextChannel()、previousChannel()、増加ボリューム()、減少ボリューム()など。 学んだことをさらに強化するには、Java コースのビデオ レッスンを視聴することをお勧めします。