접근 제한자(Access Modifier)

김경태·2022년 9월 19일

Java 기초

목록 보기
4/7

main 메서드를 가지지 않는 대부분의 클래스들은 외부 클래스에서 이용할 목적으로 설계된 라이브러리 클래스이다.
라이브러리 클래스를 설계할 때는 외부 클래스에 접근할 수 있는 멤버와 접근할 수 없는 멤버로 구분해서, 필드, 생성자, 메서드를 설계한다.
멤버들은 객체 자신들만의 속성이자 특징이므로 대외적으로 공개되는 것이 결코 좋은 것은 아니다.그런 이유로 프로그래머가 객체의 멤버들에게 접근 제한을 걸 수가 있는데 자바에서는 이를 접근 제한자라 한다.

캡슐화

항상 은닉화를 전제로 한다. 관련이 있는 데이터 그리고 동작들을 하나로 묶어 요약하고 사용자에게는 내부적인 접근을 허용하지 않는 대신에 사용의 편의성을 제공해 주는 것이다.

  • 데이터 포호의 장점: 은닉화를 통해 데이터의 접근을 제어할 수 있다.
  • 유지 보수성의 장점: 객체에 대한 수정 작업으로 인해 객체 활용도에 문제가 발생한다면 제품 하나에 대한 upgrade가 상당히 부담스러울 것이다. 자바에서는 각 기능을 하나의 모듈(부품)처럼 활용하여 객체간의 이식성이 높고 독립적인 면을 유지하는 장점이 있다.
  • 사용자 편위성의 장점: 전기 압력밥솥이 어떤 원리와 과정으로 밥을 지어내는지는 알 필요 없이 그냥 사용법만 익혀서 사용한다.

interface

interface는 다중 상속을 위해 만드는데, 보통 2가지 방식으로 설계한다. 하나는 여러 class에서 공통적으로 사용하기 위한 상수 위주로 만들거나, 메서드 위주로 만든다. 인터페이스는 접근 제한자 없이 만들어지는데, 기본적으로 public 이다. 여러 클래스에서 사용하기 위해서 인터페이스를 만들어도 되고, 상수(Constant) 클래스를 만들어도 된다. 본인의 선택.

abstract(추상화) class

추상화 클래스를 만드는 이유는 추상화 메서드를 만들기 위해서이다. 추상화 클래스를 상속하는 자식 클래스는 추상화 메서드를 자신의 입맛대로 수정할 수 있다.

접근 제한자 종류

public, protected, default, private 순서로 접근 제한이 강화.

접근 제한자적용 대상접근 가능 대상접근 불가 대상
public클래스, 필드, 생성자, 메서드모든 대상없음
protected필드, 생성자, 메서드같은 패키지 또는 자식 클래스자식 클래스가 아닌 다른 패키지에 소속된 클래스
default클래스, 필드, 생성자, 메서드같은 패키지에 소속된 클래스다른 패키지에 소속된 클래스
private필드, 생성자, 메서드클래스 내부클래스 외부

클래스의 접근 제한(패키지)

클래스를 선언 시 같은 패키지 내에서만 사용할 것인지, 다른 패키지에서도 사용할 수 있도록 할 것인지 결정한다.
클래스에 적용할 수 있는 접근 제한: public, default

// default 접근 제한
class 클래스 { . . . }

// public 접근 제한
public class 클래스 { . . . }

default

클래스 선언 시 public 을 생략한다면 default 접근 제한을 가진다.
같은 패키지에서는 아무런 제한 없이 사용, 다른 패키지에서는 사용 불가.

public

클래스 선언 시 public 접근 제한자를 붙이면 public 접근 제한을 가진다.
같은 패키지 뿐만 아니라 다른 패키지에서도 아무런 제한 없이 사용 가능.
다른 개발자가 클래스를 사용하도록 라이브러리 클래스로 개발 시, public 접근 제한을 갖도록 한다.

A.java

package com.example.package1;

Class A { } // default 접근 제한

B.java

package com.example.package1;
publcic Class B { // public 접근 제한
	A a;		  // A 클래스 접근 가능(같은 패키지), 필드로 선언할 수 있다.
}

C.java

