[Java] Day07 - 패키지
2021-02-06 # Java

Day07. 패키지

Review Day06


Q1. @Override Annotation이 단순히 마크의 의미만 가지고 있나요?

아니다. 단순히 오버라이딩한 메서드임을 보여주는 것이 아니라 컴파일러가 오버라이딩을 한것인지 오류를 체크해준다.

예를 들어, 나는 오버라이딩을 잘했다고 생각했지만 막상 컴파일을 하고 보니 이것은 오버라이딩을 한것이 아닌 새로운 메서드를 정의한 것이라면 오류가 뜨게 하는 것이다.

따라서, 명시적으로 어노테이션을 하는 것이 좋다.


Day07. 패키지



package keyword


패키지란, 클래스의 묶음이다. 패키지 안에는 클래스 또는 인터페이스를 포함시킬 수 있으며, 서로 관련된 클래스들끼리 그룹 단위로 묶어 놓음으로써 클래스를 효율적으로 관리할 수 있다.

같은 이름의 클래스 일지라도 서로 다른 패키지에 존재하는 것이 가능하므로, 자신만의 패키지 체계를 유지함으로써 다른 개발자가 개발한 클래스 라이브러리의 클래스와 이름이 충돌하는 것을 피할 수 있다. - Java의 정석

디렉토리가 디렉토리를 포함할 수 있는 것처럼 패키지 또한 다른 패키지를 포함하는 것이 가능하다. 이는 .으로 구분이 가능하다.

예를들어 우리가 자주쓰는 String클래스는 java라는 패키지의 lang안의 String이라는 클래스이다.

이는 java.lang.String으로 쓰는 것이다.

패키지는 다음과 같은 규칙을 가진다.

  1. 하나의 소스파일에는 첫 번째 문장으로 단 한번의 패키지 선언만을 허용한다.
  2. 모든 클래스는 반드시 하나의 패키지에 속해야 한다.
  3. 패키지는 점(.)을 구분자로 하여 계층구조로 구성할 수 있다.
  4. 패키지는 물리적으로 클래스파일(.class)을 포함하는 하나의 디렉토리이다.

또한 패키지이름의 규칙도 존재한다.

패키지 시작이름 내용
java 자바 기본 패키지()
javax 자바 확장 패키지(Java vendor 개발)
org 일반적으로 비영리단체 (오픈소스) 패키지
com 일반적으로 영리단체(회사) 패키지

패키지의 선언은

1
package 패키지명;

과 같이 간단하게 설정 가능하다. 우리가 인텔리제이를 쓰다보면 첫줄에 자바에서 기본적으로 제공하는 ‘이름없는패키지(unnamed package)’가 설정되어 있음을 볼 수 있다.

패키지명은 소문자로 하는 것을 원칙으로 하고 있다.

패키지를 구성하는 과정은 뒤에 클래스패스를 다루면서 다시 얘기해보겠다.


import keyword


기존의 패키지에 포함되지 않은 다른 클래스들을 사용하기 위해서는 패키지명이 포함된 클래스 이름을 사용해야 한다.

하지만 매번 패키지이름을 쓰는 것은 불편하므로 import문을 사용하여 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명을 생략할 수 있다.

인텔리제이는 ‘Alt+Enter’를 하면 자동으로 import해주는 기능을 가지고 있다.

클래스 이름을 지정해주는 대신 ‘*’를 사용하면 컴파일러는 해당 패키지에서 일치하는 클래스이름을 찾아야 하는 수고를 더 해야할 것이다. 단지 그 뿐이다. 실행 시 성능상의 차이는 전혀 없다.

1
2
3
import java.util.Calendar;
import java.util.Date;;
import java.util.ArrayList;

위와 같은 코드는 다음과 같이 한줄로 줄일 수 있다.

1
import java.util.*;

하지만 이는 클래스의 이름 대신 ‘‘를 사용하는 것이지 패키지 대신 ‘‘를 사용하는 것은 불가능하다.

1
2
import java.util.*;
import java.text.*;

1
import java.*;

과 같지 않다.


빌트인패키지(Built-in package)


지금까지 String이나 System같은 클래스들을 패키지명 없이 사용할 수 있었던 이유는 모든 소스파일에는 implicit하게 import java.lang.*이 선언되어 있다.

매우 중요하고 자주쓰는 패키지이기 때문에 따로 import문으로 지정하지 않아도 되도록 한 것이다.

이를 built-in package라 하는 것이다. 또한, 클래스 이름과 패키지 이름을 합쳐야 FQCN(Fully Qualified Class Name)이라고 한다.

추가로 static import문도 가능하다.

