private 자바 - 공용, 보호, 패키지 개인 및 개인 Java의 차이점은 무엇입니까?




접근 (21)

자바에서는 classinterface 를 만들고 상속을 처리하면서 각 액세스 수정 자, 즉 기본 (패키지 개인), public , protectedprivate 각 사용시기에 대한 명확한 규칙이 있습니까?


Answers

종종 어떤 언어의 기본 개념을 기억하는 것이 현실 세계의 유추를 만들어 냄으로써 가능하다는 것을 깨달았습니다. 다음은 Java에서 액세스 한정자를 이해하는 비유입니다.

당신이 대학의 학생이고 주말에 당신을 방문 할 친구가 있다고 가정합시다. 캠퍼스 중간에 대학 설립자의 큰 동상이 있다고 가정 해보십시오.

  • 캠퍼스로 데려 갈 때, 당신과 당신의 친구가 보는 첫 번째 것이이 상입니다. 즉, 캠퍼스를 걸어 다니는 사람은 대학의 허가없이 동상을 볼 수 있습니다. 이것은 동상을 PUBLIC으로 만듭니다 .

  • 다음으로, 당신은 당신의 기숙사에 친구를 데려 가고 싶지만, 당신은 그를 방문객으로 등록해야합니다. 이것은 그가 캠퍼스의 여러 건물에 들어가기 위해 액세스 패스 (귀하와 동일)를 얻는다는 것을 의미합니다. 이렇게하면 그의 액세스 카드가 보호됨을 알 수 있습니다.

  • 친구가 캠퍼스 WiFi에 로그인하려고하지만 자격 증명이 없습니다. 그가 온라인으로 접속할 수있는 유일한 방법은 당신이 그 사람과 당신의 로그인을 공유하는 것입니다. (대학에 다니는 모든 학생들도이 로그인 자격증 명을 가지고 있음을 기억하십시오). 그러면 로그인 자격 증명이 NO MODIFIER로 설정 됩니다.

  • 마지막으로 친구가 웹 사이트에 게시 된 학기에 대한 성적표를 읽길 원합니다. 그러나 모든 학생들은 캠퍼스 웹 사이트의이 섹션에 액세스하기 위해 개인 로그인을 가지고 있습니다. 이렇게하면이 신임장이 PRIVATE가 됩니다.

희망이 도움이!


실제로는 간단한 그리드 쇼보다 약간 더 복잡합니다. 그리드는 액세스가 허용되는지 여부를 알려주지 만 액세스를 정확하게 구성하는 것은 무엇입니까? 또한 액세스 수준은 복잡한 방식으로 중첩 클래스 및 상속과 상호 작용합니다.

"기본"액세스 (키워드 없음으로 지정)는 package-private 이라고도 package-private . 예외 : 인터페이스에서 수정자는 공용 액세스를 의미하지 않습니다. 공개 이외의 수식어는 금지됩니다. 열거 형 상수는 항상 공개됩니다.

개요

이 액세스 지정자가있는 멤버에 대한 액세스가 허용됩니까?

  • 멤버가 private 임 : 멤버가 호출 코드와 동일한 클래스 내에 정의 된 경우에만.
  • 멤버는 패키지 전용입니다. 호출 코드가 멤버의 바로 묶는 패키지 내에있는 경우에만.
  • Member is protected : 같은 패키지이거나 멤버가 호출 코드를 포함하는 클래스의 수퍼 클래스에 정의되어있는 경우.
  • 회원은 public . 예.

어떤 액세스 지정자가에 적용됩니까?

지역 변수 및 형식 매개 변수는 액세스 지정자를 사용할 수 없습니다. 범위 규칙에 따라 외부에 본질적으로 접근 할 수 없기 때문에 사실상 사적입니다.

최고 범위에있는 클래스의 경우 public 및 패키지 개인 만 허용됩니다. 이 디자인 선택은 protected 되고 private 이 패키지 수준에서 중복되므로 (패키지의 상속이 없음) 아마도 그럴 것입니다.

모든 액세스 지정자는 클래스 멤버 (생성자, 메서드 및 정적 멤버 함수, 중첩 클래스)에서 사용할 수 있습니다.

관련 항목 : Java 클래스 내게 필요한 옵션

주문

액세스 지정자는 엄격하게 명령 할 수 있습니다.

public> protected> package-private> private

