[JAVA] 문법 정리 - 접근 제어자
접근제어자
접근 제어자[Access Modifiers] 는 클래스의 특정 필드나 메서드에 접근하는 것을 제한하는 키워드입니다.
JAVA는 private, default, protected, public 4가지 제어자를 제공합니다.
private > default > protected > public 순으로 엄격한 제한을 줄 수 있습니다.
Private
private는 해당 클래스를 제외한 모든 외부 클래스의 접근을 제한합니다.
package pack.user;
public class User {
// private 주민번호
private String residentNumber;
// default 몸무게
double weight;
// protected 나이
protected int age;
// public 이름
public String name;
}
private로 선언된 residentNumber는 외부 클래스 userService에서 접근이 불가능합니다.
package pack.user;
public class UserService {
public static void main(String[] args) {
User user = new User();
// private 접근 불가
// user.residentNumber = '19700101-1******'; -> ERROR!
}
}
Default & Protected
default 제어자는 접근 제어자를 명시하지 않았을 때 기본적으로 설정됩니다.
동일한 패키지에서만 접근이 가능하며 외부 패키지에서는 접근이 불가능합니다.
package pack.user;
public class UserService {
public static void main(String[] args) {
User user = new User();
// private 접근 불가
// user.residentNumber = '19700101-1******';
// default 접근 가능
user.weight = 80.0;
}
}
protected 제어자는 default 제어자와 동일하게 같은 패키지에서만 접근이 가능하나
예외로 해당 클래스를 상속받은 클래스의 경우 접근이 가능합니다.
package pack.product;
import pack.user.User;
public class ProductService extends User {
public static void main(String[] args) {
ProductService ps = new ProductService();
// 다른 패키지에서 default 접근 불가
// ps.weight = 80.0; -> Error!
// 다른 패키지여도 상속받았을 경우 접근 가능
ps.age = 20;
}
}
그러나 상속받았다고 public 처럼 어디서나 접근이 가능한 것은 아닙니다.
protected 필드 또는 메서드를 호출하는 패키지의 위치에 따라 접근이 불가능할 수 있습니다.
Test1 클래스를 상속받는 Test2 클래스를 다른 패키지에 생성해 보겠습니다.
package test1;
public class Test1 {
protected int protectedIntValue = 0;
protected void protectedMethod(){}
}
package test2;
import test1.Test1;
public class Test2 extends Test1 {
}
Test2 클래스와 동일한 패키지에서 TestMain 클래스를 생성하여
protected 메서드 호출 시, 에러가 발생하는 것을 알 수 있습니다.
package test2;
public class TestMain {
public static void main(String[] args) {
Test2 test2 = new Test2();
// test2.protectedMethod(); -> ERROR!
}
}
Test2 클래스는 Test1 클래스를 상속받았으니 인스턴스가 protected 에 접근이 가능한 것처럼 보이지만
호출 시점의 TestMain 클래스가 Test1과 다른 패키지에 있기 때문에 접근이 불가능합니다.
따라서 Test2 클래스에서 protected 메서드를 Override 해야 Test2 클래스와 같은 패키지에서만 접근이 가능합니다.
package test2;
import test1.Test1;
public class Test2 extends Test1 {
@Override
protected void protectedMethod() {
super.test();
}
}
일례로 java.lang.Object 클래스의 clone 메서드는 protected 로 접근이 제한되어 있습니다.
// Object.java
@IntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
따라서 clone 메서드를 사용하기 위해서는 클래스에서 메서드 재정의 후, 같은 패키지 내부에서만 사용할 수 있습니다.
package test2
public class Test2 implements Cloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
결론은 메서드 재정의가 필요할 경우에 protected 를 사용하여야 하며
상속받았더라도 같은 패키지 내에서만 사용이 가능합니다.
Public
public 제어자는 패키지, 클래스의 제약 없이 어디서든 호출할 수 있는 접근 제어자입니다.
package pack.product;
import pack.user.User;
public class ProductService extends User {
public static void main(String[] args) {
User user = new User();
// 제한 없이 public 호출 가능
user.name = "김홍동";
}
}
왜 접근제한자를 사용하는가
객체 지향 프로그래밍의 중요한 개념 중 캡슐화 [Encapsulation] 는 데이터의 직접적인 접근을 제한하고
오직 메서드를 통해서만 데이터의 처리를 수행하는 것을 의미합니다.
일부 데이터는 가공이 필요하며 잘 못 된 값을 걸러내야 할 필요성이 존재합니다.
따라서 클래스의 필드는 private 로 숨기고, 해당 데이터를 가공하는 메서드만 public 으로 외부에 노출해야 합니다.
해당 클래스를 사용하는 다른 개발자가 특정 메서드를 사용하기를 원하지 않을 경우,
외부 접근이 필요하지 않은 메서드의 경우 최대한 private 로 숨겨야 합니다.
예를 들어 유저의 몸무게는 음수가 될 수 없기 때문에
캡슐화를 통해 이러한 값을 직접적으로 할당하는 것을 막을 수 있습니다.
package pack.user;
public class User {
// private 몸무게
private double weight;
// 몸무게를 설정하는 메서드
public void setWeight(double weight) {
if(weight <= 0) {
// 에러 발생
throw new IllegalArgumentException("Weight must be greater than 0.");
}
this.weight = weight;
}
// 외부에서 호출할 필요가 없는 메서드
private void doNothing(){}
}
package pack.user;
public class UserService {
public static void main(String[] args) {
User user = new User();
// 필드에 직접 접근이 불가능함
// user.weight = -2754.23; -> ERROR!
// 올바르지 않은 데이터를 걸러낼 수 있음
// user.setWeight(-2314.54); -> ERROR!
user.setWeight(80.0);
}
}
'Java > Syntax' 카테고리의 다른 글
[JAVA] 문법 정리 - 상속과 다형성, 추상화, 인터페이스 (2) | 2025.04.18 |
---|---|
[JAVA] 문법 정리 - static, final (0) | 2025.04.14 |
[JAVA] 문법 정리 - package (0) | 2025.03.08 |
[JAVA] 문법 정리 - class (1) | 2025.03.06 |
[JAVA] 문법 정리 - 제어 흐름 (1) | 2025.02.25 |
[JAVA] 문법 정리 - 연산자 (1) | 2025.02.25 |
[JAVA] 문법 정리 - 변수 (1) | 2025.02.24 |