1
2
3
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()); –> out.println(random());으로 바꿀 수 있다.


클래스패스란?


클래스패스란 JVM 혹은 Java 컴파일러가 사용하는 파라미터로 클래스나 패키지를 찾을 때 기준이 되는 경로를 말한다.

즉, java 명령을 통해 class 파일을 실행할 때 클래스 파일을 찾는 기준이 되는 경로를 클래스패스라고 한다.

따로 지정해주지 않는다면 기본적으로는 java명령을 실행하는 위치(현재 디렉터리)를 말한다.

소스코드(.java로 끝나는 파일)를 컴파일하면 소스코드가 바이트코드로 변환되는데, java runtime으로 .class 파일에 포함된 명령을 실행하려면 이 파일을 찾을수 있어야한다.

.class 파일을 찾을 때, classpath에 지정된 경로를 사용한다.

세미 콜론(;)을 구분자로 하여 여러개의 경로를 지정할 수 있다.

classpath를 지정하는 방법 두가지를 살펴보겠다.


CLASSPATH 환경변수


CLASSPATH=,;C:\Program Files\JDK\lib\tools.jar처럼 컴퓨터 시스템 변수설정을 통해 지정할 수 있다.

JVM이 시작될 때 JVM의 클래스 로더는 이 환경변수를 호출하게 된다. 그래서 환경 변수에 설정되어 있는 디렉토리가 호출되면 그 디렉토리에 있는 클래스들을 먼저 JVM에 로드한다.

따라서, CLASSPATH 환경 변수에는 필수 클래스들이 위치한 디렉토리를 등록하도록 한다.

하지만, 운영체제를 변경하면 클래스패스가 사라지기 때문에 이식성 면에서는 불리하다.

  • Windows : 시스템설정 > 환경변수
  • linux, unix계열 : /etc/profile

따라서 최근에는 운영체제 상의 환경변수로 클래스패스를 설정하는 것은 지양하고 IDE나 빌드도구를 통해 클래스패스를 설정한다.


-classpath 옵션


원래의 자바 컴파일러인 javac를 사용할 때는 javac <options> <source filed>와 같은 형태로 컴파일을 했는데

참조할 클래스 파일들을 찾기 위해서 파일 경로를 지정해주는 -classpath 옵션이 있다.

예를들어 컴파일 할 Test.java파일이 C:\Users에 있고, 필요한 클래스파일들이 C:\Java\classes에 존재한다면,

javac -classpath C;\Java\classes C:\Users\Test.java로 옵션을 주고 컴파일시에 클래스패스가 참조된다.

이 때, -cp로 약자를 사용하여 옵션을 주는 것도 가능하다.


접근지시자(Access Modifiers)


접근 지시자는 멤버 변수나 메서드들의 접근 범위를 정의하기 위해 사용되는 것이다.

main 메서드가 없는 클래스는 대부분 다른 클래스에서 사용할 목적으로 설계된 클래스이다.

클래스들은 외부 클래스에서 접근할 수 있는 멤버와 접근할 수 없는 멤버를 구분하여 설계하는 것이 바람직하다.

객체 생성을 막기 위해 생성자를 호출하지 못하게 하거나, 객체의 특정 데이터를 보호하기 위해 해당 필드에 접근하지 못하게 하기 위해서 사용한다.

접근 제한자(Access Modifiers)또는 접근 수준 지시자(Access-level Modifier)라고도 한다.

우리가 사용할 접근제한자는 다음과 간다.

  1. public

    모든 패키지에서 아무런 제한 없이 호출 할 수 있게 하며, 보통 생성자, 필드 또는 메서드가 public이면 클래스도 public으로 선언한다.

  2. protected

    같은 패키지에서는 제한 없이 호출할 수 있으나, 다른 패키지에서는 호출할 수 없다.

    다른 패키지에 속한 클래스가 해당 클래스의 자식 클래스라면 호출할 수 있다.

  3. default

    접근제한자를 생략한다면 default 제한을 가진다.

    protected와 같이 같은 패키지에서는 제한 없이 호출할 수 있으나, 다른 패키지에서는 호출할 수 없다.

  4. private

    오로지 클래스 내부에서만 사용할 수 있다.



지시자 클래스 내부 동일 패키지 상속받은 클래스 이외
private O X X X
default O O X X
protected O O O X
public O O O O

Reference


자바의정석
https://kils-log-of-develop.tistory.com/430
https://blog.baesangwoo.dev/posts/java-livestudy-7week/
https://www.notion.so/ed8e346f88f54849a06ff968b1877ca5
https://pej4303.tistory.com/57