팩키지와 접근자
팩키지는 말 그대로 꾸러미이다.
자바는 비슷한 기능이나 비슷한 성격을 가진 클래스들을 관리하기 위해서 팩키지를 제공한다.
서류를 정리할 때 기준에 따라 각각의 서류철에 보관하는 것과 마찬가지이다.
package javabank;
public class Account {
private String accountNum;
private long balance;
public void deposit(long amt) {
balance = balance + amt;
}
public void withdraw(long amt) {
balance = balance - amt;
}
public long getBalance() {
return balance;
}
public static void main(String[] args) {
System.out.println("팩키지 테스트");
}
}
1라인의 package javabank; 의해서 Account 클래스는 javabank 팩키지에 속하게 된다.
팩키지를 선언한 소스를 컴파일 할 때는 반드시 -d 옵션을 주어 바이트코드가 생길 디렉토리를 지정해 주어야 한다.
만약 -d 옵션을 생략하면 팩키지가 적용되지 않는다.
예제를 실행하기전에 아래 그림과 같은 디렉토리 구조를 갖도록 한다.
bin 디렉토리는 바이트코드가 위치할 곳이다.
src 디렉토리는 자바 소스 파일이 위치할 곳이다.
소스에 팩키지 선언부가 있다면 src에 해당하는 팩키지명으로 서브 디렉토리를 만들어 소스를 그곳에 위치시키고 관리토록 하겠다.
아래 그림과 같이 디렉토리를 생성하고 src/javabank 디렉토리에 Account.java 파일을 복사한다.

준비가 되었다면 아래와 같이 컴파일한다.
C:\javaApp\bank\src\javabank>javac -d ../../bin Account.java C:\javaApp\bank\src\javabank>
컴파일 후 C:\javaApp\bank\bin 디렉토리로 이동해서 Account.class 파일이 생겼는지 확인한다.
C:\javaApp\bank\bin>dir
C 드라이브의 볼륨: S3A2219D002
볼륨 일련 번호: 4CBA-0648
C:\javaApp\javabank\bin 디렉터리
2008-03-07 오후 12:06 <DIR> .
2008-03-07 오후 12:06 <DIR> ..
2008-03-07 오후 12:06 <DIR> javabank
0개 파일 0 바이트
3개 디렉터리 12,990,201,856 바이트 남음
C:\javaApp\bank\bin>
Account.class 파일이 bin 디렉토리에 보이지 않고 대신 javabank 라는 디렉토리가 생겼다.
그럼 Account.class 파일은 어디에 있을까?
Account.class 파일은 C:\javaApp\bank\bin\javabank 디렉토리에서 찾을 수 있다.
이제 팩키지 예제의 디렉토리 구조는 아래와 같다.
이젠 팩키지가 적용된 클래스 파일을 실행한다.
C:\javaApp\bank\bin>java javabank.Account 팩키지 테스트 C:\javaApp\bank\bin>
우리는 Accont.java 를 컴파일할 때 -d옵션으로 C:\javaApp\bank\bin 디렉토리를 지정했다.
그래서 bin디렉토리에 바이트코드가 생긴 것이다.
사실 bin디렉토리에는 팩키지명으로 지정해준 javabank 란 디렉토리 밖에는 없지만 JVM은 bin디렉토리에 javabank.Account.class
파일이 있다고 이해한다.
팩키지가 적용된 클래스에 대해서는 팩키지명.클래스명이 완전한 클래스명이다.
따라서 Account클래스를 실행하기 위해서는 C:\javaApp\bank\bin디렉토리에서 아래와 같이 실행해야 한다.
java javabank.Account
접근자
접근자는 외부에서 접근할 수 있는지 여부를 결정한다.
접근자는 2단계 접근 제어를 제공한다.
1단계 접근 제어는 접근자가 클래스 선언부에 쓰일 때이다.
public 접근자가 Account의 클래스 선언부에 쓰인 경우
package javabank;
public class Account {
// 구현부
}
디폴트 접근자가 Account의 클래스 선언부에 쓰인 경우
package javabank;
class Account {
// 구현부
}
| 1단계 접근 제어 : 접근자가 클래스 선언부에 쓰일 경우 | |
|---|---|
| public |
모든 팩키지에서 접근할 수 있다. |
| default |
같은 팩키지에서만 접근할 수 있다. |
다음은 public 접근자가 Account의 클래스 선언부에 쓰인 경우 팩키지가 다른 객체에서 Account 객체를 참조한 예이다.
package example;
class BankSystem {
public void createAccount() {
// javabank의 Account객체를 생성할 수 있습니다.
javabank.Account ac = new javabank.Account();
}
// javabank의 Account객체의 레퍼런스를 파라미터로 받을 수 있습니다.
public void deposit(javabank.Account account, long amount) {
account.deposit(amount);
}
}
아래 그림은 javabank 팩키지에 있는 클래스가 모두 클래스 선언부에 public 으로 접근자가 지정되어 있는 경우를 그린 것이다.
그림에서 +는 public을 의미한다.
Bank, Customer, Account는 모든 팩키지에서 접근할 수 있다.
그림에서 example팩키지에 있는 BankSystem는 javabank 팩키지의 모든 클래스를 접근할 수 있다.
이 말은 위의 BankSystem 소스에서 처럼 Account 객체를 생성하거나 메소드의 파라미터로 전달받을 수 있음을 의미한다.

