Java基本チュートリアル パート2のパッケージとアクセス許可
このセクションの学習目標
- Java の 4 つのアクセス権をマスターします。
- Java 言語の命名規則をマスターします。
- シングルトン設計パターンとマルチケース設計パターンの定義構造をマスターします。
1️⃣ アクセス制御権限
カプセル化については、実は前に詳しく説明しただけですprivate
が、カプセル化を完全に説明したい場合は、4 種類のアクセス権をすべて組み合わせる必要があり、これら 4 種類のアクセス権の定義を次の表に示します。
範囲 | プライベート | デフォルト | 保護された | 公共 |
---|---|---|---|---|
同じカテゴリの | √ | √ | √ | √ |
同じパッケージ内の異なるクラス | √ | √ | ||
さまざまなパッケージのサブクラス | √ | √ | ||
異なるパッケージの非サブクラス | √ |
private
上の表は、このクラスでのみアクセスできる、default
同じパッケージでのみアクセスできる、protected
異なるパッケージのサブクラスでアクセスできる、public
すべてのクラスでアクセスできる、と単純に理解できます。
private
、 、については前回の記事で学習済みなのでdefault
、ここでは主に を説明します。public
protected
// 范例 1: 定义 com.xiaoshan.demoa.A 类
package com.xiaoshan.demoa;
public class A{
protected String info="Hello";//使用 protected权限定义
}
// 范例 2: 定义 com.xiaoshan.demob.B 类,此类继承A 类
package com.xiaoshan.demob;
import com.xiaoshan.demoa.A;
public class B extends A{
// B是A 不同包的子类
public void print(){
//直接访问父类中的protected属性
System.out.println("A 类的 info = "+ super.info);
}
}
B
クラスはA
のサブクラスであるため、親クラスの許可属性にB
はクラス内で直接アクセスできます。protected
// 范例 3: 代码测试
package com.xiaoshan.test;
import com.xiaoshan.demob.B;
public class Test {
public static void main(String args[]){
new B().print();
}
}
プログラムの実行結果:
A 类的 info = Hello
このプログラムはクラス B を直接インポートし、オブジェクトをインスタンス化してメソッドを呼び出しprint()
、メソッド内でprint()
" " を使用して親クラスの許可属性super.info
に直接アクセスします。また、メイン クラスを直接使用してpackage内の属性にアクセスしたい場合、属性は同じパッケージ内になく、継承関係がないため、アクセスできません。protected
com.xiaoshan.test
Test
A
// 范例 4: 错误的访问
package com.xiaoshan.test;
import com.xiaoshan.demoa.A;
public class Test {
public static void main(String args[]){
A a = new A();
System.out.println(a.info); //错误:无法访问
}
}
このプログラムはコンパイル時にユーザーに直接プロンプトを表示しますが、info
これはprotected
許可であるため、直接アクセスすることはできません。
実際、与えられた 4 種類のパーミッションのうち、3 種類のパーミッション ( private
、default
、protected
) はすべてカプセル化の記述であり、オブジェクト指向のカプセル化が真に完全に説明されました。実際の開発と使用に関しては、パーミッションはほとんど使用されないため、実際に使用されるパーミッションとカプセル化のdefault
概念は2 つだけですprivate
。protected
アクセス権については、初心者は次の 2 つの基本的な使用原則を理解する必要があります。
- 属性は主な使用
private
許可を宣言します。 - メソッド宣言では主に
public
権限を使用します。
2️⃣ 命名規則
命名規則の主な特徴は、プログラム内のクラス名またはメソッド名が明確にマークされることですが、Java の場合は、従う必要のある固定の命名規則がいくつかあります。
- クラス名: 各単語の最初の文字は大文字になります。例:
TestDemo
; - 変数名: 最初の単語の最初の文字は小文字で、その後の各単語の最初の文字は大文字になります。たとえば、次のようになります
studentName
。 - メソッド名: 最初の単語の最初の文字は小文字で、その後の各単語の最初の文字は大文字になります。例:
printInfo()
; - 定数名: 各文字を大文字にします。例:
FLAG
; - パッケージ名: すべて小文字、例:
com.xiaoshanjava.util
。
なお、上記 5 つの命名規則はすべての開発者が遵守するものであり、開発チームによっても独自の命名規則が存在する場合がありますので、今後のソフトウェア開発においては、これらの命名規則に注意して従う必要があります。
3️⃣ シングルトンデザインパターン (Singleton)
属性定義の多くはprivate
宣言する必要がありましたが、コンストラクタもprivate
宣言することができ、このときのコンストラクタはプライベート化されます。そして、建設業者の民営化によってどのような問題が生じ、どのような影響があるのでしょうか。簡単な分析をしてみましょう。
まず、プライベート コンストラクターの動作を説明する前に、次のプログラムを観察してみましょう。
// 范例 5: 构造方法非私有化
class Singleton {
//定义一个类,此类默认提供无参构造方法
public void print(){
System.out.println("Hello World.");
}
}
public class TestDemo{
public static void main(String args[])(
Singleton inst = null; //声明对象
inst = new Singleton(; //实例化对象
inst.print(); //调用方法
}
}
プログラム実行結果:
Hello World.
このプログラムでは、Singleton
クラス内に構築メソッドが存在するため(クラス内で構築メソッドが明示的に定義されていない場合は、パラメータなしで何もしない構築メソッドが自動生成されるため)、まずオブジェクトを直接インスタンス化し、その後、クラスで提供されるメソッドを呼び出すことができますprint()
。構築方法を変更して、private
カプセル化を使用してみましょう。
// 范例 5: 私有化构造方法
class Singleton{
//定义一个类
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
}
public class TestDemo {
public static void main(String args[]){
Singleton inst = null; //声明对象
inst = hew Singletono: //错误:The constructor Singleton() is not visible
inst.print(); //调用方法
}
}
このプログラムがクラス オブジェクトをインスタンス化すると、コンストラクターがプライベート化されて外部から呼び出すことができないため、プログラムでコンパイル エラーが発生します。つまり、クラスのオブジェクトをSingleton
外部からインスタンス化できません。Singleton
さて、Singleton
クラス内の構築メソッドが変更または追加されず、メソッドが変更されないことを保証print()
する場合、クラスの外部からprint()
オブジェクトをインスタンス化してメソッドを呼び出すにはどうすればよいでしょうか?
考え方 1:private
アクセス許可で定義された操作は、このクラスからのみアクセスでき、外部から呼び出すことはできません 構築メソッドがプライベート化されたことで、このクラスの構築メソッドはこのクラスからのみ呼び出すことができる、つまり、このクラスのインスタンス化されたオブジェクトのみがこのクラスで生成できることがわかります。
// 范例 6: 第一步思考
class Singleton {
//定义一个类
Singleton instance = new Singleton(); //在内部实例化本类对象
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
}
考え方 2: クラス内の通常の属性の場合、デフォルトでは、このクラス内にインスタンス化されたオブジェクトが存在した後にそれらを呼び出す必要がありますが、このプログラムはクラスの外にインスタンス化されたオブジェクトを生成できないため、Singleton
クラスのインスタンス化されたオブジェクトがないときにクラス内の属性を呼び出せるようにする方法を見つける必要があります。したがって、これは を使用して実行でき、定義された属性プロパティはクラス名によって直接呼び出され、オブジェクトがインスタンス化されていないときに呼び出すことができます。Singleton
instance
Singleton
static
static
// 范例 7: 第二步思考
class Singleton {
//定义一个类
static Singleton instance = new Singleton(); //可以由类名称直接访问
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
}
public class TestDemo {
public static void main(String args[]){
Singleton inst = null; //声明对象
inst = Singleton.instance; //利用“类.static属性”方式取得实例化对象
inst.print(); //调用方法
}
}
プログラム実行結果:
Hello World.
考え方3: クラス内の属性はすべてカプセル化する必要があるので、instance
上記の例の属性もカプセル化する必要があり、カプセル化後の属性を取得するにはメソッドを記述する必要がありますgetter
が、このときgetter
メソッドもstatic
typeとして定義されたクラス名で直接呼び出す必要があります。
// 范例 8: 第三步思考
class Singleton {
//定义一个类
private static Singleton instance = new Singleton();
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
public static Singleton getInstance(){
//取得本类对象
return instance;
}
}
public class TestDemo(
public static void main(String args[]){
Singleton inst = null; //声明对象
inst = Singleton.getInstance(); //利用“类.static方法()”取得实例化对象
inst.print(); //调用方法
}
}
プログラム実行結果:
Hello World.
思考 4: これを行う目的は何ですか? プログラム内のinstance
属性はstatic
定義に属します。つまり、Singleton
オブジェクト宣言がいくつあっても、クラスのすべてのオブジェクトは同じinstance
属性参照を共有することになります。したがって、それらは同じなので、何が意味があるのでしょうか?
クラス内でインスタンス化されるオブジェクトの数を制御したい場合、最初にロックする必要があるのは、クラス内のコンストラクター (コンストラクターの定義に使用) です。コンストラクターは、新しいオブジェクトをインスタンス化するときに使用する必要があるためです。コンストラクターがロックされていると、当然のことながら、新しいインスタンス化されたオブジェクトを生成することはできなくなりますprivate
。
クラス内で定義された操作を呼び出したい場合は、当然インスタンス化されたオブジェクトが必要です。このとき、クラス内のメソッドを使用してパブリック オブジェクトを定義し、メソッドを通じて毎回一意のオブジェクトを返すことができます。そのため、外部呼び出しが何度あっても、クラスは最終的に一意のオブジェクトしか生成できません。この設計は、シングルトン デザインstatic
パターンstatic
( ) に属しますSingleton
。
ただし、このプログラムにはまだ問題があり、次のコードも使用できます。
// 范例 9: 程序出现的问题
class Singleton {
//定义一个类
private static Singleton instance = new Singleton();
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
public static Singleton getInstance(){
// 取得本类对象
instance = new Singleton(); //重新实例化对象
return instance;
}
}
このプログラムの操作の構文には何の問題もありません。それが意味があるかどうかを考える必要はありません。現在のコードではそれが可能です。そうすることで、唯一のインスタンス化されたオブジェクトを表現するためのこれまでのすべての努力が無駄になっていることがわかります。したがって、この慣行を廃止する方法を見つける必要があるため、を定義するときにキーワードinstance
を追加する必要がありますfinal
。
// 范例 10: 一个完整的单例模式的程序
class Singleton {
//定义一个类
private final static Singleton instance = new Singleton();
private Singleton(){
//构造方法私有化
}
public void print(){
System.out.println("Hello World.");
}
public static Singleton getInstance(){
//取得本类对象
return instance;
}
}
public class TestDemo{
public static void main(String args[]){
Singleton inst = null; //声明对象
inst = Singleton.getInstance(); //利用“类.static方法()”取得实例化对象
inst.print(); //调用方法
}
}
プログラム実行結果:
Hello World.
クラスを使用する場合、コードがどのように動作するかに関係なく、インスタンス化されるクラスのオブジェクトはSingleton
常に 1 つだけになります。このようなコードは、デザイン パターンではシングルトン デザイン パターン ( ) と呼ばれます。Singleton
Singleton
4️⃣ 複数インスタンスの設計パターン
シングルトン設計パターンでは、クラスのインスタンス化されたオブジェクトが 1 つだけ残りますが、マルチインスタンス設計パターンでは複数のオブジェクトが定義されます。
たとえば、曜日を表す操作クラスを定義し、このクラスのオブジェクトはインスタンス化されたオブジェクトを 7 つだけ持つことができます ( ); 性別を表すクラスを定義し、インスタンス化されたオブジェクトを 2 つだけ持つことができます ( ); カラーの基本色を表す操作クラスを定義し、インスタンス化されたオブジェクトを 3 つだけ持つことができます星期一 ~星期日
( 男、女
) 红、绿、蓝
。
このような場合、そのようなクラスではユーザーが無制限にインスタンス化されたオブジェクトを作成できるようにすべきではなく、マルチインスタンス設計に属する限られた数のみを使用する必要があります。シングルインスタンス設計であっても、マルチインスタンス設計であっても、揺るぎない核心は工法の民営化です。
// 范例 11: 定义一个表示性别的类
package com.xiaoshan.demo;
class Sex{
private String title;
private static final Sex MALE = new Sex("男");
private static final Sex FEMALE = new Sex("女");
private Sex(String title){
//构造私有化
this.title = title;
}
public String toString(){
return this.title;
}
public static Sex getInstance(int ch){
//返回实例化对象
switch (ch){
case 1:
return MALE;
case 2:
return FEMALE;
default:
return;
}
}
}
public class TestDemo {
public static void main(String args[]){
Sex sex = Sex.getInstance(2);
System.out.println(sex);
}
}
プログラムの実行結果:
女
このプログラムは、まず性別を記述するマルチインスタンス プログラム クラスを定義し、その構築メソッドをカプセル化し、次にそのメソッドを使用して、指定された数値を受け取った後にgetInstance()
インスタンス化されたクラス オブジェクトを返します。Sex
例 11 のコードは、Sex
数値を使用してクラスのオブジェクトを取得します。このメソッドで表現される概念が明確ではないと感じる人もいるかもしれません。オブジェクトの型をより明確に取得するために、それを説明するインターフェイスを導入できます。
// 范例 12: 利用接口标记对象内容
interface Choose {
public int MAN = 1; //描述数字
public int WOMAN = 2; //描述数字
}
public class TestDemo {
public static void main(String args[]){
//利用接口标记内容取得对象
Sex sex = Sex.getInstance(Choose.MAM);
System.out.println(sex);
}
}
このプログラムは、指定されたクラス オブジェクトを取得したい場合Sex
、インターフェイスで定義されているグローバル定数 (実際には、Sex
一部のグローバル定数はクラスでも定義できます) を使用して判断できます。この方法は標準的な方法ですが、少し複雑なので、文字列を使用して直接判断する方が簡単です。
JDK 1.7以前では、や型の判定switch
しかサポートできず、単に数字や文字だけだと意味が不明瞭なので、 のサポートが追加されました。int
char
String
// 范例 13: 对取得Sex 类对象进行修改
package com.xiaoshan.demo;
class Sex{
private String title;
private static final Sex MALE = new Sex("男");
private static final Sex FEMALE = new Sex("女");
private Sex(String title){
//构造私有化
this.title = title;
}
public String toString(){
return this.title;
}
public static Sex getInstance(String ch){
switch (ch){
//利用字符串判断
case "man":
return MALE;
case "woman":
return FEMALE;
default:
return null;
}
}
}
public class TestDemo {
public static void main(String args[]){
Sex sex = Sex.getInstance("man");
System.out.println(sex);
}
}
プログラムの実行結果:
男
このプログラムでは判定条件を直接利用するString
ためswitch
、インスタンス化されたオブジェクトを取得する際に、オブジェクト名を文字列で記述することができ、数値を直接記述するよりも便利です。