java - 違い - パッケージプライベート 使いどころ




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

プライベート

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

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

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

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

注意

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

保護された

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

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

メソッド、フィールドはprotectedとして宣言できますが、インターフェースのメソッドとフィールドはprotectedとして宣言できません。

注意

保護されたアクセスは、サブクラスにヘルパーメソッドまたは変数を使用する機会を与え、関連しないクラスがそれを使用しないようにします。

パブリック

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

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

  • 異なるパッケージ

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

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

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

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

  • 同じパッケージ内

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

注意

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

関連アンサー

参照リンク

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

Javaでは、アクセス修飾子、つまりデフォルト(パッケージプライベート)、 publicprotectedprivate各アクセス修飾子を使用するタイミングについて明確なルールがありますか? classinterfaceを作成し、継承を処理しますか?


Javaで最も誤解を招くアクセス修飾子がprotectedます。 サブクラスがそれを見ることができる1つの例外を除いて、デフォルトの修飾子に似ていることはわかっています。 しかしどうですか? 混乱をはっきりと明らかにする例を以下に示します。

  • 私たちは2つのクラスを持っていると仮定します。 FatherSonはそれぞれ独自のパッケージになっています:

    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
          }
      }
      

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

            │ Class │ Package │ Subclass │ Subclass │ World
            │       │         │(same pkg)│(diff pkg)│ 
────────────┼───────┼─────────┼──────────┼──────────┼────────
public      │   +   │    +    │    +     │     +    │   +     
────────────┼───────┼─────────┼──────────┼──────────┼────────
protected   │   +   │    +    │    +     │     +    │         
────────────┼───────┼─────────┼──────────┼──────────┼────────
no modifier │   +   │    +    │    +     │          │    
────────────┼───────┼─────────┼──────────┼──────────┼────────
private     │   +   │         │          │          │    

+ : accessible
blank : not accessible

このページは、保護された&defaultアクセス修飾子について書いています

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

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


プライベート :限定クラスへのアクセスが制限されています

デフォルト(修飾子なし) :クラスとパッケージへのアクセスが制限されています

プロテクト :クラス、パッケージ、サブクラス(パッケージの内部と外部の両方)へのアクセスが制限されています。

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


Public Protectedデフォルトとプライベートはアクセス修飾子です。

カプセル化、クラスの内容の表示と非表示を目的としています。

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

プライベートはクラス外ではアクセスできません。デフォルトはパッケージ内でのみアクセス可能です。パッケージ内で保護されているクラスと、それを継承するクラスです。すべての人が公開されています。

通常、メンバー変数はprivateに定義されますが、メンバーメソッドはpublicです。


その違いは、既に提供されているリンクで見つけることができますが、どちらが使用されるかは、通常、「最小知識の原則」になります。 必要な可視性を最小限に抑えます。


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

パブリック:基本的には、同じパッケージ内にあるかどうかにかかわらず、どのクラスからでもアクセスできるように簡単です。

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

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

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

Protected:同じパッケージ内の変数にアクセスすることも、他のパッケージ内のサブクラスにアクセスすることもできます。 基本的にはdefault + Inheritedの動作です。

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

非公開:同じクラスにアクセスできます。

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


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

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

概要

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

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

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

ローカル変数と仮パラメータはアクセス指定子を取ることができません。 スコープ規則に従って本質的に外部にアクセスすることはできないため、効果的には非公開です。

トップスコープのクラスでは、 publicとpackage-privateのみが許可されます。 この設計選択はおそらく、 protected privateはパッケージレベルで冗長である(パッケージの継承はない)ためです。

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

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

注文

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

public> protected> package-private> private

これは、 publicアクセスを最も多く提供し、 private最小限に抑えることを意味します。 プライベートメンバーで可能な参照は、パッケージプライベートメンバーに対しても有効です。 パッケージプライベートメンバーへの参照は、保護されたメンバーに対して有効です。 (保護されたメンバーへのアクセスを同じパッケージ内の他のクラスに与えることは間違いとみなされていました)。

ノート

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

内部クラス

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

ただし、これは非常に複雑で、詳細は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

関連するいくつかの質問:


簡単なルール。 すべてのプライベートを宣言することから始めます。 そして、必要に応じて一般に向けて進め、設計はそれを保証する。

エクスプレッションの選択肢や抽象化の選択肢が公開されているかどうかを尋ねるメンバーは、自分自身に尋ねます。 最初のものは、観察可能な振舞いではなく、実際の表現にあまりにも多くの依存性を導入するため、避けたいものです。

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

また、オーバーライド時に@Overrideアノテーションを使用して、リファクタリング時に物事が壊れないようにします。


非常に短い

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

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

時間の経過と共に、いくつかのクラスをパッケージプライベートにするときと、サブクラスで使用するために保護された特定のメソッドを宣言するときの感覚を開発します。


それはすべてカプセル化に関するものです(またはJoe Phillips氏が述べたように、知識ほとんどありません)。

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

私たちはすべてprivateやpublicなどのメソッドとメンバの修飾子を使用しますが、コードを論理的に整理するためのパッケージを使用するのはあまり開発者がほとんどありません。

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

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

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

逆に、すべてをpublicとして設定すると、アクセスする必要があるかどうかが分かりません。javadoc(コンパイラを介して何も強制しない...)を書くことにつながる可能性があります。


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

public- どこからでもアクセス可能 - >
private宣言されている同じクラス内でのみアクセス可能

今、混乱はdefaultprotected

default - >アクセス修飾子キーワードがありません。これは、クラスのパッケージ内で厳密に利用可能であることを意味します。そのパッケージの外にどこにでもアクセスできます。

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


私はこのページのほとんどの回答を含め、非常に一般的に間違っている詳細に対処したいだけです。「デフォルト」アクセス(アクセス修飾子がない場合)は、必ずしもpackage-privateと同じではありません。それは何があるかによって異なります。

  • 非メンバ型(つまり、別の型の中で宣言されていないクラス、列挙型、インタフェース、および注釈型)は、デフォルトではpackage-privateです。(JLS§6.6.1

  • クラスメンバとコンストラクタは、デフォルトではパッケージプライベートです。(JLS§6.6.1

  • Enumコンストラクタはデフォルトでプライベートです。(実際に列挙型のコンストラクタ非公開でなければならず、それらを公開または保護しようとするのは誤りです)。Enum定数はpublicであり、アクセス指定子は許可されません。enumの他のメンバーはデフォルトでpackage-privateです。(JLS§8.9

  • インタフェースおよび注釈タイプのすべてのメンバーは、デフォルトでパブリックです。(実際には、インターフェースとアノテーションのタイプのメンバーは公開されていなければならず、非公開または保護されるようにするのは誤りです。)(JLS§9.3〜9.5


                | 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         |       ✔       |     ✘     |       ✘       |   ✘    






access-modifiers