Java/STUDY HALLE

[Java] 패키지

무토(MUTO) 2020. 12. 29. 01:58

0. 목표

  • package 키워드
  • import 키워드
  • 클래스패스
  • 클래스패스 환경변수
  • 클래스패스 옵션
  • 접근지시자

1. package

서로 다른 용도로 만들어진, 같은 이름의 클래스를 구분하기 위해서 만들어진 개념이다.

다음의 요구사항을 가진 프로그램을 각각의 회사에서 기능을 나누어맡아 구현한다고 가정해보자.

  • 카카오는 계산기에서 곱셈을 구현한다.
  • 네이버는 계산기에서 덧셈을 구현한다.

이제 두 회사의 결과물을 모아서 종합적인 계산기를 만들려고 한다.
그런데 모아놓고보니 문제가 생겼다. 두 회사 모두 계산기 클래스의 이름을 Calculator라고 정한것이다.

동일한 패키지 내부에는 같은 클래스의 이름이 존재할 수 없다.
그렇다고 한 회사의 클래스 명을 바꾸자니 그것만큼 클래스의 이름을 대표하기에 적절한 단어가 없다.
두 회사 모두 클래스명을 변경하기가 어렵다.

그래서 두 회사는 다음과 같이 서로 다른 디렉토리에 클래스를 만들어 따로 보관하기로 한다.

Calculator.java

package kakao;//카카오 패키지 선언

public class Calculator {
    public int calc(int a, int b) {
        return a + b;
    }
}

Calculator.java

package naver;//네이버 패키지 선언

public class Calculator {
    public int calc(int a, int b) {
        return a * b;
    }
}

Main.java

package test;

public class Main {

    public static void main(String[] args) {
        kakao.Calculator calculator1 = new kakao.Calculator();
        naver.Calculator calculator2 = new naver.Calculator();
    }
}

다음과 같이 다른 디렉토리에 각각 클래스를 만들어 충돌 문제를 해결하였다.
다만 여기서 주의해야할 점은 디렉토리만 분리하였다고해서 패키지가나뉘어지는것은 아니다.
소스파일에 제일 처음부분에 package 키워드를 사용해서 해당 소스파일의 패키지 경로를 선언해주어야 패키지가 만들어진다.

이름없는 패키지

자바의 클래스는 반드시 특정 패키지에 포함되어야 한다.
그런데 다음과 같은 파일은 패키지 선언을 하지 않았는데 아무 문제없이 실행이 된다.

public class Hello {

    public static void main(String[] args) {
        System.out.println("Hello, Study Halle!!");
    }
}

어떻게 이것이 가능할까?
별도의 패키지 선언이 존재하지 않는 파일에 정의되어있는 클래스들은 'default package'라는 것으로 묶이게 된다고 자바에서는 명시하고있다.

2. import

패키지명을 일일이 나열하는 반복적인 작업을 줄이기 위해 만들어진 개념

새로운 문제가 발생했다.
사실 계산기 프로그램을 작성하는데 카카오의 계산기는 인스턴스 생성이 한번이면 충분하고 네이버의 계산기의 인스턴스가 많이 필요했다. 그런데 패키지명을 일일이 다 적어주려다보니 이것이 너무 반복적인 작업이라 불편하다.
그래서 다음과 같은 방식을 통해서 중복을 제거했다.

package test;

import naver.Calculator;

public class Main {

    public static void main(String[] args) {
        kakao.Calculator calculator1 = new kakao.Calculator();
        Calculator calculator2 = new Calculator();
        Calculator calculator3 = new Calculator();
        Calculator calculator4 = new Calculator();
        Calculator calculator5 = new Calculator();
        Calculator calculator6 = new Calculator();
        Calculator calculator7 = new Calculator();
        Calculator calculator8 = new Calculator();
        .
        .
        .
    }
}

다음과 같이 import 키워드를 이용하여 import 선언을 하면 다음과 같은 의미가 된다.

