본문 바로가기

Java

Java- 접근 지시 제어자

인스턴스 멤버의 public과 default 선언이 갖는 의미

 타 패키지에서의 접근 여부

  -public: 어디서든 접근이 가능

  -default: 동일 패키지로 묶인 클래스 내에서만 접근이 가능하다.

 public 선언된 해당 클래스나 메소드는 타 패키지에서 접근이 가능하다. 클래스가 public 선언이 되었다면 해당 클래스는 다른 패키에 있는 파일에서 import 가능하다.

클래스 메소드 타 패키지 파일에서의 접근 여부
public public import 가능  /  메소드 접근 가능
public default import 가능  /  메소드 접근 불가
default public import 불가  
default default import 불가

 

지금 아래의 두 코드는 서로 다른 package에 선언이 되어있다.

 

SourceFile 패키지에 선언된 클래스 Cat, Duck

//Cat.java
package SourceFile;  //SourceFile package에 선언된 파일

public class Cat {  //public 클래스
    public void makeSound(){  //public 클래스의 public 함수
        System.out.println("야옹");
    }
    void makeHappy(){  //public 클래스의 default 함수
        System.out.println("스마일");
    }
}

class Duck{  //default 클래스
    public void makeSound(){  //default 클래스의 public 함수
        System.out.println("오리 꽥꽥");
    }
    void makeEgg(){  //default 클래스의 default 함수
        System.out.println("계란 프라이");
    }
}

ImportFile 패키지에 선언된 클래스 Dog

//Dog.java
package ImportFile;
import SourceFile.Cat;  //SourceFile에 있는 public 클래스 Cat을 import한다.
//import SourceFile.Duck;   //애초에 public 클래스가 아니라서 import 시도가 불가하다.

public class Dog {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.makeSound();  //public 클래스의 public 함수는 다른 패키지에서 import가 가능하다.
        //cat.makeHappy();  //public 클래스라고 할지라도 default 함수는 다른 패키지에서 import가 불가하다.
    }
}

 Dog.java는 SourceFile 패키지에 존재하는 클래스 Cat과 Duck을 Import 시도하고 있다.

Cat은 public 클래스 이므로 import가 되지만 Duck은 default 클래스라 그렇지 못한다.

Cat의 makeSound() 메소드는 public 메소드라 접근이 되지만 makeHappy는 default라서 그렇지 못한다

 

인스턴스 멤버에 대한 protected, defualt 선언이 갖는 의미

  클래스 선언에 있어서 public과 default는 위에서 보았듯이 타 패키지의 소스파일에서 import를 하느냐 여부에 따라서 그 의미가 차이가 났다. public은 다른 패키지에서도 충분히 import하여 접근이 가능한 반면에 default는 타 패키지에서는 import가 불가능했다. 그 차이를 제외하고는 동일한 패키지에서 public과 default가 갖는 의미는 동일했다.

 

  -private

public class Cat {  //public 클래스
    private String kind = "페르시안";
    private void punch(){
        System.out.println("냥냥펀치");
    }
}

class Cat2 extends Cat{  //Cat을 상속받은 Cat2
    public Cat2(String n){
        //kind = n;  //private 선언이라 접근 불가
    }
    void catHabits(){
        //punch();  //private이라 호출불가
    }
}

  private에 대한 기본적인 이해는 그닥 어렵지 않다. 동일한 클래스 내부에선 접근이 가능하고 외부 클래스에선 상속을 받았다고 하더라도 접근이 불가능하다.

 

  -protected

  protected는 default와 비슷하지만 상속과 관련된 부분에서만 차이가 있다. 기본적으로 동일한 패키지에서는 모두 접근이 가능하다.

default와 차이점이라면 protected는 상속 관계에 있는 두 클래스가 서로 다른 패키지로 묶여있어도 접근이 가능하다.

//동일 패키지에서 protected와 default
package SourceFile;

public class Cat {  //public 클래스
    double height = 51.5;
    protected String name = "나비";
    
    void makeHappy(){  //public 클래스의 default 함수
        System.out.println("스마일");
    }
    protected void jump(){
        System.out.println("폴짝");
    }

    public static void main(String[] args) {
        Cat2 tom = new Cat2(100.2,"톰");
        tom.catHabits();
    }
}

class Cat2 extends Cat{  //Cat을 상속받은 Cat2
    public Cat2(double h, String n){
        height = h;  //default
        name = n;     //protected
    }
    void catHabits(){
        makeHappy();   //default
        jump();        //protected
    }
}

지금 위의 코드(SourceFile 패키지의 Cat.java)는 정상적으로 작동한다. (동일 패키지에서 default와 protected는 동일한 작동)

 

package ImportFile;
import SourceFile.Cat;  //SourceFile에 있는 public 클래스 Cat을 import한다.

public class Dog {

}

class Cat3 extends Cat{
    public Cat3(double h, String n){
        //height = h;  //default라서 다른 패키지에서 호출 불가
        name = n;     //protected
    }
    void catHabits(){
        //makeHappy();   //default라서 다른 패키지에서 호출 불가
        jump();        //protected
    }
}

Cat.java가 ImportFIle 패키지의 Dog.java에 import된 상황으로 서로 다른 패키지에서 default 멤버는 접근이 불가한 반면, protected 멤버 변수 name과 메소드 jump()는 상속이 된 상황에선 접근이 가능한 것을 볼 수 있다. 다만 여기서 중요한 것은 상속이 되어야지 사용이 가능한 것을 기억하자.

 

 

예시

  1)동일한 패키지 내부에서의 접근

package AAA;

public class AA {
    public String PUBLIC = "public";
    String DEFAULT = "default";
    protected String PROTECTED = "protected";
    private String PRIVATE = "private";

    public static void main(String[] args) {
        BB b = new BB();
        CC c = new CC();
        
        b.bbFunc();
        c.ccFunc();
    }
}

class BB{
    void bbFunc(){
        AA a = new AA();
        System.out.println(a.PUBLIC);
        System.out.println(a.DEFAULT);
        System.out.println(a.PROTECTED);
    }
}

class CC extends AA{
    void ccFunc(){
        System.out.println(PUBLIC);
        System.out.println(DEFAULT);
        System.out.println(PROTECTED);
    }
}


public
default
protected
public
default
protected

  같은 패키지에선 상속 여부와 관계없이 서로 다른 클래스 간 public, default, protected 멤버에 접근 가능.

 

  2)서로 다른 패키지에서의 접근

package ZZZ;
import AAA.*;

public class ZZ {
    public static void main(String[] args) {
        DD d = new DD();
        EE e = new EE();

        d.ddFunc();
        e.eeFunc();
    }
}

class DD{
    void ddFunc(){
        AA a = new AA();
        System.out.println(a.PUBLIC);
    }
}

class EE extends AA{
    void eeFunc(){
        System.out.println(PUBLIC);
        System.out.println(PROTECTED);
    }
}

public
public
protected

 서로 다른 패키지에선 상속을 받지 않았다면 public만 접근 가능.

 상속을 받았다면 public, protected에 접근 가능.

 

정리 도표

지시자 클래스 내부 동일 패키지 상속 받은 클래스 다른 패키지에 속한
클래스
  private O x x x
  default O O x x
  protected O O O x
  public O O O O

'Java' 카테고리의 다른 글

Java- 문자열 결합의 최적화(StringBuilder 클래스)  (0) 2022.12.27
Java- 메소드 오버로딩과 this  (0) 2022.12.26
Java- main 메소드  (0) 2022.12.26
Java- 클래스 변수와 클래스 메소드, static  (0) 2022.12.25
Java- 생성자  (0) 2022.12.22