Javaのpublic、protected、package-private、privateの違いは何ですか?


3171

Javaでは、すなわちデフォルト(パッケージプライベート)、アクセス修飾子の各使用する際の明確なルールがあるpublicprotectedとはprivateしながら、classかつinterface、継承を扱いますか?


161
privateパッケージ内の他のクラスから隠します。publicパッケージ外のクラスに公開します。protectedは、publicサブクラスのみに制限されたバージョンです。
ミューズフル2013

87
@Tennenrishin —いいえ。C ++とは異なり、Java protectedでは、メソッドがパッケージ全体からもアクセス可能になります。Javaの可視性モデルにおけるこの愚かさは、の目標を破りprotectedます。
Nicolas Barbulesco 2013

35
@Nicolasこれは、パッケージの有無にかかわらず、パッケージ全体からアクセスできますprotected。アクセスとして修飾子、そのすべてprotected行いますが、パッケージ外のサブクラスに公開することです。
ミューズフル2014年

15
@tennenrishin-まあ、それはニコラスが言ったことです...そしてあなたは今それを繰り返しています。あなたが最初に言ったのはprotected-そして私が引用している-「サブクラスにのみ制限されたパブリックのバージョンである」ということですが、プロテクトはパッケージ全体へのアクセスも許可するため、あなた自身の承認には当てはまりません(エルゴ、それはサブクラスへのアクセスを制限しません)。 )
luis.espinal 2014

10
また、Javaの保護されたアクセスモードがばかげているという点で、Nicolasにも同意します。起こったことは、Javaが水平(格子)と垂直のアクセス制限修飾子を融合させたことです。デフォルトのスコープは、パッケージがラティスの場合の水平/ラティス制限です。パブリックは、ラティスが全世界である別の水平方向の制限です。プライベートおよび(C ++)保護は垂直です。たとえば、protected-package実際に必要なまれなケースでクロスカットアクセスprotectedがあり、C ++の保護されたバージョンと同等であることが望ましいです。
luis.espinal 2014

回答:


5639

公式チュートリアルあなたに役立つかもしれません。

______________________________________________________________
| │クラス│パッケージ│サブクラス│サブクラス│ワールド|
| │││(同じパッケージ)│(差分パッケージ)│|
|───────────┼───────┼─────────┼──────────┼──────── ──┼────────|
|公開│+│+│+│+│+ | 
|───────────┼───────┼─────────┼──────────┼──────── ──┼────────|
|保護│+│+│+│+│| 
|───────────┼───────┼─────────┼──────────┼──────── ──┼────────|
|修飾子なし│+│+│+││| 
|───────────┼───────┼─────────┼──────────┼──────── ──┼────────|
|プライベート│+││││|
| ___________ | _______ | _________ | __________ | __________ | ________ |
 +:アクセス可能空白:アクセス不可

5
上記の表は正しくありません。privateメンバーも同じソースファイル内のクラス/静的メソッドで表示/使用できるためです。
宮本うさぎ

5
保護されたメンバーには、同じパッケージのサブクラスからのみアクセスでき、別のパッケージのサブクラスからはアクセスできません。上記の表に修正があるはずです
niks

2
世界はあなたのプロジェクトの中にあります。さらに説明する必要があります。ライブラリはプロジェクト内にあり、ライブラリを作成している場合は、これらのパブリッククラスとメソッドも公開します。したがって、プロジェクト内で言うのは少しずれています。「それを使用するすべてのもの」はより良い説明です。
adprocas

