자바의 패키지에 대해 학습하세요
학습할 것
- package 키워드
- import 키워드
- 클래스패스
- CLASSPATH 환경변수
- classpath 옵션
package c.javapackage
패키지란, 클래스의 묶음이다. 패키지에는 클래스 또는 인터페이스를 포함시킬 수 있으며, 서로 관련된 클래스들끼리 그룹 단위로 묶어 놓음으로써 클래스를 효율적으로 관리한다.
같은 이름의 클래스라도 서로 다른 패키지에 존재하는 것이 가능하므로, 자신만의 패키지 체계를 유지함으로써 다른 개발자가 개발한 클래스 라이브러리의 클래스와 이름이 충돌하는 것을 피할 수 있다.
예를 들어 String 클래스의 패키지는 java.lang이며 FQCN은 java.lang.String이 된다.
패키지를 선언하는 것은 다음과 같다. 클래스나 인터페이스의 소스파일(.java)에 다음과 같은 한 줄을 적어주면 된다.
package 패키지명;
위와 같은 패키지 선언문은 반드시 소스파일에서 주석과 공백을 제외한 첫 번째 문장이어야 하며, 하나의 소스파일에 단 한번만 선언될 수 있다.
패키지명은 대소문자 모두 허용하지만, 클래스명과 쉽게 구분하기 위해서 소문자로 하는 것을 원칙으로 하고 있다.
자바의 모든 클래스는 하나의 패키지에 포함되어야 한다. 만일 소스파일을 작성할 때 패키지를 지정하지 않으면, 자바에서 기본적으로 제공하는 이름없는 패키지에 포함된다. 따라서 패키지를 지정하지 않은 모든 클래스들은 같은 패키지에 속하게 된다.
import 패키지명.클래스명
소스코드를 작성할 때 다른 패키지의 클래스를 사용하려면 패키지명이 포함된 클래스 이름을 사용해야 한다. 하지만, 매번 패키지명을 붙여서 작성하기엔 불편하다.
클래스의 코드를 작성하기 전에 import문으로 사용하고자 하는 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명을 생략할 수 있다.
import문의 역할은 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공하는 것이다. 컴파일 시에 컴파일러는 import문을 통해 소스파일에 사용된 클래스들의 패키지를 알아 낸 다음, 모든 클래스 이름 앞에 패키지명을 붙여 준다.
모든 소스파일(.java)에서 import문은 package문 다음에, 그리고 클래스 선언문 이전에 위치해야 한다. import문은 package문과 달리 한 소스파일에 여러 번 선언할 수 있다.
import문을 선언하는 방법은 다음과 같다.
import 패키지명.클래스명;
import 패키지명.*;
키워드 import와 패키지명을 생략하고자 하는 클래스의 이름을 패키지명과 함께 써준다.
클래스 이름을 지정해주는 대신 ‘*‘을 사용하면, import문을 여러 번 사용하는 대신 한 문장으로 처리할 수 있다. 예를 들어 다음과 같이 줄일 수 있다.
import java.util.*;
import java.text.*;
위의 두 문장을 아래와 같이 할 수 없다.
import java.*;
java.lang 패키지는 자바프로그래밍에 가장 기본이 되는 클래스들을 포함하고 있는 패키지이다. java.lang 패키지는 다른 패키지들과 달리 모든 소스파일에 묵시적으로 선언되어 있다. 따라서 System과 String 같은 java.lang 패키지에 속한 클래스들은 import문 없이 사용할 수 있었던 것이다.
import문을 사용하면 클래스의 패키지명을 생략할 수 있는 것과 같이 static import문을 사용하면 static멤버를 호출할 때 클래스 이름을 생략할 수 있다. 특정 클래스의 static멤버를 자주 사용할 때 편리하다.
import static java.lang.Integer.*; // Integer클래스의 모든 static메서드
import static java.lang.Math.random; // Math.random()만.
import static java.lang.System.out; // System.out을 out만으로 참조가능.
위와 같이 선언하였다면 다음과 같이 생략이 가능해진다.
System.out.println(Math.random());
예제
import static java.lang.System.out;
import static java.lang.Math.*;
class App {
public static void main(String[] args) {
System.out.println(Math.random());
System.out.println("Math.PI : " + Math.PI);
}
}
클래스를 찾기위한 경로
JVM이(누가) 프로그램을 실행할 때(언제), 클래스파일을 찾는 데(왜) 클래스 패스(기준이 되는 파일 경로)(무엇을)를 사용한다.
자바의 실행과정을 살펴보면 소스 코드(.java)를 컴파일하면 소스 코드가 바이트 코드(바이너리 형태의 .class 파일)로 변환된다. Java runtime(java 또는 jre)으로 이 파일(바이너리 형태의 .class 파일)에 포함된 명령을 실행하려면, 이 파일을 찾을 수 있어야 한다. 이 때 classpath에 지정된 경로를 사용하여 .class 파일을 찾는다.
classpath는 .class 파일이 포함된 디렉토리와 파일을 콜론으로 구분한 목록인데, java runtime은 이 classpath에 지정된 경로를 모두 검색해서 특정 클래스에 대한 코드가 포함된 .class 파일을 찾는다.
classpath를 지정할 수 있는 방법은 두 가지가 있다.
classpath는 콜론 ‘:’으로 구분된 디렉토리 및 파일 목록으로 다음 세 가지 유형의 파일과 디렉토리를 classpath에 지정할 수 있다.
CLASSPATH=.;C:\Program Files\Java\jdk-10.0.1\lib\tools.jar
컴퓨터 시스템 변수 설정을 통해 지정할 수 있다.
JVM이 시작될 때 JVM의 클래스 로더는 이 환경 변수를 호출한다. 그래서 환경 변수에 설정되어 있는 디렉토리가 호출되면 그 디렉토리에 있는 클래스들을 먼저 JVM에 로드한다. 그러므로 CLASSPATH 환경 변수에는 필스 클래스들이 위치한 디렉토리를 등록하도록 한다.
컴퓨터 시스템 변수 설정을 통해 지정할 수 있다.
javac <options> <souce files>
컴파일러가 컴파일 하기 위해서 필요로 하는 참조할 클래스 파일들을 찾기 위해서 컴파일시 파일 경로를 지정해주는
옵션
Hello.java
파일이 C:\Java
디렉터리에 존재하고,
필요한 클래스 파일들이 C:\Java\Engclasses
에 위치한다면,
javac -classpath C:\Java\Engclasses C:\Java\Hello.java
로 해주면 된다.
만약 참조할 클래스 파일들이 그 외의 다른 디렉터리, 그리고 현 디렉토리에도 존재한다면,
javac -classpath .;C:\Java\Engclasses;C;\Java\Korclasses C:\Java\Hello.java
과 같이; 으로 구분해줄 수 있다. ( . 은 현 디렉토리, .. 은 현 디렉토리에서 상위 디렉토리를 의미한다.)
또한 classpath 대신 단축어인 cp를 사용해도 된다.
javac -cp .;C:\Java\Engclasses;C;\Java\Korclasses C:\Java\Hello.java
접근 제어자(지시자)는 멤버 또는 클래스에 사용되어, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할을 한다. 접근 제어자가 default임을 알리기 위해 실제로 default를 붙이지는 않는다. 클래스나 멤버변수, 메서드, 생성자에 접근 제어자가 지정되어 있지 않다면, 접근 제어자가 default임을 뜻한다.
public은 접근 제한이 전혀 없고, private은 같은 클래스 내에서만 사용하도록 제한하는 가장 높은 제한이다. 그리고 default는 같은 패키지 내의 클래스에서만 접근이 가능하도록 하는 것이다.
protected는 패키지에 관계없이 상속관계에 있는 자손클래스에서 접근할 수 있도록 하는 것이 제한목적이지만, 같은 패키지 내에서도 접근이 가능하다.