public 이 가장 많은 액세스를 제공하고 private 는 가장 적은 것을 의미합니다. 비공개 멤버에 대해 가능한 모든 참조는 패키지 비공개 멤버에게도 유효합니다. package-private 멤버에 대한 참조는 보호 된 멤버에서 유효하며, 등등. (보호 된 멤버에게 동일한 패키지의 다른 클래스에 대한 액세스 권한 부여는 실수로 간주되었습니다.)

노트

  • 클래스의 메소드 같은 클래스의 다른 객체의 private 멤버에 액세스 할 수 있습니다. 보다 정확하게는, 클래스 C의 메소드는 C의 서브 클래스의 오브젝트에 대해 C의 전용 멤버에 액세스 할 수 있습니다. Java는 클래스에 의해서만 인스턴스에 의한 액세스를 제한하는 것을 지원하지 않습니다. ( private[this] 사용하여 스칼라를 지원합니다.)
  • 객체를 생성하려면 생성자에 액세스해야합니다. 따라서 모든 생성자가 private 인 경우 클래스는 클래스 내에있는 코드 (일반적으로 정적 팩터 리 메서드 또는 정적 변수 초기화 프로그램)로만 생성 할 수 있습니다. 패키지 전용 또는 보호 된 생성자에 대해서도 마찬가지입니다.
    • 전용 생성자 만 있으면 클래스가 외부 적으로 서브 클래 싱 될 수 없음을 의미합니다. Java는 서브 클래스의 생성자가 암시 적으로 또는 명시 적으로 수퍼 클래스 생성자를 호출해야하기 때문에 클래스를 외부 적으로 서브 클래 싱 할 수 없음을 의미합니다. 그러나 하위 클래스가 포함 된 중첩 클래스를 포함 할 수 있습니다.

내부 수업

또한 내부 클래스와 같이 중첩 된 범위를 고려해야합니다. 복잡성의 예로 내부 클래스에는 멤버가 있으며 액세스 수정자를 사용할 수 있습니다. 그래서 당신은 public 멤버와 함께 private 클래스를 가질 수 있습니다; 회원이 액세스 할 수 있습니까? (아래 참조) 일반적으로 범위를보고 재귀 적으로 생각하여 각 수준에 액세스 할 수 있는지 확인해야합니다.

그러나 이것은 매우 복잡하며 자세한 내용 은 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 주석을 사용하면 리팩터링 할 때 상황이 깨지지 않도록 할 수 있습니다.


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

비공개 : 수업에만 제한적으로 액세스

기본값 (수정 자 없음) : 클래스 및 패키지에 대한 제한된 액세스

보호 : 클래스, 패키지 및 하위 클래스 (내부 및 외부 패키지 모두)에 대한 제한된 액세스

Public : 클래스, 패키지 (모두) 및 하위 클래스에 액세스 할 수 있습니다 ... 간단히 말해서, 모든 곳에서.


그것은 캡슐화 에 관한 모든 것입니다 (또는 Joe Phillips가 말한 것처럼, 최소한의 지식 ).

가장 제한적인 (개인) 것으로 시작하고 나중에 덜 제한적인 수식어가 필요한지 확인하십시오.

우리 모두는 private, public 같은 메서드와 멤버 수정자를 사용합니다.하지만 너무 적은 개발자가 사용하는 패키지는 논리적으로 코드 를 구성 하는 데 사용되는 패키지 입니다.

예 : 민감한 보안 방법을 '보안'패키지에 넣을 수 있습니다. 그런 다음이 패키지의 보안 관련 코드 중 일부에 액세스하는 public 클래스를 삽입하고 다른 보안 클래스 패키지는 private로 유지 합니다 . 따라서 다른 개발자는 수정자를 변경하지 않는 한이 패키지 외부에서 공개적으로 사용 가능한 클래스 만 사용할 수 있습니다. 이것은 보안 기능이 아니지만 사용법 을 안내 합니다.

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

또 다른 한 가지는 서로에 많이 의존하는 클래스가 동일한 패키지로 끝날 수 있고 종속성이 너무 강하면 결국 리팩터링되거나 병합 될 수 있다는 것입니다.

반대로 모든 것을 공개 로 설정하면 액세스해야 할 대상과 사용하지 말아야 할 대상이 명확하지 않으므로 많은 javadoc (컴파일러를 통해 시행하지는 않음)을 작성할 수 있습니다.


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();
  }
}

