[STUDY HALLE] 7주차 과제: 패키지

2 minute read

학습 목표

자바의 패키지에 대해 학습하세요.

  • package 키워드
  • import 키워드
  • 클래스패스
  • CLASSPATH 환경변수
  • classpath 옵션
  • 접근지시자

Deadline: ~2021/01/02 13:00

package 키워드

패키지는 비슷한 성격의 자바 클래스들을 모아놓는 자바의 디렉토리이다. 따라서 클래스 파일의 경로를 나타내는 키워드가 되므로 당연히 한 개만 존재하여야 하고, 이것을 각 클래스 파일의 첫 번째 문장으로 표시해야한다. 패키지는 두 가지로 분류된다.

  1. Built-in Package : java에서 제공하는 패키지
  2. User-defined Package : 사용자가 정의하여 사용하는 패키지

오라클에서 제공하는 문서에 따르면 패키지 이름과 클래스, 인터페이스의 이름의 충돌을 방지하기 위해 소문자만 사용해야 한다. 또한 도메인 주소를 뒤집어 사용하는데, 예를 들어 네이버에서 mypackage라는 패키지를 생성할 경우 com.naver.mypackage 라고 생성한다.

import 키워드

다른 패키지에 속한 클래스를 사용하기 위한 키워드이다. 원래 다른 패키지의 클래스를 사용하기 위해서는 패키지명을 포함한 클래스명을 모두 명시해야 한다. 이러한 번거로움을 덜고자 import 키워드를 이용해 패키지명을 포함한 클래스명을 미리 명시해두어서 패키지명은 생략할 수 있도록 해준다.

import java.util.ArrayList;
import java.util.Map;

import java.util.*;
// import java.*  => X

위와 같이 사용하고자 하는 클래스를 import해주면 되는데, 동일한 패키지의 모든 클래스를 import하려면 와일드카드(*)를 이용하면 된다. 이때, 와일드카드를 이용할 경우 하위 패키지의 클래스까지 포함하지 않는 것에 주의하여야 한다. 그리고 와일드카드를 이용하더라도 사용하지 않는 클래스는 자동으로 무시되어 성능 차이는 없지만, 남발하는 것은 좋지 않다는 의견(링크)이 있다.

패키지가 다르면 클래스명을 중복하여 사용하는 것이 가능하다. 그렇다면 import한 클래스명이 이미 클래스 파일에 존재하거나, 서로 다른 두 패키지에서 import한 클래스명이 겹치면 어떻게 될까?

import com.example.ex1.A;
import com.example.ex2.A;

결론은 컴파일 에러가 발생한다. 컴파일러 입장에서는 import문을 참고하여 코드에서 사용된 클래스를 식별해야하는데, 클래스 이름이 중복되므로 어느 import문을 참조할지에 대한 애매함(ambiguous)이 문제가 된다. 이런 경우에는 어쩔 수 없이 패키지를 포함한 클래스명을 사용하여 두 개의 클래스를 구분해주어야 한다.
와일드카드(*)를 남발하지 말아야하는 이유 중 하나가 이렇게 클래스명이 중복되는 상황이 발생할 수 있는 것이다.

패키지명을 생략하고 클래스에 접근하는 import 키워드에서 한 발 더 나아가 클래스명까지 생략하여 메소드에 바로 접근할 수 있게 해주는 static import도 있다.

import static java.lang.System.out;

public class test {
  public static void main(String[] args){
    // System 생략
    out.println("hello world");
  }
}

클래스패스

클래스패스는 자바의 JVM이 프로그램을 실행할 때 클래스 파일(.class)을 찾는 기준 경로이다. 클래스 파일이 포함된 폴더의 경로를 콜론(:)으로 구분지으며(윈도우는 세미콜론), 클래스패스를 따로 지정하지 않으면 JVM은 현재 디렉토리에서 클래스를 찾아준다. 클래스패스를 따로 지정하는 방법으로는 다음의 두가지 방법이 있다.

(1) -classpath 옵션

java -classpath ".;lib" example 

위와 같이 자바를 실행할 때 옵션으로 직접 명시해줄 수 있다. “,;lib” 구문을 해석하면, “우선 .(현재 디렉토리)에서 클래스를 찾고, 없으면 lib(현재 디렉토리의 하위 디렉토리)에서 클래스를 찾아라” 이다. 이 방법은 실행할 때마다 직접 지정해줘야 하는 번거로움이 있다.

(2) CLASSPATH 환경변수
환경변수의 이름을 CLASSPATH로 하여 클래스패스의 목록을 나열해주면, JVM이 이것을 참조하여 클래스를 로드할 수 있게 된다. 실행할 때마다 편리하지만, 운영체제가 변경되면 클래스 패스가 사라져 이식성 면에서 불리할 수 있다는 말이 있다. 그런데 사실 운영체제를 변경하면서 환경변수를 새로 지정하는 번거로움보다는 실행할 때마다 명시하는 번거로움이 10배는 크지 않을까?

접근제어자

접근제어자(Access Modifier)는 멤버 또는 클래스를 사용할 때, 접근 권한을 정해주는 역할을 한다. 자바에서는 네가지 접근자를 사용하는데, 순서대로 더 많은 접근을 허용한다.

  • private : 같은 클래스에서만 접근 가능
  • default : 접근제어자를 별도로 명시하지 않는 경우. 같은 패키지에서만 접근 가능
  • protected : 같은 패키지 혹은 상속받은 경우 사용 가능.
  • public : 어디서든 접근 가능
  같은 클래스 같은 패키지 자식 클래스 모든 클래스
private O X X X
default O O X X
protected O O O X
public O O O O

그렇다면 이런 접근 제한을 왜 하는 것 일까? 누구나 사용 가능하도록 모두 public으로 선언하면 왜 안 될까? 그 이유는 객체지향 프로그래밍의 주요 개념 중 하나인 정보 은닉때문이다. 캡슐화된 객체 내부가 노출되어 정보가 손상되거나 오용되는 것을 막기 위해서 접근 권한을 나누고, 필요한 만큼의 권한만 부여하는 것이다.

참고문헌

https://wikidocs.net/book/31 https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html https://www.javatpoint.com/package https://opentutorials.org/course/1223/5527

Leave a comment