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의 차이를 이해하여 적절히 사용.