출력 : Hello

3. 비공개

동일한 클래스 내에서만 액세스 할 수 있습니다.

한 클래스의 private 멤버에 다른 클래스에 액세스하려고하면 컴파일 오류가 발생합니다. 예를 들어,

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();
  }
}

출력 : Hello


그 차이점은 이미 제공된 링크에서 찾을 수 있지만 일반적으로 사용하는 링크는 "최소 지식의 원칙"에 있습니다. 필요한 최소한의 가시성 만 허용하십시오.


액세스 한정자는 여러 수준에서 액세스를 제한합니다.

Public : 기본적으로 모든 클래스에서 동일한 패키지에 있는지 여부에 관계없이 액세스 할 수 있습니다.

액세스 할 수있는 패키지가 동일한 패키지에 있다면 직접 액세스 할 수 있지만 다른 패키지에 있으면 클래스의 객체를 만들 수 있습니다.

기본값 : 모든 패키지 클래스의 동일한 패키지에서 액세스 할 수 있습니다.

액세스하려면 클래스의 개체를 만들 수 있습니다. 그러나이 변수는 패키지 외부에서 액세스 할 수 없습니다.

보호 : 다른 패키지의 서브 클래스는 물론 동일한 패키지의 변수에 액세스 할 수 있습니다. 그래서 기본적으로 default + Inherited behavior입니다.

기본 클래스에 정의 된 보호 필드에 접근하기 위해서 하위 클래스의 객체를 생성 할 수 있습니다.

비공개 : 동일한 클래스에서 액세스 할 수 있습니다.

비 정적 메서드에서는 참조 (생성자에서도) 때문에 직접 액세스 할 수 있지만 정적 메서드에 액세스하려면 클래스의 개체를 만들어야합니다.


참고 : 이것은 단지 허용 된 답변을 보충 하기위한 것입니다.

이것은 Java Access Modifiers 와 관련이 있습니다.

에서 자바 액세스 수정 :

Java 액세스 수식자는, 어느 클래스가 지정된 클래스, 그 필드, 생성자 및 메소드에 액세스 할 수 있는지를 지정합니다. 액세스 수정자는 클래스, 해당 생성자, 필드 및 메소드에 대해 개별적으로 지정할 수 있습니다. Java 액세스 수정자는 일별 음성에서 Java 액세스 지정자라고도하지만 올바른 이름은 Java 액세스 수정 자입니다. 클래스, 필드, 생성자 및 메소드는 네 가지 다른 Java 액세스 수정 자 중 하나를 가질 수 있습니다.

  • 목록 항목
  • 은밀한
  • 기본값 (패키지)
  • 보호 된
  • 공공의

클래스 구성원에 대한 액세스 제어 에서 자습서 :

액세스 수준 수정자는 다른 클래스가 특정 필드를 사용하거나 특정 메서드를 호출 할 수 있는지 여부를 결정합니다. 액세스 제어에는 두 가지 레벨이 있습니다.

  • 최상위 - 공개 또는 패키지 - 개인 (명시 적 수정 자 없음).
  • 멤버 레벨 - 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     ║
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

첫 번째 데이터 열은 클래스 자체가 액세스 수준에 의해 정의 된 멤버에 액세스 할 수 있는지 여부를 나타냅니다. 보시다시피 클래스는 항상 자체 멤버에 액세스 할 수 있습니다. 두 번째 열은 클래스와 동일한 패키지의 클래스가 해당 패밀리에 관계없이 해당 멤버에 액세스 할 수 있는지 여부를 나타냅니다. 세 번째 열은이 패키지 외부에서 선언 된 클래스의 하위 클래스가 멤버에 액세스 할 수 있는지 여부를 나타냅니다. 네 번째 열은 모든 클래스가 멤버에 액세스 할 수 있는지 여부를 나타냅니다.

액세스 수준은 두 가지면에서 영향을줍니다. 우선, Java 플랫폼의 클래스와 같은 다른 소스에서 가져온 클래스를 사용할 때 액세스 수준에 따라 클래스에서 사용할 수있는 클래스의 멤버가 결정됩니다. 둘째, 클래스를 작성할 때 모든 멤버 변수와 클래스의 모든 메소드가 가져야하는 액세스 레벨을 결정해야합니다.