3
たとえばMyClass、私が現在行っている場合はAnotherClass extends MyClass、内からすべての保護されたパブリックメソッドとプロパティにアクセスできますAnotherClass。私が行う場合MyClass myClass = new MyClass();にはAnotherClassどこか-のは、コンストラクタを言わせて-それは別のパッケージ内にある場合、私は唯一のパブリックメソッドにアクセスする必要があります。実行= new MyClass() { @Override protected void protectedMethod() { //some logic } };すると、保護されたメソッドにアクセスできるように見えますが、これは拡張と同じですが、代わりにインラインです。
adprocas

3
残念ながら、この答えは全体的な単純化です。特に考慮した場合、現実はもう少し複雑ですprotected(これは、完全に理解するのは実際には非常に難しいアクセス修飾子です-自分が何をprotected意味するかを知っていると考えるほとんどの人は、実際にはそうではありません)。また、ボヘミアンが指摘したように、それは質問には答えません- 各アクセス修飾子をいつ使用するかについては何も述べていません。私の意見では、この答えではありません非常に悪いdownvoteに十分な、しかし、があります。しかし、4000以上の賛成票は?どうしてそうなった?
Dawood ibnカリーム2018

483

(注意:私はJavaプログラマーではなく、Perlプログラマーです。Perlには正式な保護機能がないため、問題をよく理解しているのかもしれません:))

民間

ご想像のとおり、宣言されたクラスだけがそれを見ることができます。

パッケージプライベート

宣言されたパッケージでのみ表示および使用できます。これはJavaのデフォルトです(これは間違いと見なされています)。

保護された

Package Private +は、サブクラスまたはパッケージメンバーから見ることができます。

公衆

誰もがそれを見ることができます。

公開済み

私が制御するコードの外から見える。(Java構文ではありませんが、この説明では重要です)。

C ++は "友達"と呼ばれる追加のレベルを定義し、それについてあなたが知らなければ少ないほど良いです。

何を使うべきですか?全体のアイデアは、情報を隠すためのカプセル化です。ユーザーから何かが行われる方法の詳細をできるだけ隠す必要があります。どうして?後で変更することができ、誰のコードも壊さないからです。これにより、オーバーホールしたばかりのコードが誰かに使用されているという心配なく、バグを最適化、リファクタリング、再設計、修正できます。

したがって、経験則では、必要なものだけを表示するようにします。プライベートから始めて、必要に応じて可視性を追加します。ユーザーが知るために絶対に必要なものだけを公開します。公開するすべての詳細は、システムを再設計する能力を妨げます。

ユーザーが内部をパブリックにしてオーバーライドできるようにするのではなく、ユーザーが動作をカスタマイズできるようにしたい場合は、それらの内臓をオブジェクトに入れて、そのインターフェースをパブリックにすることをお勧めします。そうすれば、新しいオブジェクトをプラグインできます。たとえば、CDプレーヤーを作成していて、「このCDに関する情報を検索」ビットをカスタマイズ可能にしたい場合は、これらのメソッドを公開するのではなく、その機能をすべて独自のオブジェクトに入れて、オブジェクトゲッター/セッターだけを公開します。 。このように、あなたの腸を露出することについてけちであることが、良い構成と懸念の分離を促進します

個人的には「プライベート」と「パブリック」だけにこだわっています。多くのオブジェクト指向言語にはそれがあります。「保護された」は便利ですが、それは本当にごまかしです。インターフェースがプライベート以上になると、それはあなたのコントロールの外にあり、他の人のコードを調べて用途を見つける必要があります。

これが「公開」のアイデアの出番です。インターフェイスを変更(リファクタリング)するには、それを使用しているすべてのコードを見つけ、それも変更する必要があります。インターフェイスがプライベートの場合、問題ありません。保護されている場合は、すべてのサブクラスを見つける必要があります。それが公開されている場合は、自分のコードを使用するすべてのコードを見つける必要があります。たとえば、内部使用のみの企業コードで作業している場合、これが可能である場合があります。インターフェイスがパブリックであるかどうかは関係ありません。企業リポジトリからすべてのコードを取得できます。しかし、インターフェースが「公開されている」場合、それを使用しているコードがコントロールの外にある場合は、うんざりしています。そのインターフェースをサポートする必要があります。保護されたインターフェースでさえ公開されたと見なすことができます

多くの言語では、パブリック/保護/プライベートの階層的性質が制限的であり、現実に沿っていないことがわかります。そのために、特性クラスの概念がありますが、それは別のショーです。


26
友人->「それについてあまり知らない方が良い」--->これは選択的な可視性を提供し、パッケージのプライバシーよりも優れています。C ++では、すべての関数をメンバー関数にすることができるわけではないため、C ++には用途があります。もちろん邪悪な心による誤用の危険があります。
セバスチャンマッハ

30
C ++での「保護された」の意味は異なることに注意してください。保護されたメソッドは事実上プライベートですが、継承クラスから呼び出すことができます。(同じパッケージ内の任意のクラスから呼び出すことができるJavaとは対照的です。)
Rhys van der Waerden、2011年

9
@RhysvanderWaerden C#は、この点ではC ++と同じです。Javaが、パッケージ全体ではなく、サブクラスにアクセスできるメンバーを宣言することを許可していないのはかなり奇妙です。それは私にとって逆さまのようなものです-パッケージは子クラスよりも広いスコープです!
Konrad Morawski 2013年

15
@KonradMorawski IMHOパッケージは、サブクラスよりもスコープが小さいです。クラスをfinalに宣言していない場合、ユーザーはそれをサブクラス化できるはずです。そのため、Java保護は公開されたインターフェースの一部です。OTOH、パッケージは、単一の組織によって暗黙的に開発されています(例:com.mycompany.mypackage)。コードが自分のパッケージで自分自身を宣言している場合は、暗黙的に自分が自分の組織の一部であることを宣言しているので、コミュニケーションをとるべきです。したがって、パッケージは、サブクラス(オブジェクトを拡張する人々)よりも小さくて簡単にオーディエンス(私の会社の人々)に到達するため、低い可視性としてカウントされます。
町の名を冠した

2
friendクラス間の特別な関係を定義するのに適しています。正しく使用すると、多くの場合、優れたカプセル化が可能になります。たとえば、特権ファクトリクラスはこれを使用して、内部依存関係を構築型に注入できます。適切に設計されたオブジェクトモデルを正しく維持することを気にしない人は、ワークロードを緩和するために悪用することができるため、この名前は不適切です。
Dennis

434

次の表は、モジュールの列も含まれる、より優れたバージョンです。

Javaアクセス修飾子

解説

  • プライベートメンバーは(i)であるだけで、それが宣言されているのと同じクラス内でアクセス。

  • アクセス修飾子j)のないメンバーは、同じパッケージ内のクラス内でのみアクセスできます。

  • 保護されたメンバーは、( k)同じパッケージ内のすべてのクラス内でアクセス可能である他のパッケージ内のサブクラス内。

  • 公共のメンバーは(l(それは内に存在しない限り)すべてのクラスにアクセス可能であるモジュールそれがで宣言されているパッケージをエクスポートしません)。


選択する修飾子は?

アクセス修飾子は、誤ってカプセル化を解除することを防ぐためのツールです(*)。メンバーがクラス、パッケージ、クラス階層の内部であるか、またはまったく内部でないかを考え、それに応じてアクセスレベルを選択します。

例:

  • フィールドlong internalCounterは変更可能であり、実装の詳細であるため、おそらくプライベートにする必要があります。
  • (同じパッケージ内の)ファクトリクラスでのみインスタンス化する必要があるクラスは、パッケージの外部から直接呼び出すことはできないため、パッケージ制限付きコンストラクターが必要です。
  • void beforeRender()レンダリングの直前に呼び出され、サブクラスでフックとして使用される内部メソッドは保護する必要があります。
  • void saveGame(File dst)GUIコードから呼び出されるメソッドは、公開すべきです。

(*)カプセル化とは正確には何ですか?


