영권's
7주차 과제: 패키지 본문
목표
자바의 패키지에 대해 학습하세요.
학습할 것 (필수)
- package 키워드
- import 키워드
- 클래스패스
- CLASSPATH 환경변수
- -classpath 옵션
- 접근지시자
package 키워드
패키지란 우리가 컴퓨터에서 사용하는 폴더와 비슷한 개념이다.
패키지는 수 많은 클래스들을 체계적으로 관리하기 위해 존재한다.
폴더를 만들어서 파일을 관리하듯 패키지를 만들어서 클래스를 저장/관리한다.
패키지의 물리적인 형태는 "파일 시스템의 폴더" 이다.
또한, 파일 시스템의 폴더 기능만이 아니라 클래스의 일부분이다.
pakage 는 소스의 가장 첫줄에 위치하며 클래스 파일 안에 하나의 pakage 만 선언할 수 있습니다.
만약 pakage 선언이 없다면 default pakage 에 속한것으로 취급하며 default pakage 는 어떤 패키지에도 속하지 않는 상태를 말합니다.
- 패키지는 클래스를 유일하게 만들어주는 "식별자" 역할을 한다.
- 클래스의 전체 이름은 "패키지 + 클래스명" 이다.
- 패키지가 계층구조로 되어 있다면 도트(.)를 사용해서 표현한다.
ex) 상위패키지.하위패키지.클래스명
Test 클래스가 com.livestudy 패키지에 속해 있다면
Test 클래스의 전체 이름은 com.livestudy.Test
실제 파일 시스템 : com\livestudy\Test.class
또한, 패키지는 폴더 또는 디렉토리로서, 우리는 기능이나 특징이 비슷한 클래스를 하나의 패키지에 넣는다.
→ 패키지의 이름은 최대한 그 패키지 안에 들어갈 클래스들을 포괄하는 이름이 좋겠다.
FQCN (Fully Qualified Class Name)
모든 클래스에는 정의된 클래스 이름과 패키지 이름이 있다.
이 둘을 합쳐야 완전하게 한 클래스를 표현할 수 있으며 FQCN(Fully Qualified Class Name)이라 한다.
ex) String 클래스의 패키지는 "java.lang" 이며 FQCN은 "java.lang.String"이 된다.
네임스페이스(Namespace)
어떤 파일 "A"를 사용하기 위해 그 파일의 이름인 "A"를 이용해 파일을 접근(참조)한다.
파일 "A"를 열어보기 위해서 우리는 파일 "A"의 디렉토리 '경로(path)'를 알아야 한다.
우리가 원하는 파일 "A"가 예를 들어 **"/Users/dir_a/"**에 존재한다고 치자, 그런데 "Users/dir_b/" 라는 경로에 또 파일 "A"가 존재한다고 하자.
이 둘은 같은 파일일까? ⇒ 다른 파일이다. 그렇다면 이 두 파일을 어떻게 구분하는가?
바로 디렉토리 경로로 구분한다. 따라서 여기서는 "dir_a", "dir_b"가 바로 네임스페이스 역할을 한다.
네임스페이스란 이름을 구분 할 수 있게 해주는 공간을 의미한다. 위 예시에서는 디렉토리가 바로 공간이고, 자바에서는 패키지(Package)가 바로 그 공간이다.
이러한 특성으로 패키지는 이름 중복으로 인한 문제를 방지할 수 있다.
패키지 안의 클래스 이름은 고유해야 한다. 다시말해, 하나의 패키지 안에는 같은 이름의 두개의 클래스를 만들 수 없다.
but. 패키지가 다르다면 상관없다.
패키지 자체가 분리된 다른공간 임으로 다른 패키지에 같은 이름의 클래스가 있더라도, 내 패키지 안에 똑같은 이름을 쓸 수 있다.
패키지 선언
패키지는 클래스를 컴파일 하는 과정에서 자동적으로 생성되는 폴더이다.
컴파일러는 클래스에 포함되어 있는 패키지 선언을 보고, 파일 시스템의 폴더로 자동 생성 시킨다.
package 상위패키지.하위패키지;
public class ClassName{ ... }
package 상위패키지.하위패키지;
public class ClassName{ ... }
패키지 이름은 개발자 임의로 정의해도 되지만, 지켜야할 규칙이 있다.
- 숫자로 시작해서 안된다.
- _, $ 를 제외한 특수문자를 사용해서는 안된다.
- java로 시작하는 패키지는 자바 표준 api 에서만 사용하므로 사용해서는 안된다.
- 모두 소문자로 작성하는 것이 관례이다.
패키지가 서로 중복되지 않도록 회사의 도메인 이름으로 패키지를 만든다.
도메인 이름으로 패키지 이름을 만들 경우, 도메인 이름 역순으로 패키지 이름을 지어준다.
(포괄적인 이름이 상위 패키지가 되도록 하기 위함이다.)
마지막에는 프로젝트 이름을 붙여주는 것이 관례이다.
빌트-인 패키지(Built-in Package)
자바는 개발자들이 사용할 수 있도록 여러 많은 패키지 및 클래스를 제공한다.
가장 자주 쓰이는 패키지로는 java.lang과 java.util이 있다.
java.lang은 자주 사용하는 패키지이지만 한번도 import하여 사용한적이 없다.
즉, 자바에서 java.lang 패키지는 아주 기본적인 것들이기 때문에 import로 불러오지 않아도 자바가 알아서 java.lang의 클래스를 불러온다.
import
import 키워드는 다른 패키지에 있는 클래스나 인터페이스 등을 참조할 때 사용합니다.
동일 패키지의 클래스나 java.lang 패키지의 클래스는 import 구문 없이 참조 가능합니다.
이때 규칙은 FQCN을 입력해야 합니다.
같은 패키지에 속하는 클래스들은 서로 서로 사용할 수 있지만,
다른 패키지에 속하는 클래스를 사용하려면 2가지 방법 중 하나를 선택해야 한다.
- 패키지와 클래스를 모두 기술하는 방법
FQCN을 모두 작성하여 사용하고자 하는 객체를 생성 하는것이다.
→ 패키지 이름이 짧을 경우 불편함이 없지만, 길거나 이렇게 사용해야할 클래스가 많다면 전체적으로 코드의 가독성이 떨어진다.
- import 문 사용
- import 문 작성 위치 : 패키지 선언과 클래스 선언 사이에 선언된다.
- 패키지에 포함된 다수 클래스를 사용해야 한다면, 모든 클래스를 의미하는 [*] 기호를 사용한다.
- import 문의 개수 제한은 없다.
- 사용하고자 하는 패키지를 import 문으로 선언하고, 클래스를 사용할 때는 패키지를 생략한다.
static import
Static import는 자바 5버전 이상에서 소개된 기능이다.
임의의 패키지의 클래스에서 public static으로 정의된 멤버(필드나 메서드)를 사용할 때, 클래스명을 언급하지 않고도 사용할 수 있다.
import 문을 사용하면 클래스의 패키지명을 생략할 수 있는 것과 같이 static import문을 사용하면 static 멤버를 호출할 때 클래스 이름을 생략할 수 있다. 특정 클래스의 static 멤버를 자주 사용할 때 편리하다. 그리고 코드도 간결해진다.
// import static org.assertj.core.api.Assertions.*; 예시
import static java.lang.System.out;
class Test {
public static void main(String[] args) {
// System.out.println(Math.random());
out.println(Math.random());
}
}
만약 2개의 다른 패키지에 있는 클래스들을 다 사용하려할 경우, 클래스 풀네임(FQCN)을 사용해서 코드를 작성한다.
클래스패스
- CLASSPATH 환경변수
- classpath 옵션
클래스패스란, JVM이나 Java 컴파일러에 사용자정의 클래스와 패키지의 위치를 지정해주는 파라미터이다.
쉽게 말해, 자바가 클래스를 찾아 사용을 해야하는데, 클래스들이 어디 있는지 위치를 지정해주는 값이다.
classpath 옵션은 java와 javac 명령어에 모두 사용할 수 있다.
좀더 자바의 관점에서 말한다면 JVM이 프로그램을 실행할 때, 클래스 파일을 찾는 데 기준이 되는 파일 경로를 말합니다.
소스 코드(.java 파일)를 컴파일하면 소스 코드가 “바이트 코드”(바이너리 형태의 .class 파일)로 변환됩니다.
Java runtime(java 또는 jre)으로 이 .class 파일에 포함된 명령을 실행하려면, 먼저 이 파일을 찾을 수 있어야 합니다.
이 때 .class 파일을 찾을 때 classpath에 지정된 경로를 사용합니다.
classpath는 .class 파일이 포함된 디렉토리와 파일을 콜론(;)으로 구분한 목록입니다.
찾으려는 클래스 코드가 포함된 .class 파일을 찾으면 첫 번째로 찾은 파일을 사용합니다.
classpath를 지정할 수 있는 두 가지 방법이 있습니다.
- 환경 변수 CLASSPATH를 사용하는 방법
- Java runtime 에 -classpath 옵션을 사용하는 방법
classpath에 사용할 수 있는 값
앞에서 설명한 대로 classpath는 콜론(:)으로 구분된 디렉토리 및 파일 목록이다. 다음 세가지 유형의 파일과 디렉토리를 classpath에 지정할 수 있다. ( 윈도우 운영체제에서는 세미콜론(;)으로 구분합니다.)
- /export/home/username/java/classes와 같은 디렉토리
- myclasses.zip과 같은 zip파일
- myclasses.jar와 같은 jar(자바 아카이브) 파일
위 세가지 유형을 모두 사용하면 다음과 같이 지정할 수 있습니다.
/export/home/username/java/classes:/export/home/username/java/classes.zip:/export/home/username/java/classes.jar
.zip 파일과 .jar 파일은 하나의 아카이브로 압축된 자바 클래스 파일 세트를 말합니다.
classes.zip 파일
classes.zip 파일은 1.1 기반 Java Runtime 의 표준 클래스가 모두 포함된 아카이브 파일입니다. 예를 들어, java.awt, java.io, java.net 등의 패키지에 있는 클래스가 모두 여기에 포함되어 있습니다.
JDK 1.1 이전에는 classes.zip 파일을 classpath에 포함시켜야 했습니다.
그러나 1.1 버전부터는 classes.zip 파일을 plasspath에 포함시키면 안됩니다. Java 가 자동으로 classes.zip 파일을 찾을 수 있기 때문입니다. classes.zip 파일을 classpath에 지정하면 지정하지 않을 때보다 더 많은 문제가 발생합니다.
일반적으로 다음과 같은 문제가 발생합니다.
JDK 1.1.4를 설치할 때 포함된 classes.zip 파일을 classpath에 추가한다고 가정합니다.
classes.zip 파일을 .cshrc와 같은 쉘 시작 파일 중 하나에 추가하고 나서 classes.zip 파일의 경로를 지정한 것을 기억하지 못합니다. 그러나 새 jdk를 사용하면 경로에서 이전의 classes.zip 파일을 먼저 찾게 되기 때문에 이전의 클래스가 사용됩니다. 따라서 java 프로그램은 실행되지 않고 문제와 관련이 없는 오류 메시지가 나오게됩니다.
rt.jar 파일
JRE와 JDK 사이에는 차이가 있습니다. JRE는 JDK 중에서 java 프로그램을 실행하는 프로그램만 포함된 환경입니다. 따라서 JRE는 classes.zip 파일에서 클래스를 찾지 않습니다. 대신 rt.jar 파일을 사용합니다.
rt.jar 파일에는 classes.zip과 동일한 클래스가 모두 포함되어 있고, 아카이브 형식과 이름만 다른 것을 사용합니다. Java 1.2 가 발표되면서 classes.zip 파일은 없어졌습니다. 대신 JDK 와 JRE가 모두 rt.jar 파일을 사용합니다. rt.jar 파일을 classpath에 지정해야 하는가에 대해서는 classes.zip 파일과 동일한 규칙이 적용됩니다. 즉, 지정할 필요가 없습니다.
- JVM의 클래스로더는 런타임 시에 $CLASSPATH 환경변수를 호출해 해당 디렉토리에 정의된 클래스들을 로딩하게 된다.
- 3가지 Class Loader 가 존재한다.
BootStrap Class Loader
- 기본 클래스로더 중 최상위 클래스 로더
- jre/lib/rt.jar 에 담긴 JDK 클래스 파일을 로딩해준다.
- String 클래스나, Object 클래스를 사용할 수 있었던 이유가 바로 BootStrap Class Loader가 자동으로 메모리에 적재해주기 때문이다.
Extension Class Loader
- 익스텐션 클래스로더는 jre/lib/ext 폴더나 java.ext.dirs 환경 변수로 지정된 폴더에 있는 클래스 파일을 로딩한다.
System Class Loader
- 바로 System Class Loader 가 우리가 만든 Class를 메모리에 올리는 역할을 하는데, 그 때 classpath 기준으로 클래스들을 로드해준다.
.class 파일이 실행될 경로(CLASSPATH)를 알고 실행했다는 것이며,
설정은 아래와 같이 시스템 환경변수로 JAVA_HOME과 CLASSPATH를 설정해두었다.
타 경로에서 class 파일을 실행할 때 -cp(classpath) 옵션을 통해 실행할 수 있었다.
plus.
- javac로 java파일을 컴파일 할 때에도 -cp(classpath) 옵션을 통해 컴파일 할 수 있다.
-cp(classpath) 옵션은
- 자바 컴파일러가 컴파일 하기 위해서 필요로 하는 참조할 클래스 파일들을 찾기 위해 컴파일 시에 파일 경로를 지정해주는 옵션이다.
즉, 다른 클래스에 의존하는 클래스의 소스 파일을 컴파일 하기 위해서 다른 클래스가 위치하는 경로를 잡아주는 것이다.
즉, -cp(classpath) 옵션은 컴파일할 때, 실행할 때 모두 사용할 수 있다.!
CLASSPATH 환경변수
환경변수는 운영체제에 지정하는 변수로 자바 가상머신과 같은 애플리케이션들은 환경변수 값을 참고해서 동작하게 된다.
자바는 클래스 패스로 환경변수 CLASSPATH를 사용하는데 이 값을 지정하면 실행할때마다
-cp(classpath) 옵션을 사용하지 않아도 된다.
but.
운영체제를 변경하면 클래스패스가 사라지기 때문이 이식성 면에서 불리할 수 있다.
windows
시스템 설정 > 환경 변수
linux, unix 계열
/etc/profile
IDE의 자동 클래스패스 설정
최근에는 운영체제 상의 환경변수로 클래스패스를 설정하는 것은 지양하고 IDE나 빌드도구를 통해 클래스패스를 설정한다.
접근지시자
- 접근 제한자(Access Modifier) / 접근 수준 지시자(Access-level Modifier)
main() 메소드가 없는 클래스는 대부분 외부 클래스에서 이용할 목적으로 설계된 클래스이다.
클래스들은 외부 클래스에서 접근할 수 있는 멤버와 접근할 수 없는 멤버를 구분하여 설계하는 것이 바람직하다.
객체 생성을 막기 위해 생성자를 호출하지 못하게 하거나,
객체의 특정 데이터를 보호하기 위해 해당 필드에 접근하지 못하게 하거나,
특정 메소드를 호출할 수 없도록 제한한다.
이러한 기능을 구현하기 위해 자바는 접근 제한자(Access Modifier) 를 제공하고 이는 접근 수준 지시자 (Access-level Modifier)라고도 한다.
4가지 접근 제한자가 있으며, 제한이 작은 순서는 public < protected < default < private 이다.
public
- 모든 패키지에서 아무런 제한 없이 호출 할 수 있게 한다.
- 보통 생성자 또는 필드, 메소드가 public이라면, 클래스도 public 접근 제한을 가진다.
protected
- default 접근 제한과 마찬가지로 같은 패키지에 속하는 클래스에서 호출할 수 있도록 한다.
- 차이점은 다른 패키지에 속한 클래스가 해당 클래스의 자식(child) 클래스라면 호출 할 수 있다.
default
- 접근 제한자를 생략했다면 default 접근제한을 가진다.
- 같은 패키지에서는 제한 없이 호출할 수 있으나, 다른 패키지에서는 호출할 수 없다.
private
- 오로지 클래스 내부에서만 사용할 수 있다.
Singleton 예시
클래스 외부에서 new 연산자로 생성자를 호출할 수 없도록 제한하며, getInstance() 함수를 통해서 단 하나의 객체만 사용하도록 보장한다.
- new 연산자로 객체를 생성하려하면, has private access 라고 오류가 발생한다.
import를 "*"를 사용할 것이냐 구체적으로 할 것이냐?
intellij 에서 import 할 때 IDE가 import하는 방식 이 있다.
왜 필요하냐?
때에 따라, 조직에 따라 이러한 부분을 컨밴션으로 가져가는 팀들도 있기도 하다.
Preference → code style → Java → Imports → "Class count to use import with "*""
출처:
www.notion.so/ed8e346f88f54849a06ff968b1877ca5
blog.baesangwoo.dev/posts/java-livestudy-7week/
'스터디 > 백기선 라이브 스터디(자바)' 카테고리의 다른 글
9주차 과제: 예외 처리 (0) | 2021.02.23 |
---|---|
8주자 과제: 인터페이스 (0) | 2021.02.22 |
6주차 과제: 상속 (0) | 2021.02.17 |
5주차 과제: 클래스 (0) | 2021.02.08 |
3주차 과제: 연산자 (0) | 2021.01.18 |