이 페이지의 대부분의 답변을 포함하여 매우 일반적으로 잘못된 세부 정보를 다루기를 원합니다. "기본"액세스 (액세스 한정자가없는 경우)는 package-private과 항상 같지는 않습니다 . 그것은 무엇이 무엇인지에 달려 있습니다.

  • 비 멤버 형 (즉, 클래스, enums, 인터페이스, 및 다른 형 내에 선언되어 있지 않은 주석 형)은 디폴트로 package-private입니다. ( JLS §6.6.1 )

  • 클래스 멤버와 생성자는 기본적으로 패키지 전용입니다. ( JLS §6.6.1 )

  • 열거 형 생성자는 기본적으로 비공개 입니다. 실제로 열거 형 (enum) 생성자 비공개 여야 하며 공용 또는 보호 대상으로 설정하는 것은 오류입니다. 열거 형 상수는 public이며 액세스 지정자를 허용하지 않습니다. 열거 형의 다른 멤버는 기본적으로 package-private입니다. ( JLS §8.9 )

  • 인터페이스 및 주석 유형의 모든 멤버는 기본적으로 public 입니다. (사실, 인터페이스 및 주석 유형의 구성원이 있어야 공개하고, 그들이 개인 또는 보호를 만들려고하면 오류가 발생합니다.) ( 9.5 JLS §9.3 )


은밀한

  • 메소드, 변수 및 생성자

private로 선언 된 메소드, 변수 및 생성자는 선언 된 클래스 자체 내에서만 액세스 할 수 있습니다.

  • 클래스 및 인터페이스

개인 액세스 수정자는 가장 제한적인 액세스 레벨입니다. 클래스와 인터페이스는 private 일 수 없습니다.

노트

공용 getter 메서드가 클래스에 있으면 private로 선언 된 변수를 클래스 외부에서 액세스 할 수 있습니다. 수퍼 클래스에서 보호 된 것으로 선언 된 변수, 메서드 및 생성자는 다른 패키지의 하위 클래스 또는 보호 된 멤버 클래스의 패키지 내의 모든 클래스에서만 액세스 할 수 있습니다.

보호 된

  • 클래스 및 인터페이스

보호 된 액세스 수정자는 클래스 및 인터페이스에 적용 할 수 없습니다.

메소드, 필드는 protected로 선언 할 수 있지만 인터페이스의 메소드와 필드는 protected로 선언 할 수 없습니다.

노트

보호 된 액세스는 하위 클래스가 도우미 메서드 또는 변수를 사용할 수있는 기회를 제공하고 관련없는 클래스가이를 사용하지 못하게합니다.

공공의

공용으로 선언 된 클래스, 메소드, 생성자, 인터페이스 등은 다른 클래스에서 액세스 할 수 있습니다.

따라서 공용 클래스 내에서 선언 된 필드, 메소드, 블록은 Java Universe에 속한 모든 클래스에서 액세스 할 수 있습니다.

  • 다른 패키지

그러나 우리가 액세스하려고하는 public 클래스가 다른 패키지에 있으면 public 클래스를 가져와야합니다.

클래스 상속 때문에 클래스의 모든 공용 메서드와 변수는 하위 클래스에 상속됩니다.

기본 없음 - 키워드 :

기본 액세스 수정자는 클래스, 필드, 메소드 등에 대한 액세스 한정자를 명시 적으로 선언하지 않음을 의미합니다.

  • 동일한 패키지 내에서

액세스 제어 수정 자없이 선언 된 변수 또는 메소드는 동일한 패키지의 다른 클래스에서 사용할 수 있습니다. 인터페이스의 필드는 암시 적으로 public static final이며 인터페이스의 메서드는 기본적으로 public입니다.

노트

정적 필드를 오버라이드 할 수 없습니다. 오버라이드를 시도하면 오류가 표시되지 않지만 우리는 무엇을 제외하고는 작동하지 않습니다.

관련 답변

참조 링크

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


액세스 수정자를 생각할 때 이런 식으로 생각하면됩니다 ( 변수메소드 모두에 적용됨 ).

public-> 모든 곳에서 액세스 가능
private-> 선언 된 동일한 클래스 내에서만 액세스 가능

이에 관해서 이제 혼란이 발생 default하고protected