다음은 Bank, Customer, Account 소스에서 클래스 선언부가 default접근자로 지정되어 있는 경우를 그린 것이다.

이 경우 다른 팩키지에 있는 BankSystem 클래스에서는 Bank, Customer, Account 는 보이지 않는다.(그림은 희미하게 표현했음.)
BankSystem에서 Bank, Customer, Account 객체에 대한 레퍼런스를 얻으려고 하면 컴파일 에러가 난다.
즉, BankSystem.java 를 컴파일하면 7라인과 11라인에서 javabank.Account is not visible 이란 컴파일 에러를 만나게 된다.
| 2단계 접근 제어 : 접근자가 멤버에 쓰일 경우 | |
|---|---|
| public | 모든 팩키지에서 접근 가능 |
| protected |
같은 팩키지에서만 접근 가능 다른 팩키지에 있더라도 상속 관계에 있는 자식 클래스에서 부모클래스의 protected접근자로 지정된 멤버는 접근 가능 |
| default | 같은 팩키지에서만 접근 가능 |
| private | 외부에서 접근할 수 없음 |
접근자는 클래스 선언부에 쓰인 1단계 접근 제어가 통과되면 두번째로 해당 객체의 멤버(변수와 메소드)에 대해서 적용된다.
멤버에 적용되는 가장 쉬운 접근자는 public과 private이다.
멤버의 접근자가 public이면 모든 팩키지에서 접근할 수 있습니다.
멤버의 접근자가 private이면 접근할 수 없다.
디폴트 접근자는 같은 팩키지에서만 접근할 수 있다.
protected는 디폴트 접근자보다 접근 허용범위가 더 넓다.
일단 디폴트 접근자처럼 같은 팩키지에서 접근할 수 있다.
거기에 더하여, 상속 관계에 있는 자식 클래스가 다른 팩키지에 속한 부모클래스의 멤버에 접근할 때, 이 멤버 접근자가 protected면
접근할 수 있다.
그림에서 #는 protected을 의미한다.

클래스를 설계할 때는 아래 사항은 객체 지향 프로그래밍의 기본이므로 지키도록 한다.
- 멤버변수를 private 로 선언
- private 선언된 멤버변수에 대한 setters, getters 중 설계상 필요없는 메소드는 삭제
웹사이트의 회원 클래스를 위 사항을 지켜 구현해 본다.
package net.java_school.user;
public class User {
private String id;
private String password;
private String name;
private String email;
private String mobile;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
}
- 다음 : 상속
- 이전 : 연산자, if문과 반복문
