백기선님이 과거에 진행했던 Java 스터디 7주차 스터디 입니다.
Package 키워드
이전에 패키지에 관한 내용을 적은 포스팅이 있다. 아래 링크에서 확인할 수 있다.
https://devdebin.tistory.com/101?category=1004578
Package, 패키지를 정리하자면
- 패키지란, 클래스의 묶음이다.
- 사실 클래스의 실제 이름은 패키지명을 포함한다. java.lang.String이 String 클래스의 원래 이름이다.
- 하나의 소스파일에는 첫 번째 문장으로 단 한 번의 패키지 선언만을 허용한다.
- 모든 클래스는 반드시 하나의 패키지에 속해야 한다.
- 패키지는 점(.) 구분자로 하여 계층구조로 구성할 수 있다.
- 패키지는 소문자로 작성하는 것이 원칙이다.
- 서로 관련된 클래스들끼리 그룹 단위로 묶어 놓음으로써 클래스를 효율적으로 관리한다.
- 클래스가 물리적으로 하나의 클래스파일(.class)인 것과 같이 패키지는 물리적으로 하나의 디렉토리다.
패키지 선언 방식은 아래와 같다.
//package 패키지명;
package com.codechobo.bookl; //패키지 선언
class Test{
//내부 코드
}
모든 클래스는 반드시 하나의 패키지에 포함되어야 한다고 하지만,
분명 소스 코드를 작성할 때 패키지를 선언하지 않고도 문제가 없던 경우가 많았다.
이유는 자바에서 기본적으로 제공하는 '이름없는 패키지'(unnamed package) 때문이다.
자신이 속할 패키지를 선언하지 않는다면 '이름없는 패키지'에 속하게 된다.
Import 키워드
소스코드를 작성할 때 다른 패키지의 클래스를 사용하려면 패키지명이 포함된 클래스 이름을 사용해야 한다.
예시를 들자면, Subway 클래스를 사용하기 위해서, project.vehicle.Subway 이렇게 매번 패키지명을 붙여서 사용해야 한다.
이러면 코드는 더러워지고 매번 작성하기도 불편하다. 이를 막기 위해 Import 키워드가 있다.
클래스의 코드를 작성하기 전에 import문으로 사용하고자 하는 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명은 생략할 수 있다.
import문의 역할은 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공하는 것이다.
컴파일 시에 컴파일러는 import문을 통해 소스파일에 사용된 클래스들의 패키지를 알아낸 다음,
모든 클래스 이름 앞에 패키지명을 붙여준다.
import 선언 방법은 다음과 같다.
import 패키지명.클래스명;
import 패키지명.*;
//아래는 예시
import java.util.Calender;
import java.util.Date;
import java.util.ArrayList;
import java.util.*;
키워드 import와 패키지명을 생략하고 사용하고자 하는 클래스의 이름을 패키지명과 함께 써주면 된다.
혹시 같은 패키지에서 여러 개의 클래스가 사용된다면,
'패키지명.*'을 이용해서 지정된 패키지에 속하는 모든 클래스를 패키지명 없이 사용할 수 있다.
클래스 이름을 지정해주는 대신 *을 사용하는 것을 보면, *을 사용할 때 성능 차이가 있을 것이라고 생각할 수 있는데
놀랍게도 두 방식에 성능 차이는 전혀 없다.
마지막으로 static import문에 대해 알아보자.
import문을 사용하면 클래스의 패키지명을 생략할 수 있는 것과 같이 static import문을 사용하면 static 멤버를 호출할 때,
클래스 이름을 생략할 수 있다. 아래와 같은 예시를 확인할 수 있다.
import static java.lang.System.out;
import static java.lang.Math.*;
public Example{
public static void main(String[] args){
//System.out.println(Math.random());
out.println(random());
//System.out.println("Math.PI :" + Math.PI);
out.println("Math.PI" + PI);
}
}
접근 제어자
접근 제어자에 대해 정리한 포스팅은 아래 링크에서 확인할 수 있다.
https://devdebin.tistory.com/103?category=1004578
클래스패스
클래스패스는 컴파일러나 JVM등이 클래스의 위치를 찾는데 사용되는 경로다.
위에서 확인한 클래스가 속한 패키지 경로처럼, 디렉터리와 파일을 .으로 구분한다. terminal에서 pwd의 개념과 비슷하다고 생각..?
.java 파일이 컴파일러에 의해 컴파일 되면 바이트코드로 이루어진 .class 파일이 만들어지는데 이것이 클래스 파일이다.
그러면 JVM은 인터프리터와 JIT 컴파일러를 사용해 바이트코드(.class)를 네이티브 코드로 바꿔,
우리가 작성한 프로그램(소스코드)을 실행 한다.
여기서 JVM이 실행할 클래스의 위치를 알아야 하는데, 클래스패스를 통해 .class의 위치를 파악한다.
클래스패스를 지정하는데 크게 2가지 방법이 있다.
- CLASSPATH 환경 변수를 사용하는 방법이 있다.
- java runtime에서 -classpath 옵션을 사용하는 방법이 있다.
CLASSPATH 환경 변수
환경변수는 운영체제에 지정하는 변수로 자바 가상머신과 같은 애플리케이션들은 환경변수의 값을 참고해서 동작하게 된다.
자바는 클래스 패스로 환경변수 CLASSPATH를 사용하는데 이 값을 지정하면 실행할 때마다 -classpath 옵션을 사용하지 않아도 되기 때문에 편리하다.
하지만 운영체제를 변경하면 클래스 패스가 사라지기 때문에 이식성면에서 불리할 수 있다.
-classpath옵션
옵션 -classpath는 자바를 실행할 때 사용할 클래스들의 위치를 JVM에게 알려주는 역할을 한다.
실습으로 한 번 살펴보자. 아래와 같은 .java 파일을 만든다.
이제 아래와 같은 명령어를 입력하자. 자바 파일의 이름은 Deom.java다. (Demo 오타 양해 부탁드립니다..ㅎㅎ)
javac Deom.java
그러면 ls 명령어를 입력하면 아래와 같이 두 클래스 파일이 생성된 것을 알 수 있다.
Deom.java에 있던 두 클래스가 컴파일 되어 .class파일이 된 것이다.
그리고 실행을 하면 잘 동작한다.
그럼 이제 여기서 아래와 같이 새로운 lib 폴더를 만들고 거기로 Item.class 파일을 옮겨보자. 기존에 있던 것은 삭제!
이제 java ClassPathDemo명령어를 입력하면 아래와 같이 터미널에 에러가 출력된다.
Item을 찾지 못했다는 에러가 발생했다. Item.class 파일이 같은 디렉토리(패키지)에 존재하지 않아서 발생한 에러다.
이를 -classpath를 사용해서 해결해보겠다.
결국 java -classpath .:lib ClasspathDemo 이 구문을 이해할 것 같다.
위에서 '옵션 -classpath는 자바를 실행할 때 사용할 클래스들의 위치를 JVM에게 알려주는 역할'라고 말했다.
구문의 뜻은
ClasspathDemo를 실행할 때 필요한 클래스들(Item.class)이 있다면 .(현재 디렉토리에서 찾고) 없다면 lib 디렉토리를 찾는 것이다.
즉 -classpath는 ClasspathDemo를 실행할때 필요한 클래스를 현재 디렉토리에서 찾고 없다면 lib 디렉토리에서 찾게 한 것이다.
이제 위에서 언급한 자바를 실행할 때 사용할 클래스들의 위치를 JVM에게 알려주는 역할이 무슨 말인지 이해할 수 있겠다.
참고자료
자바의 정석 (저자 : 남궁성)
댓글