11
ただ言う:赤/緑の色の区別に問題がある人はたくさんいます。赤/緑(または黄/オレンジ/ ...)の配色を使用するテーブルは、ほとんどの場合、何よりも「良い」とは
言えません

1
@GhostCat、私は同意しません。私はそれはすなわち、多くの人々のために、「仕事がない」/「作品」と直感的に赤/緑の整列を考えているより良い多くの選択肢より。
aioobe 2018年

8
colourblindawareness.org/colour-blindness/… ... 色覚異常の男性の8%は、おおよそ1%重水素症、1%変色虫、1 %変色性および5%重水素症に分けることができます。そして、私はその5%のうちの50%の1人なので、安心してください:赤/緑は嫌です。
GhostCat 2018年

6
@GhostCat OK ..それは私が予想したよりも人口の大部分です。この色覚異常シミュレータに画像をアップロードし、すべての異なるモードをテストしました。単色性/アクロマトプシアモードでも、色の違いは合理的です。違いがわかりますか、それともシミュレータがオフになっていますか?(私はまだ赤/緑がカラーを見る人にとって非常に直感的であるという意見です。)
aioobe

3
私は違いを見ることができますが、運転免許証のためにドイツで行わなければならない色覚異常テストの半分にも合格することができます;-) ...しかし、そのようなシミュレータは「十分に良い」と思います。
GhostCat 2018年

206
____________________________________________________________________
                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |    
Modifier of x \ |               |           |               |       
————————————————*———————————————+———————————+———————————————+———————
public          |              |          |              |     
————————————————+———————————————+———————————+———————————————+———————
protected       |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
private         |              |          |              |       
____________________________________________________________________

1
それは言葉で言う価値があります-「保護された修飾子は他のパッケージでオブジェクトを利用可能にしますが、デフォルト/修飾子なしは同じパッケージへのアクセスを制限します」
vanguard69

2
@ vanguard69、protected修飾子は顕著になります、いくつかの他のパッケージ内の他のクラスに利用できる(クラス、メソッド、またはフィールド)のみIFFは、他のクラスは、そのクラスのサブクラスであると述べたprotectedマーク- ことが宣言されています。
Abdull

「下塗りなし」?「別のパッケージのこのサブクラス」?ええと。私はJavaを知っていると思いました。
sehe

@AlexanderFarberは、特定のブラウザー構成用に最適化しましたか?これが今の私のクロムで、これがあるのFirefox
sehe

では、変更を元に戻しましょう
Alexander Farber

165

簡単なルール。すべてをプライベートに宣言することから始めます。そして、ニーズが発生し、設計がそれを保証するように、国民に向かって前進します。

メンバーを公開するときは、表現の選択肢または抽象化の選択肢を公開するかどうかを自問してください。1つ目は、観察可能な動作ではなく実際の表現に依存しすぎるため、避けたいものです。

原則として、サブクラス化によってメソッド実装をオーバーライドしないようにしています。ロジックを台無しにするのは簡単すぎる。オーバーライドする場合は、抽象保護メソッドを宣言してください。

また、オーバーライドするときに@Overrideアノテーションを使用して、リファクタリング時に破損しないようにします。


3
@RuchirBaronia、 "world" =どこにあるかに関係なく、アプリケーション内のすべてのコード。
Andrejs 2016

116

実際には、単純なグリッドの表示よりも少し複雑です。グリッドはアクセスが許可されているかどうかを通知しますが、正確には何がアクセスを構成していますか?また、アクセスレベルはネストされたクラスや継承と複雑な方法で相互作用します。

「デフォルト」アクセス(キーワードがないことで指定)は、package-privateとも呼ばれます。例外:インターフェースでは、修飾子はパブリックアクセスを意味しません。public以外の修飾子は禁止されています。列挙型定数は常にパブリックです。

概要

このアクセス指定子を持つメンバーへのアクセスは許可されていますか?

  • Member is private:メンバーが呼び出しコードと同じクラス内で定義されている場合のみ。
  • メンバーはパッケージプライベートです:呼び出しコードがメンバーのすぐ外側のパッケージ内にある場合のみ。
  • Member is protected:同じパッケージ、またはメンバーが呼び出しコードを含むクラスのスーパークラスで定義されている場合。
  • メンバーはpublic:はい。

適用されるアクセス指定子

ローカル変数と仮パラメーターはアクセス指定子をとることはできません。スコーピングルールによれば、これらは本質的に外部からアクセスできないため、事実上プライベートです。

トップスコープのクラスの場合、publicおよびpackage-private のみが許可されます。この設計上の選択が考えられるため、protectedおよびprivateパッケージ・レベルで冗長になる(パッケージのない相続はありません)。

すべてのアクセス指定子は、クラスメンバー(コンストラクター、メソッド、静的メンバー関数、ネストされたクラス)で使用できます。

関連:Javaクラスのアクセシビリティ

注文

アクセス指定子は厳密に順序付けできます

public> protected> package-private> private

publicほとんどのアクセスを提供する意味、private。プライベートメンバーで可能な参照は、パッケージプライベートメンバーにも有効です。package-privateメンバーへの参照はすべて、保護されたメンバーで有効です。(同じパッケージ内の他のクラスに保護されたメンバーにアクセス権を与えることは誤りと見なされました。)

ノート

  • クラスのメソッド、同じクラスの他のオブジェクトのプライベートメンバーにアクセスできます。より正確には、クラスCのメソッドは、Cの任意のサブクラスのオブジェクトのCのプライベートメンバーにアクセスできます。Javaは、インスタンスによるアクセス制限をサポートしていません。クラスによってのみ制限しています。(を使用してサポートしているScalaと比較してくださいprivate[this]。)
  • オブジェクトを構築するには、コンストラクタにアクセスする必要があります。したがって、すべてのコンストラクターがプライベートの場合、クラスはクラス内に存在するコード(通常は静的ファクトリーメソッドまたは静的変数初期化子)によってのみ構築できます。同様に、package-privateまたはprotectedコンストラクター。
    • Javaがサブクラスのコンストラクターを暗黙的または明示的にスーパークラスコンストラクターを呼び出す必要があるため、プライベートコンストラクターのみを持つことは、クラスを外部でサブクラス化できないことも意味します。(ただし、それをサブクラス化するネストされたクラスを含めることはできます。)