package com.example.package2; 		// 다른 패키지
import com.example.package1.*; 		// package1 import 
public class C {
	A a; // A 클래스 접근 불가 (컴파일 에러)
    B b; // B 클래스 접근 가능
}

C클래스는 A클래스와 다른 패키지 이므로
default 접근 제한 A클래스에 접근 불가, public 접근 제한 B클래스 접근 가능
C클래스에서 B클래스를 이용한 필드 선언 및 생성자 / 메서드 내부에서 변수 선언 가능

생성자의 접근 제한

	public class ClassName {
	// public 접근 제한 생성자
	public ClassName( . . . ) { . . . }
    
    // protected  접근 제한 생성자
    protected ClassName( . . . ) { . . . }
    
    // default 접근 재한 생성자
    ClassName( . . . ) { . . . }
    
    // private 접근 제한 생성자
    private ClassName( . . . ) { . . . }
}

객체를 생성하기 위해 new 연산자로 생성자를 호출해야 한다.
생성자가 어떤 접근 제한을 갖느냐에 따라 호출 가능 여부가 달라진다.
생성자에 적용할 수 있는 접근 제한: public, protected, default, private
클래스에 생성자를 선언하지 않으면, 컴파일러에 의해 기본 생성자가 추가된다.
자동으로 생성되는 기본 생성자의 접근 제한은 클래스의 접근 제한과 동일하다.(public, default)
public class ClassName이라면 public ClassName() {} 기본 생성자가 자동 생성되고,
class ClassName이라면 ClassName() {} 기본 생성자(default 접근 제한자)가 자동 생성된다.

접근 제한자생성자설명
public클래스( . . . )모든 패키지에서 제한 없이 생성자 호출 가능. 생성자가 public 접근 제한이면, 클래스도 public 접근 제한을 가지는 것이 정상적. 클래스가 default 접근 제한 가질 때, 클래스 사용 패키지로 한정되므로 생성자가 public 접근 제한을 가지더라도 같은 패키지 내에서만 호출 가능.
protected클래스( . . . )default 접근 제한과 마찬가지로, 같은 패키지에 속하는 클래스에서 생성자 호출 가능. 다른 패키지에 속한 클래스가 해당 클래스의 자식 클래스라면 생성자를 호출할 수 있다.
default클래스( . . . )생성자를 선언할 때 public/private 생략 시 default 접근 제한을 가진다. 같은 패키지 내에서 아무런 제한 없이 생성자 호출 가능. 다른 패키지에서는 생성자를 호출할 수 없다.
private클래스( . . . )동일 패키지, 다른 패키지 상관 없이 생성자를 호출 할 수 없다. 클래스 외부에서 new 연산자로 객체 생성 불가. 오로지 클래스 내부에서만 생성자 호출할 수 있고, 객체를 만들 수 있다.

A.java(클래스 내부)

package com.example.xmlparsingtest.package1;

public class A {
    A a1 = new A(true);		// 가능(클래스 내부)
    A a2 = new A(1);		// 가능(클래스 내부)
    A a3 = new A("문자열");  // 가능(클래스 내부)

    public A(boolean b) {} // public 접근 제한
    A(int b) {} // default // default  접근 제한
    private A(String S) {} // private 접근 제한
}

클래스 내부에서는 A의 모든 생성자 호출 가능.

B.java(같은 패키지, 다른 클래스)

package com.example.xmlparsingtest.package1;	// A와 동일 패키지

public class B {
	// 필드
    A a1 = new A(true);		// 가능(A 클래스의 public 생성자)
    A a2 = new A(1);		// 가능 (A 클래스의 default 생성자, 같은 패키지)
    A a3 = new A("문자열");  // 불가능: private 생성자 이기 때문에 컴파일 에러
}

C.java(다른 패키지, 다른 클래스)

package com.example.xmlparsingtest.package2;	// 다른 패키지

import com.example.xmlparsingtest.package1.A;	// package1 import

public class C {
	// 필드
    A a1 = new A(true);	// 가능(A의 default 생성자 접근 가능)
    A a2 = new A(1); // 다른 패키지라서 컴파일 에러(dafualt 생성자)
    A a3 = new A("문자열"); // 다른 패키지라서 컴파일 에러(private 생성자)
}

