package 키워드
패키지란
- 자바에서 패키지는 연관있는 클래스들을 묶는데에 사용된다
- 이를 사용하면 name conflict를 막고 보다 maintainable한 코드를 작성할 수 있다
패키지 종류
- Build-in Packages (JAVA API 로부터의 패키지)
- 자바 8까지
rt.jar
에 포함된 라이브러리를 포함
- 자바 9이상부터는
jmods
디렉토리에 존재
BootStrap ClassLoader
가 있기 때문에 Built-in 패키지를 사용할 수 있는 것
- User-defined Packages (개발자가 직접 생성한 패키지)
FQCN
- Full Qualified Class Name의 약자
- 모든 클래스에는 정의된 클래스 이름 + 패키지 이름이 있으며 이 둘을 합쳐야 완전하게 하나의 클래스를 지칭하게 됨 (클래스 이름 중복 등이 가능하므로)
- 예로,
String
클래스의 패키지는 java.lang
, FQCN은 java.lang.String
- 만약, 서로 다른 패키지의 같은 클래스명을 가진 클래스를 한 클래스에서 사용해야 할 경우, 최소 둘 중 하나는 FQCN을 적어주어야 한다
class MyClass {
package dev.gmelon.a;
}
---
class MyClass {
package dev.gmelon.b;
}
---
class Client {
import dev.gmelon.a.MyClass;
// import dev.gmelon.b.MyClass; // 컴파일 오류
MyClass myClassA = new MyClass(); // 패키지 a의 MyClass
dev.gmelon.b.MyClass myClassB = new dev.gmelon.b.MyClass(); // 패키지 b의 MyClass
}
패키지 생성하기
- 자바는 파일시스템의
디렉토리
를 패키지로 사용
- 패키지 이름과 위치한 폴더의 이름이 같아야 함
- 예를 들어,
dev.gmelon.spring
이라는 패키지를 만들고 싶으면
- 아래와 같이 디렉토리를 구성하고
spring
폴더 하위에 클래스 파일을 생성하면 됨
└── dev
└── gmelon
└── spring
└── MyClass.java
MyClass.java
의 상단에는 현재 클래스 파일의 패키지를 나타내기 위해 package
키워드를 사용
- 클래스는 하나의 패키지에만 포함될 수 있으며 패키지 선언문은 소스 코드 제일 처음에 작성되어야 함
package dev.gmelon.spring;
class MyClass {
...
}
unnamed default package
- 클래스 파일에 패키지를 (
package
키워드로) 명시하지 않으면, default package
에 소속된다
- 이러한 클래스는
import
키워드로 불러올 수 없다
- 다만, 동일하게 패키지 명을 작성하지 않아
default package
에 속한 다른 클래스는 이를 불러올 수 있다.
default
패키지는 최상단에서만 가능 (java
폴더 바로 하단)
import 키워드
- 원래는 클래스 사용 시
패키지명이 포함된 클래스명 전체
를 적어주어야 사용할 수 있다
- import 문을 사용해 패키지를 import하면 패키지명을 제외하고 클래스명 만으로 클래스를 사용할 수 있다
- import 문은 package 키워드 다음, 클래스 선언문 이전에 위치
import 하지 않아도 되는 패키지
java.lang
패키지에 한하여 별도의 import 문 없이도 사용이 가능하다
- 같은 패키지의 클래스는 import 없이도 사용 가능하다
- 다만 같은 패키지 내라도 하위 패키지에 포함된 클래스라면 import가 필요하다
import 종류
- import는
패키지
또는 패키지 내부의 개별 클래스
에 대하여 수행할 수 있다
import package.name.MyClass; // 단일 클래스를 import
import package.name.*; // package.name 패키지 내의 모든 클래스를 import
MyClass myClass = new MyClass; // package.name.MyClass 를 import 했으므로 사용 가능
static import
- 자바 1.5 버전에서 추가된 기능으로, 클래스 이름을 따로 선언할 필요 없이 static 멤버에 접근이 가능
- 아래는 사용 예시
assertThat()
은 Assertions
클래스의 static method
// 이전 방식 (import 없이 클래스명 전체와 함께 사용)
Assertions.assertThat(1).isEqualTo(1);
// static import 사용
import static org.assertj.core.api.Assertions.assertThat;
// 아래도 가능
// import static org.assertj.core.api.Assertions.*;
...
assertThat(1).isEqualTo(1); // static 메소드명 만으로 사용 가능하다
클래스패스
- JVM이 프로그램을 실행할 때 클래스 파일을 찾는데 기준이 되는 경로 를 말함
- 자바 런타임은
콜론(mac & linux, windows는 세미콜론)
으로 구분된 경로 (클래스 패스)를 모두 참조해 필요한 클래스 파일을 찾는다
- 클래스 패스 내에 동일한 클래스가 존재한다면, 먼저 발견된 클래스를 사용한다
- 클래스패스는 디렉토리 뿐만 아니라
.zip
, .jar
파일로도 지정 가능하다
Runtime ClassPath vs Compiletime ClassPath
- 자바 프로그램은 컴파일 될 때도 ClassPath가 필요하지만, 실행 시에도 ClassPath가 필요하다
- 컴파일 시와 실행 시에 모두 사용하는 클래스에 대한 정보가 필요한데,
- ClassPath 정보는 컴파일 시 클래스 파일에 포함되지 않기 때문
- 추가로, Compile 시엔 필요 없지만 Runtime 시에만 필요한 라이브러리 들도 존재
- 따라서, Compile 시에 적은 ClassPath를 Runtime에 적지 않으면 클래스를 찾을 수 없다는 오류가 발생할 수도 있다!
gradle과 ClassPath
gradle.build
에 dependency를 추가하면 해당 라이브러리들은 ~/.m2/repository
아래에 저장된다
- 그 후, 만약 gradle로 빌드까지 한다면 gradle은 이미 어떤 외부 라이브러리를 사용하는지 알고 있기 때문에 참조해서 알아서 빌드를 해줌
- Intellij로 빌드를 하게 되면, 사용하고 있는 외부 라이브러리를 알아내서
-classpath
옵션으로 넣어줌
CLASSPATH 환경변수
환경변수란
- 컴퓨터에서 프로세스가 동작하는 방식에 영향을 미치는 동적인 값들의 모임
- OS에서 프로세스들을 생성할 때 이 값을 참조
- 최신 JVM에서는 기본 라이브러리는 ClassPath 설정 없이도 사용이 가능하다
- 실제 개발 시엔 환경변수로 ClassPath를 설정하게 되면 모든 프로젝트에 전역적으로 설정되는 문제가 있어서 잘 사용하지 않음
- 대신, 프로젝트 별로
-classpath
옵션을 사용
-classpath 옵션
- 컴파일 시에 자바 컴파일러가 참조할 클래스 파일들의 경로를 명시
javac -classpath <디렉토리>
와 같이 사용
- 예를 들어
Main.java
를 컴파일하기 위해 코드 내부에서 참조하는 클래스 파일들이 현재 디렉토리와 a/b
라는 디렉토리에 위치한다면 아래와 같이 할 수 있다
javac -classpath .:a/b ./Main.java
- 인텔리제이로 프로그램 실행 시 외부 라이브러리와 직접 생성한 클래스 파일의 모든 경로를
-classpath
로 작성해준다
접근지시자
질문
- 최근 JVM에서 기본 라이브러리의 위치?
- 9버전 이후에는 jmods에 있고, 모듈화 되어 있다. ex)
java.lang
의 경우 java.base
패키지로 모듈화
- 8버전엔
rt.jar
파일에 포함되어 있음
참고문헌