内部クラス

また、内部クラスなどのネストされたスコープも考慮する必要があります。複雑さの例としては、内部クラスにメンバーがあり、それ自体がアクセス修飾子を取ることができるということがあります。したがって、パブリックメンバーを持つプライベート内部クラスを持つことができます。メンバーはアクセスできますか?(以下を参照してください。)一般的なルールは、スコープを見て、再帰的に考えて、各レベルにアクセスできるかどうかを確認することです。

ただし、これは非常に複雑です。詳細については、Java言語仕様を参照してください。(はい、過去にコンパイラのバグがありました。)

これらがどのように相互作用するかについては、この例を検討してください。プライベート内部クラスを「リーク」することは可能です。これは通常警告です:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

コンパイラー出力:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

関連する質問:


1
「パブリック以外の修飾子は禁止されています」 — Java 9以降では、これは当てはまりません。インターフェースはプライベートメソッドを持つこともできます。
MC皇帝

96

経験則として:

  • private:クラスのスコープ。
  • default(またはpackage-private):パッケージのスコープ。
  • protected:(package scope + childパッケージのようですが、異なるパッケージからサブクラス化できます)。保護された修飾子は常に「親子」関係を維持します。
  • public: どこにでも。

その結果、アクセス権を3つの権利に分割すると、

  • (D)irect(同じクラス内のメソッドから、または「this」構文を介して呼び出します)。
  • (R)eference(クラスへの参照を使用するか、「ドット」構文を使用してメソッドを呼び出す)。
  • (I)継承(サブクラス化による)。

次に、この単純なテーブルがあります。

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+

54

非常に短い

  • public:どこからでもアクセス可能。
  • protected:同じパッケージのクラス、および任意のパッケージにあるサブクラスからアクセスできます。
  • デフォルト(修飾子は指定されていません):同じパッケージのクラスからアクセスできます。
  • private:同じクラス内でのみアクセスできます。

48