default-> 액세스 수정 자 키워드가 없습니다. 이는 클래스의 패키지 내에서 엄격하게 사용할 수 있음을 의미합니다. 그 패키지 밖에서는 아무 것도 액세스 할 수 없습니다.

protected-> default동일한 패키지 클래스 보다 약간 더 엄격 하고 덜 엄격 합니다. 선언 된 패키지 외부의 하위 클래스에서 액세스 할 수 있습니다 .


  • 공개 - 응용 프로그램의 어느 곳에서나 액세스 할 수 있습니다.

  • 기본값 - 패키지에서 액세스 할 수 있습니다.

  • protected - 다른 패키지의 패키지 및 하위 클래스에서 액세스 할 수 있습니다. 게다가

  • 비공개 - 해당 클래스에서만 액세스 할 수 있습니다.


David의 대답은 각 액세스 수정 자의 의미를 제공합니다. 각각을 언제 사용할 지에 관해서는 외부 사용 (API)을위한 모든 클래스와 각 클래스의 메서드를 공개하고 다른 모든 메서드는 private로 제안하는 것이 좋습니다.

시간이 지남에 따라 일부 클래스를 패키지 전용으로 만드는 경우와 하위 클래스에서 사용하도록 보호 된 특정 메서드를 선언 할시기에 대한 개념을 개발할 것입니다.


Java에서 가장 오해 된 액세스 수정자가 protected . 서브 클래스가 그것을 볼 수있는 한 가지 예외를 제외하고는 기본 수정 자와 유사하다는 것을 알고 있습니다. 그러나 어떻게? 다음은 혼란을 명확히 해명 한 예입니다.

  • 우리는 2 개의 클래스가 있다고 가정합니다. FatherSon 은 각각 자신의 패키지 안에 있습니다 :

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
    
  • Father 에게 보호 된 foo() 메소드를 추가해 보겠습니다.

    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 ) [이것은 컨텍스트 번호에 포함될 수 있습니다. 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
          }
      }
      

경험 법칙 :

  • private : 클래스 범위.
  • default (또는 package-private ) : 패키지 범위.
  • protected : 패키지 범위 + 자식 (패키지와 같지만 다른 패키지에서 하위 클래스로 분류 할 수 있음). 보호 된 수정자는 항상 "부모 - 자식"관계를 유지합니다.
  • 공개 : 모든 곳.

결과적으로 액세스 권한을 세 가지 권한으로 나누면

  • (D) irect (같은 클래스 내의 메소드로부터 호출).
  • (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   |
+—————————————————+————————————+———————————+

패키지에 표시됩니다. 기본값. 한정자가 필요하지 않습니다.

수업에만 공개 ( 비공개 ).

세계에 공개 ( 공개 ).

패키지 및 모든 하위 클래스 ( 보호됨 )에 표시됩니다.

변수 및 메소드는 호출되는 수정 자없이 선언 될 수 있습니다. 기본 예제 :

String name = "john";

public int age(){
    return age;
}

비공개 액세스 수정 자 - 비공개 :

private로 선언 된 메소드, 변수 및 생성자는 선언 된 클래스 자체 내에서만 액세스 할 수 있습니다. 개인 액세스 수정자는 가장 제한적인 액세스 레벨입니다. 클래스와 인터페이스는 private 일 수 없습니다.

공용 getter 메서드가 클래스에 있으면 private로 선언 된 변수를 클래스 외부에서 액세스 할 수 있습니다.

private 한정자를 사용하는 것은 객체가 자체를 캡슐화하고 외부 세계의 데이터를 숨기는 주요 방법입니다.

예 :

Public class Details{

    private String name;

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

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

공용 액세스 수정 자 - 공개 :

공용으로 선언 된 클래스, 메소드, 생성자, 인터페이스 등은 다른 클래스에서 액세스 할 수 있습니다. 따라서 공용 클래스 내에서 선언 된 필드, 메서드, 블록은 Java 유니버스에 속한 모든 클래스에서 액세스 할 수 있습니다.

그러나 액세스하려고하는 공용 클래스가 다른 패키지에 있으면 공용 클래스를 가져와야합니다.

클래스 상속 때문에 클래스의 모든 공용 메서드와 변수는 하위 클래스에 상속됩니다.

예:

public void cal(){

}

보호 된 액세스 수정 자 - 보호 :

수퍼 클래스에서 보호 된 것으로 선언 된 변수, 메서드 및 생성자는 다른 패키지의 하위 클래스 또는 보호 된 멤버 클래스의 패키지 내의 모든 클래스에서만 액세스 할 수 있습니다.

보호 된 액세스 수정자는 클래스 및 인터페이스에 적용 할 수 없습니다. 메소드, 필드는 protected로 선언 할 수 있지만 인터페이스의 메소드와 필드는 protected로 선언 할 수 없습니다.

보호 된 액세스는 하위 클래스가 도우미 메서드 또는 변수를 사용할 수있는 기회를 제공하고 관련없는 클래스가이를 사용하지 못하게합니다.

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}

(경고 : 나는 자바 프로그래머가 아니다, 나는 펄 프로그래머이다. 펄은 공식적인 보호 장치가 없다. 어쩌면 나는 그 문제를 잘 이해하고있다.))