naver패키지의 Calculator를 의미할때에는 다 생략하고 Calculator만 표시하겠다.

주의사항

어느날 카카오 Calculator의 인스턴스 생성을 추가적으로 여러번 해줘야 할 일이 생겼다고해서 중복을 없애기 위해 import kakao.Calculator를 하면 위에서 작성한 naver.Calculator와 충돌이 발생하여 컴파일 에러가 발생한다.

import static

임의의 클래스의 정적 메서드를 사용할 때 import static 을 사용하면 인스턴스를 생성하지 않고도 클래스명 없이 바로 메서드를 사용할 수 있다.

ex)

package test;

import static java.lang.Math.abs;

public class Main {

    public static void main(String[] args) {
        int abs = abs(-3);
        System.out.println(abs);//3
    }
}

3. 클래스패스

jvm이 프로그램의 실행 과정에서 실행에 필요한 클래스를 찾을 때 기준이 되는 위치들의 목록.

사실 우리는 이미 엄청난 IDE의 기본기능에 길들여져왔기 때문에 다음과 같은 사항을 몰랐어도 코딩이 가능하다. 우리가 일반적으로 java 파일을 실행하는 방법을 생각해보자

  1. IDE를 켜서 원하는 곳에 java 소스파일을 작성한다.
  2. run 버튼을 누른다.
  3. 실행창을 확인한다.

우리는 왜 classpath에 대해서 몰라도 코딩이 가능했던것일까?
그것은 바로 IDE에서 우리가 그런거 몰라도 코딩이 가능하게 다 설정을 잡아놔주었기 때문이다.

4. -classpath 옵션

다음 내용을 보자.

우리가 run하면 IntelliJ가 자동으로 해주는것들
우리가 코딩하기에 편하게 저장되어있는 여러가지 환경변수들과 IDE에 저장되어있는 classpath

원래는 classpath를 모른다면 java 파일을 아무곳에서나 실행할 수 없다.

예를들어

C:\Users\mf311\IdeaProjects\BaekJoon\src\kakao 위치에서

C:\Users\mf311\IdeaProjects\BaekJoon\src\Hello.java 파일을 실행하고자 한다.

항상 하던대로 java Hello 를 터미널에 입력해보자.

클래스를 찾을수 없다고 한다. 왜 이런일이 발생했을까?

jvm 구동시 기본 classpath는 현재 위치이다. 별다른 옵션을 주지 않는다면 현재위치가 classpath 가 된다.

그래서 현재 위치에서는 Hello.class 파일을 찾을수가 없기 때문에 다음과 같이 클래스를 찾을 수 없다는 알림을 띄우는 것이다.

그렇다면 정상 실행 시키고 싶다면 어떻게 해야할까?

다음과 같이 직접 -classpath옵션을 부여하면 jvm 구동을 통해 소스파일 실행이 가능하다.

5. CLASSPATH 환경변수

CLASSPATH라는 이름을 가진 환경변수를 등록하고 내부에 값을 대입하면 일일이 -classpath 옵션으로 클래스패스를 설정하지 않아도 된다.

윈도우의 경우에는 set 명령어를 이용하면 환경변수를 설정할 수 있다.
set CLASSPATH ".;"

현재 cmd 창을 벗어나서도 영구적으로 등록하고싶다면 setx 명령어를 사용하면 영구적으로 등록된다.
setx CLASSPATH ".;"

6. 접근지시자

객체지향적으로 클래스를 캡슐화하고 정보를 은닉하기 위해 단계별로 접근 제한을 강제하는 키워드

제어자 클래스 내부 동일패키지 상속받은클래스 이외의 영역
public o o o o
protected o o o
default o o
private o

'Java > STUDY HALLE' 카테고리의 다른 글

[Java] 예외처리  (0) 2021.01.15
[Java] 인터페이스  (0) 2021.01.08
[Java] 상속  (0) 2020.12.22
[Java] 클래스  (0) 2020.12.16
[Java] 선형 자료구조  (0) 2020.12.07