Javaで最も誤解されているアクセス修飾子はprotectedです。サブクラスがそれを見ることができるという一つの例外を除いて、それはデフォルトの修飾子に似ていることを知っています。しかし、どうやって?混乱を明確にした例を次に示します。

  • 2つのクラスがあるとします。FatherそしてSon、それぞれが独自のパッケージに含まれています。

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
  • に保護されたメソッドfoo()を追加しましょうFather

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
  • このメソッドfoo()は、4つのコンテキストで呼び出すことができます。

    1. foo()が定義されているのと同じパッケージにあるクラス内(fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
    2. サブクラス内、thisまたはを介した現在のインスタンスsuper

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
    3. タイプが同じクラスの参照について:

      package fatherpackage;
      
      public class Father
      {
          public void fatherMethod(Father f)
          {
              f.foo(); // valid even if foo() is private
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Son s)
          {
              s.foo();
          }
      }
    4. タイプが親クラスであり、パッケージfoo()定義されている参照の場合(fatherpackage)[これはコンテキストno内に含めることができます。1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
  • 以下の状況は無効です。

    1. 型が親クラスであり、パッケージが定義されているパッケージの外部にある参照foo()fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
    2. サブクラスのパッケージ内の非サブクラス(サブクラスは保護されたメンバーをその親から継承し、非サブクラスに対してプライベートにします):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }

Object#clone()protectedメンバーの例です。
Eng.Fouad 2013年

doとsuper.foo()first invalid はどう違いf.foo()ますか?
cst1992

1
@ cst1992わかりにくいですが、Java言語仕様6.6.2を参照してください:「オブジェクトの保護されたメンバーまたはコンストラクターは、そのオブジェクトの実装を担当するコードによってのみ宣言されているパッケージの外部からアクセスできます」。super.foo()を使用すると、参照「super」は「実装に直接責任があります」が、参照「f」はそうではありません。どうして?「スーパー」が父のタイプであることは100%確実である可能性がありますが、「f」ではありません。実行時には、それは父の他のサブタイプである可能性があります。docs.oracle.com/javase/specs/jls/se9/html/…を
skomisa

1
を理解している人からの回答を読むのは爽快protectedです。残念ながら、このページの他のすべての回答はprotected、少し間違っています。
Dawood ibnカリーム2018

30

民間

  • メソッド、変数、コンストラクタ

プライベートとして宣言されたメソッド、変数、およびコンストラクターは、宣言されたクラス自体内でのみアクセスできます。

  • クラスとインターフェース

プライベートアクセス修飾子は、最も制限的なアクセスレベルです。クラスとインターフェースをプライベートにすることはできません。

注意

プライベートとして宣言された変数は、クラスにパブリックゲッターメソッドが存在する場合、クラスの外部からアクセスできます。スーパークラスで保護されていると宣言されている変数、メソッド、およびコンストラクターは、他のパッケージのサブクラス、または保護されたメンバーのクラスのパッケージ内のクラスからのみアクセスできます。


保護された

  • クラスとインターフェース

保護されたアクセス修飾子は、クラスとインターフェイスに適用できません。

メソッド、フィールドは保護されていると宣言できますが、インターフェースのメソッドとフィールドは保護されていると宣言できません。

注意

保護されたアクセスにより、サブクラスはヘルパーメソッドまたは変数を使用できるようになりますが、関連のないクラスはそれを使用できません。


公衆

クラス、メソッド、コンストラクター、インターフェースなどのpublic宣言は、他のクラスからアクセスできます。

したがって、パブリッククラス内で宣言されたフィールド、メソッド、ブロックには、Javaユニバースに属する任意のクラスからアクセスできます。

  • 異なるパッケージ

ただし、アクセスしようとしているパブリッククラスが別のパッケージにある場合でも、パブリッククラスをインポートする必要があります。

クラス継承のため、クラスのすべてのパブリックメソッドと変数は、そのサブクラスによって継承されます。


デフォルト-キーワードなし:

デフォルトのアクセス修飾子とは、クラス、フィールド、メソッドなどのアクセス修飾子を明示的に宣言しないことを意味します。

  • 同じパッケージ内

アクセス制御修飾子なしで宣言された変数またはメソッドは、同じパッケージ内の他のクラスで使用できます。インターフェースのフィールドは暗黙的にpublic static finalであり、インターフェースのメソッドはデフォルトでpublicです。

注意

静的フィールドをオーバーライドすることはできません。オーバーライドしようとしてもエラーは表示されませんが、それ以外は機能しません。

関連する回答

参照リンク

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifiers.htm


21

違いは、すでに提供されているリンクにありますが、どちらを使用するかは、通常「最小知識の原則」に起因します。必要な最小限の可視性のみを許可します。


20

プライベート:クラスへの限定アクセス

デフォルト(修飾子なし):クラスとパッケージへの制限付きアクセス

保護:クラス、パッケージ、およびサブクラスへのアクセス制限(パッケージの内部と外部の両方)

Public:クラス、パッケージ(すべて)、およびサブクラスにアクセス可能...つまり、どこでも。


17

アクセス修飾子は、いくつかのレベルでアクセスを制限するためにあります。

パブリック:基本的に、同じパッケージにあるかどうかに関係なく、どのクラスからでもアクセスできるのと同じくらい簡単です。

同じパッケージに属している場合にアクセスするには、直接アクセスできますが、別のパッケージに属している場合は、クラスのオブジェクトを作成できます。

デフォルト:パッケージのどのクラスからでも同じパッケージでアクセスできます。

アクセスするには、クラスのオブジェクトを作成します。ただし、パッケージの外部からこの変数にアクセスすることはできません。

保護されています他のパッケージのサブクラスと同様に、同じパッケージの変数にアクセスできます。したがって、基本的にはデフォルト+継承された動作です。

基本クラスで定義された保護フィールドにアクセスするには、子クラスのオブジェクトを作成できます。

プライベート: 同じクラスでアクセスできます。

非静的メソッドでは、この参照のため(コンストラクターでも)、直接アクセスできますが、静的メソッドでアクセスするには、クラスのオブジェクトを作成する必要があります。


16

Javaでアクセス修飾子。

Javaアクセス修飾子は、Javaでアクセス制御を提供するために使用されます。

1.デフォルト:

同じパッケージ内のクラスにのみアクセスできます。

例えば、

// Saved in file A.java
package pack;

class A{
  void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B{
  public static void main(String args[]){
   A obj = new A(); // Compile Time Error
   obj.msg(); // Compile Time Error
  }
}

このアクセスは、パブリックよりも制限されて保護されていますが、プライベートよりは制限されていません。

2.パブリック

どこからでもアクセスできます。(グローバルアクセス)

例えば、

// Saved in file A.java

package pack;
public class A{
  public void msg(){System.out.println("Hello");}
}

// Saved in file B.java

package mypack;
import pack.*;

class B{
  public static void main(String args[]){
    A obj = new A();
    obj.msg();
  }
}

出力:こんにちは

3.プライベート

同じクラス内でのみアクセスできます。

別のクラスのプライベートメンバーにアクセスしようとすると、コンパイルエラーがスローされます。例えば、

class A{
  private int data = 40;
  private void msg(){System.out.println("Hello java");}
}

public class Simple{
  public static void main(String args[]){
    A obj = new A();
    System.out.println(obj.data); // Compile Time Error
    obj.msg(); // Compile Time Error
  }
}

4.保護されている

同じパッケージ内のクラスとサブクラスにのみアクセス可能

例えば、

// Saved in file A.java
package pack;
public class A{
  protected void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B extends A{
  public static void main(String args[]){
    B obj = new B();
    obj.msg();
  }
}

出力:こんにちは

ここに画像の説明を入力してください


14
  • 公共 -アプリケーション内のどこからでもアクセスできます。

  • デフォルト -パッケージからアクセス可能。

  • protected-パッケージおよび他のパッケージのサブクラスからアクセスできます。同様に

  • プライベート -クラスからのみアクセスできます。


14

パッケージに表示されます。デフォルト。修飾子は必要ありません。

クラスにのみ表示されます(プライベート)。

世界に公開公開)。

パッケージとすべてのサブクラスに表示されます(protected)。

変数とメソッドは、呼び出される修飾子なしで宣言できます。デフォルトの例:

String name = "john";

public int age(){
    return age;
}

プライベートアクセス修飾子-プライベート:

プライベートとして宣言されたメソッド、変数、およびコンストラクターは、宣言されたクラス自体内でのみアクセスできます。プライベートアクセス修飾子は、最も制限的なアクセスレベルです。クラスとインターフェースをプライベートにすることはできません。

プライベートとして宣言された変数は、クラスにパブリックゲッターメソッドが存在する場合、クラスの外部からアクセスできます。

プライベート修飾子の使用は、オブジェクトがそれ自体をカプセル化し、データを外部から隠す主な方法です。

例:

Public class Details{

    private String name;

    public void setName(String n){
        this.name = n;
    }

    public String getName(){
        return this.name;
    }
}

パブリックアクセス修飾子-パブリック:

クラス、メソッド、コンストラクター、インターフェースなどのpublic宣言は、他のどのクラスからでもアクセスできます。したがって、パブリッククラス内で宣言されたフィールド、メソッド、ブロックには、Javaユニバースに属する任意のクラスからアクセスできます。

ただし、アクセスしようとしているパブリッククラスが別のパッケージにある場合でも、パブリッククラスをインポートする必要があります。

クラス継承のため、クラスのすべてのパブリックメソッドと変数は、そのサブクラスによって継承されます。

例:

public void cal(){

}

保護されたアクセス修飾子-保護された:

スーパークラスで保護されていると宣言されている変数、メソッド、およびコンストラクターには、別のパッケージのサブクラス、または保護されたメンバーのクラスのパッケージ内のクラスからのみアクセスできます。

保護されたアクセス修飾子は、クラスとインターフェイスに適用できません。メソッド、フィールドは保護されていると宣言できますが、インターフェースのメソッドとフィールドは保護されていると宣言できません。

保護されたアクセスにより、サブクラスはヘルパーメソッドまたは変数を使用できるようになりますが、関連のないクラスはそれを使用できません。

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}

12

このページは、保護されたデフォルトのアクセス修飾子についてよく書いています

....保護:保護されたアクセス修飾子は少しトリッキーであり、デフォルトのアクセス修飾子のスーパーセットと言えます。保護されたメンバーは、同じパッケージ内のアクセスに関する限り、デフォルトのメンバーと同じです。違いは、保護されたメンバーは、親クラスが存在するパッケージの外部にある、メンバーが宣言されているクラスのサブクラスにもアクセスできることです。

しかし、これらの保護されたメンバーは、「継承を通じてのみパッケージの外部からアクセスできます」。つまり、メンバーがサブクラス自体に存在するかのように、他のパッケージに存在するサブクラスのクラスの保護されたメンバーに直接アクセスできます。ただし、その保護されたメンバーは、親クラスの参照を使用して、パッケージ外のサブクラスでアクセスできなくなります。....


これを追加するだけです。「子が親クラスの保護されたメンバーにアクセスすると、サブクラスのプライベート(またはサブクラスのサブクラスによって継承できる特別なプライベートメンバー)メンバーになります。」
Anand

9

Davidの答えは、各アクセス修飾子の意味を提供します。それぞれをいつ使用するかについては、外部で使用するためのすべてのクラスと各クラスのメソッド(そのAPI)、およびその他すべてを非公開にすることをお勧めします。

時間の経過とともに、一部のクラスをパッケージプライベートにする時期、およびサブクラスで使用するために保護された特定のメソッドを宣言する時期についての感覚を養います。


6

注:これは受け入れられた回答の単なる補足です。

これは、Java Access Modifiersに関連しています。

Java Access Modifiersから:

Javaアクセス修飾子は、特定のクラスとそのフィールド、コンストラクター、およびメソッドにアクセスできるクラスを指定します。アクセス修飾子は、クラス、そのコンストラクター、フィールド、およびメソッドに対して個別に指定できます。Javaアクセス修飾子は、日常のスピーチではJavaアクセス修飾子とも呼ばれますが、正しい名前はJavaアクセス修飾子です。クラス、フィールド、コンストラクター、およびメソッドは、4つの異なるJavaアクセス修飾子の1つを持つことができます。

  • リストアイテム
  • 民間
  • デフォルト(パッケージ)
  • 保護された
  • 公衆

アクセスの制御からクラスのメンバーへのチュートリアル:

アクセスレベル修飾子は、他のクラスが特定のフィールドを使用したり、特定のメソッドを呼び出したりできるかどうかを決定します。アクセス制御には2つのレベルがあります。

  • トップレベル-パブリック、またはパッケージプライベート(明示的な修飾子なし)。
  • メンバーレベル-public、private、protected、またはpackage-private(明示的な修飾子なし)。

クラスは修飾子publicで宣言できます。その場合、そのクラスはどこにいてもすべてのクラスに表示されます。クラスに修飾子がない場合(デフォルト、package-privateとも呼ばれます)、それはそれ自体のパッケージ内でのみ表示されます

次の表は、各修飾子によって許可されるメンバーへのアクセスを示しています。

╔═════════════╦═══════╦═════════╦══════════╦═══════╗
 Modifier     Class  Package  Subclass  World 
╠═════════════╬═══════╬═════════╬══════════╬═══════╣
 public       Y      Y        Y         Y     
 protected    Y      Y        Y         N     
 no modifier  Y      Y        N         N     
 private      Y      N        N         N     
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

最初のデータ列は、クラス自体がアクセスレベルで定義されたメンバーにアクセスできるかどうかを示します。ご覧のとおり、クラスは常に自分のメンバーにアクセスできます。2列目は、クラスと同じパッケージ内のクラス(その親子関係に関係なく)がメンバーにアクセスできるかどうかを示します。3番目の列は、このパッケージの外部で宣言されたクラスのサブクラスがメンバーにアクセスできるかどうかを示します。4番目の列は、すべてのクラスがメンバーにアクセスできるかどうかを示します。

アクセスレベルは2つの方法であなたに影響を与えます。まず、Javaプラットフォームのクラスなど、別のソースからのクラスを使用する場合、アクセスレベルによって、独自のクラスが使用できるそれらのクラスのメンバーが決まります。第2に、クラスを作成するときは、クラス内のすべてのメンバー変数とすべてのメソッドが持つべきアクセスレベルを決定する必要があります。


1
補足とは正確には何ですか、なぜそれが既存の投稿の編集ではないのですか?
2016年

補足はアクセス修飾子です。なぜ編集しないのですか?歴史的な目的のために受け入れられた答えを変更せずに保ち、私の答えを与えるため。
ישואוהבאותך

5

Public Protected DefaultおよびPrivateはアクセス修飾子です。

これらは、カプセル化、またはクラスのコンテンツを非表示および表示するためのものです。

  1. クラスはパブリックまたはデフォルトにすることができます
  2. クラスメンバーは、パブリック、保護、デフォルト、またはプライベートにすることができます。

Privateはクラス外ではアクセスできませんDefaultはパッケージ内でのみアクセスできます。パッケージとそれを拡張するクラスで保護されています。すべての人に公開されています。

通常、メンバー変数はプライベートに定義されていますが、メンバーメソッドはパブリックです。


Defaultはアクセス修飾子ではなく、他の2つはスペルミスです。
ローンの侯爵

5

多くの場合、あらゆる言語の基本的な概念を思い出すことが、現実世界のアナロジーを作成することで可能になることに気づきました。Javaのアクセス修飾子を理解するための私の類推は次のとおりです。

あなたが大学の学生で、週末にあなたを訪ねてくる友人がいるとします。キャンパスの真ん中に大学の創設者の大きな像があるとしよう。

  • 彼をキャンパスに連れて行くと、あなたとあなたの友人が最初に目にするのはこの像です。つまり、キャンパス内を歩く人は誰でも、大学の許可なしに像を見ることができます。これにより、像はPUBLICになります。

  • 次に、友達を寮に連れて行きたいのですが、そのためには、彼を訪問者として登録する必要があります。これは、彼がキャンパス内のさまざまな建物に入るためのアクセスパス(あなたと同じ)を取得することを意味します。これにより、彼のアクセスカードはPROTECTEDになります

  • 友達がキャンパスWiFiにログインしたいのですが、ログインするための資格情報がありません。彼がオンラインになる唯一の方法は、あなたが彼とログインを共有することです。(覚えておいてください、大学に通うすべての学生はこれらのログイン資格情報も持っています)。これにより、ログイン資格情報がNO MODIFIERになります。

  • 最後に、あなたの友人は、ウェブサイトに掲載されている学期の進捗レポートを読みたいと考えています。ただし、キャンパスWebサイトのこのセクションにアクセスするには、すべての学生が自分の個人ログインを持っています。これにより、これらの資格がPRIVATEになります。

お役に立てれば!


4

アクセス修飾子について考えているときは、このように考えてください(変数メソッドの両方に適用されます)。

public->すべての場所からアクセス可能->
private宣言されている同じクラス内でのみアクセス可能

それが来るとき今、混乱が生じたdefaultprotected

default->アクセス修飾子キーワードがありません。つまり、クラスのパッケージ内でのみ使用できます。どこにもそのパッケージの外にはアクセスできません。

protected-> 宣言されてdefaultいるパッケージの外部のサブクラスからアクセスできる同じパッケージクラスよりも少し厳しく、それとは別に。


4

Javaアクセスは使用できるものを変更します

ここに画像の説明を入力してください

アクセス修飾子はclassfield[概要]、に適用できますmethod。これにアクセス、サブクラス化、またはオーバーライドしてみてください。

  • へのアクセスfieldまたはmethodを介したアクセスclass
  • 継承。後続class(サブクラス)アクセス修飾子は任意です。後続method(オーバーライド)アクセス修飾子は同じであるか、それを拡張する必要があります

トップレベルのクラス(第1レベルのスコープ)は、publicおよびにすることができますdefaultNested class[概要]はそれらのいずれかを持つことができます

package パッケージ階層には適用されません

Swiftアクセス修飾子


2

それはすべてカプセル化に関するものです(またはJoe Phillipsが述べたように、最低限の知識)。

最も制限の厳しい(プライベート)から始めて、後で制限の少ない修飾子が必要かどうかを確認します。

私たちは皆、private、publicなどのメソッド修飾子とメンバー修飾子を使用していますが、開発者が少なすぎることの1つは、パッケージを使用してコードを論理的に編成することです。

たとえば、機密性の高いセキュリティメソッドを「セキュリティ」パッケージに入れることができます。次に、セキュリティ関連のコードの一部にアクセスするパブリッククラスをこのパッケージに入れますが、他のセキュリティクラスパッケージはプライベートにします。したがって、他の開発者はこのパッケージの外部からパブリックに利用可能なクラスのみを使用できます(修飾子を変更しない限り)。これはセキュリティ機能ではありませんが、使用方法をガイドします。

Outside world -> Package (SecurityEntryClass ---> Package private classes)

もう1つは、相互に大きく依存するクラスが同じパッケージになってしまい、依存関係が強すぎると、最終的にリファクタリングまたはマージされる可能性があることです。

逆に、すべてをパブリックとして設定すると、何にアクセスすべきか、何にアクセスすべきでないかが明確になりません。そのため、多くのjavadocが作成される可能性があります(コンパイラを介して何も強制されません...)。


2

private-protected-public-perfect-analogy-for-the-variable-data-types

次のブロック図は、派生クラスアクセスモードがプライベートの場合に、基本クラスのデータメンバーがどのように継承されるかを説明しています。

ここに画像の説明を入力してください

注:プライベートアクセス指定子を使用してデータメンバーを宣言することは、データ非表示と呼ばれます。

出典:アクセス指定子–プライベート、パブリック、保護


1
問題はC ++ではなくJavaに関するものでした。
ブノワ

1
@Benoitしかし、私が投稿したもの、特別な写真は、:javaとc ++の両方で同じではありませんか?このルールはjavaにも適用されませんか?感謝
leonidaa

2
C ++では3つの修飾子しかないのに対し、Javaには4つあります。
Benoit

1
類推は良いですが、デフォルトのアクセス指定子がありません
mss

1
OPは、「Javaのパブリック、保護、パッケージプライベート、プライベートの違いは何ですか?」
JL_SO

2

私の2セント:)