은밀한

당신이 생각하는 것처럼, 그것이 선언 된 클래스 만이 그것을 볼 수 있습니다.

비공개 패키지

패키지 가 선언 된 패키지 에서만 보이고 사용할 수 있습니다. 이것은 Java에서 기본값입니다 (일부는 실수로 표시됨).

보호 된

Package Private +는 하위 클래스 또는 패키지 멤버가 볼 수 있습니다.

공공의

누구나 볼 수 있습니다.

Published

내가 제어하는 ​​코드 외부에 표시됩니다. (Java 구문은 아니지만이 토론에서는 중요합니다.)

C ++은 "친구"라고 불리는 추가 레벨을 정의합니다.

무엇을 사용해야합니까? 전체 아이디어는 정보를 숨기기위한 캡슐화입니다. 가능한 한 많이 사용자가 수행 한 작업의 세부 사항을 숨기려고합니다. 왜? 왜냐하면 나중에 그들을 바꿀 수 있고 다른 사람의 코드를 깨지 않기 때문입니다. 이를 통해 누군가가 방금 분해 한 코드를 사용하고 있다는 걱정없이 버그를 최적화, 리팩터링, 재 설계 및 수정할 수 있습니다.

따라서 엄지 손가락의 규칙은 사물을 보이는 대로만 보이게 만드는 것입니다. 비공개로 시작하고 필요에 따라 더 많은 가시성을 추가하십시오. 사용자가 알기에 절대적으로 필요한 것을 공개 만하면 공개하는 모든 세부 사항이 시스템을 재 설계 할 수있는 능력을 손상시킵니다.

사용자가 행동을 사용자 정의하여 내선을 공개 할 수 없도록 공개하기보다는 행동을 사용자 정의 할 수있게하려면 이러한 내장을 객체로 이동하여 해당 인터페이스를 공개하는 것이 좋습니다. 그렇게하면 새 객체를 간단하게 연결할 수 있습니다. 예를 들어, CD 플레이어를 작성하고 "이 CD에 대한 정보 찾기"비트를 사용자 정의 할 수있게하려는 경우 해당 메소드를 공용으로 만들지 않고 모든 해당 기능을 자체 객체에 넣고 객체 getter / setter를 public으로 설정하십시오 . 이런 식으로 귀하의 용기를 드러내는 것에 대한 인색감은 좋은 구성과 관심사의 분리를 조장합니다.

개인적으로 나는 단지 "사적"과 "대중"만을 고집합니다. 많은 OO 언어가 가지고 있습니다. "Protected"는 편리 할 수 ​​있지만 정말 속임수입니다. 인터페이스가 개인적인 것 이상으로되면 컨트롤을 벗어나기 때문에 다른 사람의 코드를보고 용도를 ​​찾아야합니다.

인터페이스의 변경 (리팩토링)을 위해서는 인터페이스를 사용하고있는 모든 코드를 찾고 변경해야합니다. 인터페이스가 비공개 인 경우 문제가 없습니다. 그것이 보호되면 모든 하위 클래스를 찾아야합니다. 공개 된 경우 코드를 사용하는 모든 코드를 찾아야합니다. 때로는 가능합니다. 예를 들어 회사 코드를 사용하여 내부 용으로 만 작업하는 경우 인터페이스가 공용인지 여부는 중요하지 않습니다. 회사 저장소에서 모든 코드를 가져올 수 있습니다. 그러나 인터페이스가 "게시"된 경우 컨트롤 외부에서 코드를 사용하면 코드가 붙습니다. 해당 인터페이스 또는 위험 코드를 지원해야합니다. 보호 된 인터페이스조차도 게시 된 것으로 간주 될 수 있습니다 (이것이 내가 보호받는 것에 신경 쓰지 않는 이유입니다).

