WhatYourName.java 파일 안에는 A 클래스와 B 클래스가 존재하고 A 클래스가 main을 포함한다고 하자.
만약 WhatYourName.java를 컴파일한다면 A.class, B.class 파일이 하나씩 만들어진다.
WhatYourName.java 파일이 PS 폴더 안에 있다고 해보자. 우리는 명령 프롬프트로 컴파일을 할 때 다음과 같이 진행할 것이다.
C:\PS>javac WhatYourName.java
이때의 C:\PS
가 현재 디렉토리이다. 현재 디렉토리는 실행 중인 프로그램의 작업 디렉토리를 말한다. javac
는 현재 디렉토리에서 파일을 찾아 컴파일하고 컴파일된 파일을 해당 디렉토리에 생성한다.
하지만, 예를 들어 PS 폴더 아래에 MyClass라는 폴더를 생성하여 A.class와 B.class를 옮겨 놓는다고 하자.
C:\PS>java WhatYourName.java
main 함수를 실행시킬 때, A 클래스와 B 클래스에 대한 정보를 가져와야 한다. 그러나 현재 디렉토리에는 두 클래스 파일이 존재하지 않기 때문에 실행이 정상적으로 진행되지 않는다.
클래스를 찾는 경로를 별도로 지시하는 것이 가능한데 이것이 클래스 패스(Class Path)이다.
" . "은 현재 위치를 뜻하고 " ; "로 경로들을 구분한다.
절대 경로
C:\PS>set classpath=.;C:\PS\MyClass
상대 경로
C:\PS>set classpath=.;.\MyClass
상대 경로로 지정하면 현재 디렉토리의 위치가 바뀌어도 아래의 디렉토리도 같이 바뀌기 때문에, 상대 경로로 클래스 패스를 지정하는 것이 더 선호되는 방법이다.
우리가 모든 클래스를 정의하기 보다는 다른 사이트 등에서 가져와서 사용하는 경우가 많다. 하지만 여러 사이트에서 클래스를 가져올 때, 이름이 같은 경우가 있을 수 있다.
먼저, 공간에서의 충돌이 발생할 수 있다. 같은 이름의 클래스 파일을 같은 곳에 둘 수 없기 때문에 디렉토리가 달라져야 한다.
또, 접근 방법에서의 충돌이 발생한다. 인스턴스 선언시에 어떤 클래스를 가져와야 하는지 알 수 없기 때문에 이름을 달리하거나 디렉토리를 명시해줘야 한다.
이러한 문제점들을 해결하기 위해 패키지 선언을 해줘야 한다.
예를 들어, "wxfx.com"의 smart 그룹에서 Circle.class를 만들고 "fxmx.com"의 simple 그룹에서 Circle.class를 만들었다고 해보자.
// wxfx.com의 smart 그룹의 Circle.class
package com.wxfx.smart;
public class Circle {
...
// fxmx.com의 simple 그룹의 Circle.class
package com.fxmx.simple;
public class Circle {
...
패키지의 이름은 모두 소문자로 구성되고, 인터넷 도메인 이름의 역순으로 이름을 구성한다.
인스턴스 생성 시에도 모두 명시해주어야 한다.
com.wxfx.smart.Circle c1 = new com.wxfx.smart.Circle(3.5);
com.fxmx.simple.Circle c2 = new com.fxmx.simple.Circle(5.5);
컴파일 시에 JVM은 클래스 패스를 기준으로 "com"을 찾는다. 따라서 현재 디렉토리에 "com"이 포함되어 있어야 한다.
인스턴스 생성때마다 패키지 명을 모두 적기 힘들기 때문에 import 선언을 통해서 이후에 쉽게 사용한다.