民間:

クラス->トップレベルのクラスをプライベートにすることはできません。内部クラスはプライベートにすることができ、同じクラスからアクセスできます。

インスタンス変数->クラスでのみアクセス可能。クラス外にはアクセスできません。

パッケージプライベート:

クラス->トップレベルのクラスは、パッケージプライベートにすることができます。同じパッケージからのみアクセスできます。サブパッケージからではなく、外部パッケージからではありません。

インスタンス変数->同じパッケージからアクセス可能。サブパッケージからではなく、外部パッケージからではありません。

保護:

クラス->トップレベルのクラスは保護できません。

インスタンス変数->同じパッケージまたはサブパッケージでのみアクセスできます。クラスの拡張中は、パッケージの外部にのみアクセスできます。

公衆:

クラス->パッケージ/サブパッケージ/別のパッケージからアクセス可能

インスタンス変数->パッケージ/サブパッケージ/別のパッケージからアクセス可能

詳細な回答はこちら

https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md


1
  • 公衆

    クラスメンバーがpublicで宣言されている場合、どこからでもアクセスできます

  • 保護された

    クラスメンバーがキーワードprotectedで宣言されている場合、同じクラスメンバー、同じパッケージ内のクラスメンバーの外部、および継承されたクラスメンバーからアクセスできます。クラスメンバーが保護されている場合、外部のパッケージクラスが継承されない限り、つまり他のパッケージのスーパークラスを拡張しない限り、外部のクラスからアクセスできません。ただし、保護されたクラスメンバーは常に同じパッケージクラスで利用できます。同じパッケージクラスが継承されているかどうかは関係ありません。

  • デフォルト

    Javaでは、デフォルトはアクセス修飾子キーワードではありません。クラスメンバーがアクセス修飾子キーワードなしで宣言されている場合、この場合はデフォルトのメンバーと見なされます。デフォルトのクラスメンバーは、同じパッケージクラスメンバーが常に使用できます。ただし、外部クラスが保護されたメンバーとは異なりサブクラスであっても、外部パッケージクラスメンバーはデフォルトのクラスメンバーにアクセスできません

  • 民間

    クラスメンバーがキーワードprotectedで宣言されている場合、この場合、同じクラスメンバーのみが使用できます。