필드와 메서드 접근 제한

클래스 내부에서만 사용할 것인지, 패키지 내에서만 사용할 것인지, 다른 패키지에서도 사용할 것인지 결정.
필드와 메서드가 어떤 접근 제한을 갖느냐에 따라 결정된다.
필드, 메서드에 적용할 수 있는 접근 제한: public, protected, default, private

// 필드 선언
[ public | protected | private ] [static] 타입 필드;

// 메서드 선언
[ public | protected | private ] [static] 리턴타입 메서드( . . . ) { . . . }
접근 제한자필드/매서드설명
public필드 메서드(...)모든 패키지에서 아무 제한 없이 필드, 메서드 사용 가능.필드, 메서드가 public 접근 제한이면, 클래스도 public 접근 제한을 가져야 한다. 클래스가 default 접근 제한이라면, 같은 패키지 안에서만 클래스가 사용되기 때문이다.
protected필드 메서드(...)default 접근 제한과 마찬가지로, 같은 패키지에 속하는 클래스에서 필드, 메서드 사용 가능. 다른 패키지에 속한 클래스가 해당 클래스의 자식 클래스라면 필드와 메서드를 사용할 수 있다.
default필드 메서드(...)public/private 생략 시 default 접근 제한을 가진다. 같은 패키지에서만 필드, 메서드 사용 가능. 다른 패키지에서는 필드, 메서드 사용 불가.
private필드 메서드(...)동일 패키지, 다른 패키지 간에 필드와 메서드 사용 불가. 클래스 내부에서만 사용 가능.

A.java

package com.example.xmlparsingtest.package1;

public class A {
    // 필드
    public int field1;  // public 접근 제한 필드
    int field2;         // default 접근 제한 필드
    private int field3; // private 접근 제한 필드

    // 생성자
    public A() {
        field1 = 1;     // 가능(클래스 내부 필드)
        field2 = 2;     // 가능(클래스 내부 필드)
        field3 = 3;     // 가능(클래스 내부 필드)

        method1();      // 가능(클래스 내부 메서드)
        method2();      // 가능(클래스 내부 메서드)
        method3();      // 가능(클래스 내부 메서드)
    }

    // 메서드
    public void method1() {}    // public 접근 제한 메서드
    void method2() {}           // default 접근 제한 메서드
    private void method3() {}   // private 접근 제한 메서드
}

B.java

package com.example.xmlparsingtest.package1;

public class B { // public
    // 생성자
    public B() {
        A a = new A();  // A 클래스 접근 가능(public)

        a.field1 = 1;   // 가능: A 클래스의 public 필드 접근 가능
        a.field2 = 2;   // 가능: A 클래스의 default 필드 접근 가능(같은 패키지)
        a.field3 = 3;   // 불가능(컴파일 에러): A 클래스의 private 필드 접근 불가

        a.method1();    // 가능: A 클래스의 public 메서드 접근 가능
        a.method2();    // 가능: A 클래스의 default 메서드 접근 가능(같은 패키지)
        a.method3();    // 불가능(컴파일 에러): A 클래스의 private 메서드 접근 불가
    }
}

C.java

package com.example.xmlparsingtest.package2;    // A, B 클래스와 다른 패키지

import com.example.xmlparsingtest.package1.A;   // import A 클래스

public class C {
    // 생성자
    public C() {
        A a = new A();  // a 객체 생성, A 클래스 접근 가능

        a.field1 = 1;   // 가능: public 필드 접근 가능
        a.field2 = 2;   // 불가능: default 필드 접근 불가(컴파일 에러)
        a.field3 = 3;   // 불가능: private 필드 접근 불가(컴파일 에러)

        a.method1();    // 가능: public 메서드 접근 가능
        a.method2();    // 불가능: default 메서드 접근 불가(컴파일 에러)
        a.method3();    // 불가능: private 메서드 접근 불가(컴파일 에러)
    }
}

일단 static 객체에서 static 이 아닌 객체를 호출 하는것은 불가능 하다.
static 이 먼저 정의가 되기 때문에 아직 정의되지 않은 객체는 호출할 수 없기 때문이다.

https://kephilab.tistory.com/

profile
잊지 않기 위해 기록

0개의 댓글