많은 언어에서는 공개 / 보호 / 개인의 계층 적 특성이 너무 제한적이며 현실과 일치하지 않는 것으로 나타납니다. 이를 위해 특성 클래스 의 개념이 있지만 또 다른 쇼입니다.


공식 튜토리얼 은 당신에게 유용 할 수 있습니다.

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

+ : accessible
blank : not accessible

첫 번째 대답은 기본적으로 정확합니다.

  • 동일한 패키지의 클래스
  • 다른 패키지로부터의 선언 클래스의 서브 클래스

그러나 약간의 트릭이 있습니다.

6.6.2 보호 된 접근에 대한 세부 사항

객체의 보호 된 멤버 또는 생성자는 해당 객체의 구현을 담당하는 코드에 의해서만 선언 된 패키지 외부에서 액세스 할 수 있습니다.

즉, 다른 패키지의 서브 클래스는 슈퍼 클래스의 임의 인스턴스의 protected 멤버에 액세스 할 수 없으며 자체 유형의 인스턴스에서만 액세스 할 수 있습니다 (유형은 컴파일 타임 형식이므로 컴파일 타임 유형의 표현식입니다).

예를 들어 (이 코드가 Cat 있다고 가정)

Dog dog = new Dog();
Animal cat = new Cat();

dog.testInstanceMethod(); // Not allowed, because Cat should not be able to access protected members of Dog
cat.testInstanceMethod(); // Not allowed, because compiler doesn't know that runtime type of cat is Cat

((Cat) cat).testInstanceMethod(); // Allowed

Cat 가 자신의 불변량을 보장하는 방법을 알고 있기 때문에 Cat 가 자신의 protected 멤버에게 안전하게 액세스 할 수있는 반면 Cat 의해 Dogprotected 멤버에 액세스하면 Dog 불변량이 깨질 수 있기 때문에 의미가 있습니다.

세부 규칙 :

6.6.2.1 보호 된 회원에 대한 접근

C를 보호 된 멤버 m이 선언 된 클래스 라하자. 액세스는 C의 하위 클래스 S의 본문 내에서만 허용됩니다. 또한 Id가 인스턴스 필드 또는 인스턴스 메서드를 나타내는 경우 다음과 같습니다.

  • Q가 ExpressionName 인 정규화 된 이름 Q.Id로 액세스하는 경우 표현식 Q의 유형이 S 또는 S의 서브 클래스 인 경우에만 액세스가 허용됩니다.
  • 액세스가 필드 액세스 표현식 E.Id (E가 기본 표현식 인 경우) 또는 메소드 호출 표현식 E.Id (..) (E가 기본 표현식 인 경우)로 액세스가 허용되는 경우에만 액세스가 허용됩니다 E의 타입이 S 또는 S의 서브 클래스 인 경우.

6.6.2.2 보호 된 생성자에 대한 공인 된 액세스

C를 보호 된 생성자가 선언 된 클래스라고하고, S가 보호 된 생성자의 사용이 선언 된 가장 안쪽의 클래스라고 가정합니다. 그때:

  • 슈퍼 클래스 생성자 호출 super (..) 또는 E.super (..) 형식의 수퍼 클래스 생성자 호출 (E가 기본 표현식 인 경우)에 의한 액세스 인 경우 액세스가 허용됩니다.
  • 액세스가 new C (....) {...} 형식의 익명 클래스 인스턴스 작성 표현식이거나 E.new C (..) {... 형식의 정규화 된 클래스 인스턴스 작성 표현식 인 경우 }, 여기서 E는 기본 표현식이고 액세스가 허용됩니다.
  • 그렇지 않으면 new C (...) 형식의 간단한 클래스 인스턴스 생성 식 또는 E.new C (....) 형식의 정규화 된 클래스 인스턴스 생성 식 (E는 Primary 표현식)으로 액세스하는 경우 , 액세스가 허용되지 않습니다. 보호 된 생성자는 정의 된 패키지 내에서만 클래스 인스턴스 생성 표현식 (익명 클래스를 선언하지 않음)을 통해 액세스 할 수 있습니다.

참조 :





java private public protected access-modifiers