-1

Javaのアクセス指定子:Javaには4つのアクセス指定子があります。つまり、private、package-private(デフォルト)、protected、publicであり、アクセス順が大きくなっています。

プライベート:あるクラスを開発していて、このクラスのメンバーがこのクラスの外部に公開されないようにしたい場合は、プライベートとして宣言する必要があります。プライベートメンバーは、それらが定義されているクラス(つまり、包含クラス)でのみアクセスできます。プライベートメンバーには、「this」参照およびこれらのメンバーを含むクラスの他のインスタンスでもアクセスできますが、このクラスの定義内でのみアクセスできます。

Package-private(デフォルト):このアクセス指定子は、以下で説明するアクセスに加えて、プライベートアクセス指定子によって指定されたアクセスを提供します。

一部のパッケージ、したがってその中の一部のクラス(たとえばClass1)を開発している場合、デフォルト(明示的に言及する必要はありません)アクセス指定子を使用して、クラス内のメンバーを(同じ)パッケージ内の他のクラスに公開できます。これらの他のクラス(同じパッケージ内)では、Class1のインスタンスでこれらのデフォルトメンバーにアクセスできます。また、Class1のサブクラス内でこれらのデフォルトメンバーにアクセスすることもできます(この参照上、またはClass1のインスタンス上、またはClass2のインスタンス上)。

