Java
[JAVA] 접근제어자, 은닉
임혁진
2025. 1. 11. 15:50
접근 제어자(Access Modifier)와 은닉(Encapsulation)은 자바의 객체지향 프로그래밍에서
데이터 보호와 캡슐화를 구현하는 핵심 개념입니다.
이들은 클래스와 멤버(변수, 메서드)의 접근 범위 를 제한하거나 관리하여, 코드의 보안성과 유지보수성을
높이는 데 기여합니다
1. 접근제어자(Access Modifiers)
클래스에 적용되는 접근제어자
- public: 다른 패키지에서도 접근 가능.
- default: 접근제어자를 명시하지 않으면 default로 설정되며, 같은 패키지 내에서만 접근 가능.
예시
class A {
//클래스 붙는 접근제어자(접근제어자를 붙이지않으면 default)
}
public class B {
A a = new A(); //default는 같은 패키지에서 접근가능
}
멤버 변수와 메서드에 적용되는 접근제어자
- public: 모든 패키지에서 접근 가능.
- protected: 같은 패키지 + 상속받은 클래스에서 super 키워드를 통해 접근 가능.
- default: 같은 패키지 내에서만 접근 가능.
- private: 같은 클래스 내에서만 접근 가능.
예시
default :
package day07.modi.cls.pac2;
import day07.modi.cls.pac1.*;
public class C {
// A a = new A(); //A클래스는 default라서 패키지가 다르면 접근 x
B b = new B(); //B클래스는 public라서 접근 ok
}
public :
public class A {
//생성자에 접근제어자
public A(int i) {}
A(boolean b) {}
private A(String s) {}
//---------------------------------------------------
//멤버변수와 메서드에 붙는 접근제어자
public int var1;
int var2;
private int var3;
public void method01() {}
void method02() {}
private void method03() {}
public A() {
//A에서는 모두 접근 가능
this.var1 = 1;
this.var2 = 2;
this.var3 = 3;
method01();
method02();
method03();
}
private :
public class B {
A a = new A(1); //public (o)
A a2 = new A(true); //default (o)
//A a3 = new A("홍길동"); //private (x)
//생성자에 private붙여서 외부에서 객체 생성을 못하도록 처리하기도 함
//-------------------------------------------------------
public B() {
A a = new A();
a.var1 = 1;
a.var2 = 2; //default (o) //같은패키지
//a.var3 = 3; //private (x)
a.method01();
a.method02(); //default (o) //같은패키지
//a.method03(); //private (x)
}
}
2. protected와 default의 차이
- default: 같은 패키지 내에서만 접근 가능.
- protected: 같은 패키지 + 상속받은 클래스에서 super로 접근 가능.
예시
protected :
public class A {
/*
* protected는 기본적으로 같은 패키지기에서만 사용할 수 있습니다.
* default랑 접근 범위는 동일합니다.
* 단, 패키지가 다르더라도 상속관계에서 super를 통한 접근은 허용됨.
*/
protected boolean bool;
protected A() {}
protected void method() {}
}
3. 은닉화(Encapsulation)
잘못된 예 - 은닉화 없이 설계된 클래스
public class MyBirth {
public int day;
public int month;
public int year;
public String ssn; //주민번호
public void info() {
System.out.println("생일:" + year + "년" + month + "월" + day + "일");
System.out.println("주민번호:" + ssn);
}
}
문제점
- 멤버 변수에 바로 접근이 가능하므로 잘못된 값 저장 가능.
public class MainClass {
public static void main(String[] args) {
//변수를 public으로 열어두면, 잘못된 값(유효성 검증 불가)이 저장될 수 있습니다.
MyBirth me = new MyBirth();
me.year = 2023;
me.month = 11;
me.day = 35;
me.ssn = "내알빠? 이게뭔데?";
me.info();
}
}
생일:2023년11월35일
주민번호:내알빠? 이게뭔데?
이렇게 나올 수 있다.
개선된 예 - 은닉화와 getter, setter 활용
public class MyBirth {
//은닉 - 중요한 정보(멤버변수, 메서드) private으로 선언
private int day;
private int month;
private int year;
private String ssn;
/*
* 은닉 변수에 값에 접근할 때, 미리 생성해 놓은 getter/setter메서드를 사용해서 접근합니다.
*
* setter메서드
* 1. 은닉변수에 값을 저장하기 위한 메서드
* 2. 접근제어자를 public으로 선언하고 이름은 set멤버변수명 으로 지정
*
*/
public void setDay(int day) {
if(day < 0 || day > 31) {
System.out.println("잘못된 값인데요?");
return;
}
this.day = day;
}
/*
* getter메서드
* 1. 은닉변수의 값을 조회하기 위한 메서드
* 2. 접근제어자를 public으로 선언하고 이름은 get멤버변수명 으로 지정
*
*/
public int getDay() {
return day;
}
/*
* 1. month, year, ssn에 대한 getter, setter
*
* month - 1~12월 까지만 저장
* year - 1950~2023년 이하인 경우만 저장
* ssn - "-" 제거후에 13자리만 저장
*
*/
//setter
public void setMonth(int month) {
if(month < 1 || month > 12) {
System.out.println("잘못된 월 입니다");
return;
}
this.month = month;
}
//getter
public int getMonth() {
return month;
}
//setter
public void setYear(int year) {
if(year < 1950 || year > 2023) {
System.out.println("잘못된 년도 입니다");
return;
}
this.year = year;
}
//getter
public int getYear() {
return year;
}
//setter -ssn
public void setSsn(String ssn) {
ssn = ssn.replace("-", "");
if(ssn.length() != 13 ) {
System.out.println("길이는 13자리 입니다");
return;
}
this.ssn = ssn;
}
//getter
public String getSsn() {
return ssn;
}
Setter로 변수의 범위를 잡고 , Getter 메소드로 반환, set,get는 public으로 해서 private 변수에 접근을 했다.
사용
public class MainClass {
public static void main(String[] args) {
MyBirth me = new MyBirth();
//me.day = 100;
//값의 저장
me.setYear(2022);
me.setMonth(12);
me.setDay(30);
me.setSsn("123123-1231231");
//값의 사용
int year = me.getYear();
int month = me.getMonth();
int day = me.getDay();
String ssn = me.getSsn();
System.out.println(year + "년" + month + "월" + day + "일입니다");
System.out.println("주민번호:" + ssn);
}
}
4. 객체를 매개변수로 받는 경우
예제
public class Chef {
public void cooking() {
System.out.println("오늘은 내가 주방장~!");
}
}
public class Hotel {
//멤버변수
private Chef chef;
//생성자
//호텔이 생성될 때 초기값을 갖는다.
public Hotel() {
this.chef = new Chef();
}
//객체를 매개변수로 받는 setter
public void setChef(Chef chef) {
this.chef = chef;
}
//객체를 반환하는 getter
public Chef getChef() {
return chef;
}
}
public class MainClass {
public static void main(String[] args) {
//호텔객체생성
Hotel hotel = new Hotel();
//setter메서드의 사용법
//1st
hotel.setChef(new Chef());
//2nd
Chef c = new Chef();
hotel.setChef(c);
//getter메서드의 사용법
Chef chef = hotel.getChef();
chef.cooking();
}
}
정리
- **private**로 멤버 변수를 보호하고, getter와 setter로 값을 검증하여 설정.
- 객체 간 의존성을 낮추기 위해 setter를 사용.
- protected와 default의 차이를 이해하여 적절히 사용.