프로젝트를 개발하다 보면 적게는 수십 개, 많게는 수백 개의 클래스를 작성해야 한다. 클래스를 체계적으로 관리하지 않으면 클래스 간의 관계가 뒤엉켜서 복잡하고 난해한 프로그램이 되어 결국 유지 보수가 어렵게 된다. 자바에서는 클래스를 체계적으로 관리하기 위해 패키지(package)를 사용한다. 우리가 폴더를 만들어 파일을 저장 관리하듯이 패키지를 만들어 클래스를 저장 관리한다. 패키지의 물리적인 형태는 파일 시스템의 폴더이다.
패키지는 단순히 파일시스템의 폴더 기능만 하는 것이 아니라 클래스의 일부분이다. 패키지는 클래스를 유일하게 만들어주는 식별자 역할을 한다. 클래스 이름이 동일하더라도 패키지가 다르면 다른 클래스로 인식한다. 클래스의 전체 이름은 "패키지명+클래스명" 인데 패키지가 상, 하위로 구분되어 있다면 ( . ) 도트 를 사용해서 다음과 같이 표현한다.
상위패키지.하위패키지.클래스
예를 들어 Car 클래스가 com.mycompany 패키지에 속해 있다면 Car 클래스의 전체 이름은 com.mycompany.Car가 되고 실제 파일 시스템에서는 com\mycompany 폴더에 Car.class가 위치한다. 패키지가 중요한 이유는 클래스만 따로 복사해서 다른 곳으로 이동하면 클래스는 사용할 수 없기 때문이다. 예를 들어 Car 클래스가 com.mycompany 패키지에 소속되어 있을 경우, 파일 시스템 com\yourcompany 폴더에 Car.class를 저장하면 Car 클래스를 사용할 수 없다. 클래스를 이동할 경우에는 패키지 전체를 이동시켜야 한다.
패키지 선언
패키지는 클래스를 컴파일 하는 과정에서 자동으로 생성되는 폴더이다. 컴파일러는 클래스에 포함 되어 있는 패키지 선언을 보고, 파일 시스템의 폴더로 자동 생성시킨다. 다음은 패키지를 선언하는 방법이다.
package 상위패키지.하위패키지;
public class ClassName { ... }
패키지 이름은 개발자가 임의대로 지어주면 되지만, 여기에도 지켜야할 몇 가지 규칙이 있다.
- 숫자로 시작해서는 안되고, _, $를 제외한 특수 문자를 사용해서는 안 된다.
- java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 사용해서는 안된다.
- 모두 소문자로 작성하는 것이 관례이다
여러 개발 회사가 함께 참여하는 대규모 프로젝트나, 다른 회사의 패키지를 이용해서 개발할 경우, 패키지 이름이 중복될 가능성이 있다. 그래서 회사들 간에 패키지가 서로 중복되지 않도록 흔히 회사의 도메인 이름으로 패키지를 만든다. 도메인은 등록 기관에서 유일한 이름이 되도록 검증되었기 때문에 도메인 이름으로 패키지를 만들면 다른 회사의 패키지와 중복되는 경우가 발생하지 않는다. 도메인 이름으로 패키지 이름을 만들 경우, 도메인 이름 역순으로 패키지 이름을 지어주는데, 그 이유는 포괄적인 이름이 상위 패키지가 되도록 하기 위해서이다. 그리고 마지막에는 프로젝트 이름을 붗여주는 것이 관례이다.
com.samsung.projectname
com.hyndai.projectname
패키지 선인이 포함된 클래스 컴파일
패키지 선언이 포홤된 클래스를 명령 프롬프트에서 컴파일할 경우, 단순히 javac ClassName.java로 컴파일해서는 패키지 폴더가 생성되지 않는다. 패키지 폴더가 자동으로 생성되려면 javac 명령어 다음에 -d 옵션을 추가하고 패키지가 생성될 경로를 다음과 같이 지정해야 한다.
javac -d . ClassName.java // 현재 폴더 내에 생성
javac -d ..\bin ClassName.java // 현재 폴더와 같은 위치의 bin 폴더에 생성
javac -d C:\Temp\bin ClassName.java // C:\Temp\bin 폴더에 생성
패키지에 소속된 클래스를 명령 프롬프트에서 실행하려면 바이트 코드 파일(*.class)이 있는 폴더에서 java 명령어를 사용해서는 안된다. 패키지는 클래스의 일부분이므로 패키지가 시작하는 폴더에서 java 명령어를 사용해야한다.
import문
같은 패키지에 속하는 클래스들은 아무런 조건 없이 다른 클래스를 사용할 수 있지만 다른 패키지에 속하는 클래스를 사용하려면 두 가지 방법 중 하나를 선택해야 한다. 첫 번째 방법은 패키지와 클래스를 모두 기술하는 것이다. 다음은 com.hankook 패키지에 소속된 Tire 클래스를 이용해서 필드를 선언하고 객체를 생성한 것이다.
package com.mycompany;
public class Car {
com.hankook.Tire tire = new com.hankook.Tire();
}
패키지 이름이 짧을 경우에는 불편함이 없겠지만, 패키지 이름이 길거나 이렇게 사용해야 할 클래스 수가 많다면 패키지 이름을 붙인다는 것은 코드를 난잡하게 할 수 있다. 그래서 두 번째 방법인 import문을 주로 사용한다. 사용하고자 하는 패키지를 import문으로 선언하고, 클래스를 사용할 때에는 패키지를 생략하는 것이다.
package com.mycompany;
import com.hankook.Tire;
[ 또는 import com.hankook.*; ]
public class Car {
Tire tire = new Tire();
}
import문이 작성되는 위치는 패키지 선언과 클래스 선언 사이다. 패키지에 포함된 다수의 클래스를 사용해야 한다면 클래스별로 import문을 작성할 필요 없이 클래스 이름을 생략하고 대신 *를 사용해서 import문을 한 번 작성하면 된다. *는 패키지에 속하는 모든 클래스들을 의미한다. import문의 개수는 제한이 없고 필요한 패키지가 있다면 얼마든지 추가할 수 있다. 주의할 점은 import문으로 지정된 패키지의 하위 패키지는 import 대상이 아니다. 만약 하위 패키지에 있는 클래스들도 사용하고 싶다면 같은 방법으로 import문을 하나 더 작성해야 한다.
패키지 이름 전체를 기술하는 첫 번째 방법이 꼭 필요한 경우가 있는데, 서로 다른 패키지에 동일한 클래스 이름이 존재하고, 두 패키지가 모두 import 되어 있을 경우이다. 자바 컴파일러는 어떤 패키지에서 클래스를 로딩할지 결정할 수 없기 때문에 컴파일 에러가 발생한다. 이 경우에는 정확하게 패키지 이름 전체를 기술해야 한다.
세 패키지를 모두 사용하는 Car.java 소스를 보자. Tire 클래스는 import 된 두 패키지에 모두 있기 때문에 12 ~ 13라인처럼 패키지 이름과 함께 전체 이름이 기술되어야 한다. 9라인의 Engine 클래스는 hyndai 패키지에만 존재하기 때문에 아무런 문제가 없고, 10 ~ 11 라인의 SnowTrie과 BigWidthTire 클래스도 각각 hankook, kumho 패키지에만 존재하기 때문에 아무런 문제가 없다.
// SnowTire.java
package sec12.exam03_import.hankook;
public class SnowTire { }
// Tire.java
package sec12.exam03_import.hankook;
public class Tire { }
// BigWithTire.java
package sec12.exam03_import.kumho;
public lass BigWidthTire { }
// Tire.java
package sec12.exam03_import.kumho;
public class Tire { }
// Engine.java
package sec12.exam03_import.hyndai;
public class Engine { }
// Car.java
package sec12.exam03_import.mycompany
package sec12.exam03_import.hankook.*;
package sec12.exam03_import.hyndai.Engine;
package sec12.exam03_import.kumho.*;
public class Car {
// 필드
Engine engine = new Engine();
SnowTire tire1 = new SnowTire();
BigWidthTire tire2 = new BigWidthTire();
package sec12.exam03_import.hankook.Tire = tire3 = new package sec12.exam03_import.hankook.Tire();
package sec12.exam03_import.kumho.Tire = new package sec12.exam03_import.kumho.Tire();
}
'Java 길찾기 > 이것이 자바다' 카테고리의 다른 글
[Java] Getter와 Setter 메소드 (0) | 2022.01.17 |
---|---|
[Java] 접근 제한자 (0) | 2022.01.14 |
[Java] final 필드와 상수 (0) | 2022.01.12 |
[Java] 정적 멤버와 static (0) | 2022.01.11 |
[Java] 인스턴스 멤버와 this (0) | 2022.01.10 |