基本的に、同じパッケージ内で、クラスのインスタンスのデフォルトメンバー、またはサブクラスの「this」参照にアクセスできます。

protected:このアクセス指定子は、以下で説明するアクセスに加えて、package-privateアクセス指定子によって指定されたアクセスを提供します。

一部のパッケージを開発しているため、その中にあるクラス(たとえばClass1)を開発しているときに、このメンバーにパッケージの外部からアクセスしたくない場合(たとえば、パッケージ(つまり、APIを使用しているクライアント)が一般的ですが、クライアントがClass1を拡張するClass2と言うクラスを書き込む場合にのみ、例外を作成し、このメンバーへのアクセスを許可します。したがって、一般に、保護されたメンバーは、派生クラス、つまりClass2の「this」参照でアクセスでき、Class2の明示的なインスタンスでもアクセスできます。

ご注意ください:

  1. Class1の明示的なインスタンスでアクセスしようとすると、Class2のClass1の継承された保護メンバーにアクセスできますが、継承されているメンバーにはアクセスできません。
  2. Class2を拡張する同じ/異なるパッケージ内に別のクラスClass3を書き込む場合、Class1の保護されたメンバーは、この参照およびClass3の明示的なインスタンスでアクセスできます。これは、拡張された階層にも当てはまります。つまり、保護されたメンバーは、この参照または拡張クラスのインスタンスで引き続きアクセスできます。Class3では、Class2のインスタンスを作成すると、継承されますが、Class1から保護されたメンバーにアクセスできなくなります。

つまり、他のパッケージの保護されたメンバーにアクセスできるのは、この他のパッケージのクラスがこの保護されたメンバーを含むクラスを拡張し、保護されたメンバーが「this」参照または拡張クラスの明示的なインスタンスで、拡張の定義内でアクセスされる場合のみです。クラス。

public:このアクセス指定子は、下記のアクセスに加えて、保護されたアクセス指定子によって指定されたアクセスを提供します。

あるパッケージを開発し、その中にあるクラス(たとえばClass1)を開発しているときに、他のクラスで作成されたClass1のインスタンスの他のパッケージでこのメンバーにアクセスできるようにする場合は、Class1内のデータメンバーにパブリックアクセス指定子を使用する必要があります。パッケージ。基本的に、このアクセス指定子は、データメンバーを条件なしで世界に公開する場合に使用する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.