Java - 패키지

Lee·2021년 1월 1일
0

Java

목록 보기
5/9
post-thumbnail

자바에서 제공하는 패키지에 대해 학습해보자 🤔

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

패키지란? 🤔

Document Description 💡

  • 패키지는 관련 클래스 및 인터페이스 집합을 구성하는 네임스페이스입니다. 개념적으로 패키지는 컴퓨터의 다른 폴더와 비슷하다고 생각할 수 있습니다. HTML 페이지는 한 폴더에, 이미지는 다른 폴더에, 스크립트 또는 응용 프로그램은 다른 폴더에 보관할 수 있습니다. 자바 프로그래밍 언어로 작성된 소프트웨어는 수백, 수천 개의 개별 클래스로 구성될 수 있기 때문에 관련 클래스와 인터페이스를 패키지에 넣어 정리하는 것이 이치에 맞다.

정리하자면 ✍️

  • 클래스의 묶음
  • 클래스뿐만 아니라 인터페이스를 포함 시킬 수 있음
  • 흔히 폴더 구조를 생각하면 된다.
  • Package Ex) src/com/lee/week/Main.java

이름없는 패키지 💡

  • 모든 클래스는 반드시 하나의 패키지에 포함되어야 하는데 패키지를 선언하지 않고 사용하는 것.

사용하는 이유는? 🤔

  • 서로 관련된 클래스들끼리 그룹 단위로 묶어 놓음으로써 효과적으로 클래스 파일을 관리할 수 있기 때문이다.
  • 우리가 PC에 목적별(사진/문서/폴더/workspace 폴더)로 폴더를 생성해서 관리하는 것과 같은 의미이다.

특징 ✍️

  • 모든 클래스는 반드시 하나 이상의 패키지를 포함하고 있다.
  • 패키지 선언은 주석과 공백을 제외하고 제일 첫 번째 문장에 선언되어야 하고, 하나의 소스파일(.java)에는 단 한 번만 선언할 수 있다.

import 란? 🤔

  • 다른 패키지의 클래스를 사용하려면 패키지명이 포함된 클래스 이름을 사용해야만 한다. 하지만 매번 패키지명을 붙여서 작성하기는 비효율적이기 때문에 자바에서 import 키워드를 따로 제공한다.
  • import 키워드는 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 미리 제공하는 것이다.
  • 이로 인해 우리는 import 키워드를 통해 다른 패키지에 속한 클래스를 패키지 이름을 제외한 채로 사용할 수 있게 된다.

import 선언 💡

  • import 키워드는 모든 소스파일에서 package문 다음에, 그리고 클래스 선언 문 이전에 위치한다.

import 특징 ✍️

  • package 키워드와는 달리 하나의 소스파일에 여러 번 선언할 수 있다.

import java.lang 🚀

  • 자바에서 가장 많이 사용하는 java.lang 패키지에 대해서 import 키워드를 사용하지 않아도 클래스 이름만으로도 사용할 수 있다.

Constant Interface 🤔

사용을 추천하지 않는 Anti 패턴 💡

  • Constant Interface(상수 인터페이스)란? 오직 상수만 정의한 인터페이스이다.
  • 변수를 등록할 때 자동으로 public static final이 붙는다. 따라서 상수처럼 어디에서나 접근 가능
인터페이스의 목적 💡
  • 인터페이스를 구현하는 클래스를 만들게 되면, 그 인터페이스를 해당 클래스의 객체를 참조할 수 있는 자료형 역할을 하게 된다.
    • 해당 클래스의 객체로 어떤 일을 할 수 있는지 클라이언트에게 알리는 행위임
  • 인터페이스의 목적은 여기까지이며 다른 목적으로 인터페이스를 정희 하고 사용하는 것은 적절치 못함
인터페이스를 잘못 사용하고 있는 예시 💡
  • 상수 인터페이스(Constant Interface)
    • 형태
      • 메소드가 없고, static final 필드만 있는 형태로 모든 필드는 상수 정의임
      • 대체로 상수 이름 앞에 클래스 이름을 붙이는 번거로움을 피하기 위해서임
public interface PhysicalConstants {
		static final double AVOGADROS_NUMBER = 6.022_140_857e23;
		static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23;
		static final double ELECTRON_MASS = 9.109_383_56e-31;
}
  • 문제점
    • 상수 정의를 인터페이스에 포함시키면 구현 세부사항이 클래스의 공개 API에 스며들게 되고 혼동을 줄 우려가 있음
    • 자바 플랫폼 라이브러리에도 상수 인터페이스가 몇 개 있는데 java.io.Object.StreamConstants 실수로 포함된 것으로 생각해야 하고 따라 해서는 절대 안됨

결론 🚀

  • 인터페이스는 자료형을 정의할 때만 사용해야 한다.

static import 🤔

  • 1.5 버전 이후로 static import 기능이 추가되었고, 클래스 이름을 따로 선언할 필요 없이 static 멤버에 접근할 수 있다
  • import 문을 사용하면 클래스의 패키지명을 생략할 수 있는 것과 같이 static import 문을 사용하면 static 멤버를 호출할 때 클래스명을 생략할 수 있다.
  • 개인적인 생각이지만 위에서 언급한 상수 인터페이스의 활용을 억제하기 위해 나오지 않았나..? 라는 생각이 든다.

static import 언제 사용하는가? 🤔

  • static 필드나 메소드에 접근할려면 일반적으로 이렇게 접근할 것 이다.

    {ClassName} + {.} + {Method | Field}

    이러한 접근방식에 단점은 매번 사용하려는 메소드나 필드 앞에 Class 명을 기술하는게 매우 번거롭다는 것이다.
    하지만, static import 을 이용하면 획기적으로 이러한 문제를 줄일 수 있다.

  • static import 를 사용하기 전 💡

    Math API 에 있는 필드와 메소드를 사용하기 위해선 위와 같은 문법으로 기술해야한다. 만약 Math API 를 사용하는 곳이 많아진다면??아마 너무 번거롭지 않을까??

  • static import 를 사용한 후 💡

    Math 클래스를 작성하지 않아도 필드나 메소드에 접근이 가능해졌다. 이로써 번거로운 작업은 조금이나마 덜어졌다고 말할 수 있다.
    위와 같이 정적인 필드나 메소드에 접근할 때 번거로움을 줄일 수 있지만, 너무 과하게 사용하면 오히려 가독성이 떨어질 것이고, 변수명, 메소드명으로만 나와 있기 때문에 클래스의 멤버로 오해하기 쉬울 것이다. 그렇기에 일정 시간이 지나면 코드를 분석할 때 어려움을 겪을 것 같다.

ClassPath 🤔

  • classpath란? 말 그대로 클래스를 찾기 위한 경로이다.
  • JVM이 프로그램을 실행할 때, 클래스 파일을 찾는 과정에서 기준이 되는 파일 경로를 말하는 것
  • 소스 코드를 컴파일하면 바이트 코드로 변환되고 JVM 이 바이트 코드로 된 파일을 실행하려면 찾아야 하는데 이 바이트 코드까지의 경로를 classpath라고 한다.

classpath 환경 변수

  • 환경변수란? 🤔

    • 프로세스가 컴퓨터에서 동작하는 방식에 영향을 미치는, 동적인 값들의 모임
    • 운영체제에서 자식 프로세스들을 생성할 때 참조하는 변수
  • 환경변수 사용하는 이유 💡

    • 환경 변수 PATH를 설정하는 이유는 Windows의 명령 프롬프트(cmd), macOS의 터미널(Terminal) 같은 창에서 설치된 경로까지 이동하지 않고 java, javac를 사용하려고 설정하는 것이다.
    • 예를 들어 /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk 이러한 경로에 자바가 설치되었다고 가정해보면
    • 흔히? 우리가 바이트 코드를 보기 위해선 컴파일을 해야 하는데 이때 환경변수가 설정되어 있지 않으면 /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk 경로로 이동하여 javac 명령을 실행해야만 한다.
    • 하지만 자바가 설치되어 있는 경로를 시스템 변수로 설정하면 디렉토리를 이동하지 않고 컴파일이 가능하다.
  • 환경변수 설정 📌

    • macOS Catalina부터 기본 쉘이 bash 에서 zsh로 변경되어서 zsh 기준으로 설명할 예정
    • 자바를 설치하면 /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk 에 설치된다
    • java -version
    • zsh에 맞게 Path 설정을 하기 위해선 vi ~/.zshrc 명령어를 입력한다
      • i키를 입력하면 수정 모드로 변경된다, 그 후 맨 밑으로 이동하여
      • 위와 같이 입력한 후 esc 키 누른 후 :wq를 입력한 후 빠져나온다
      • source ~/.zshrc 명령어를 입력하여 수정된 zshrc 파일을 설정해준다.
      • javac -version, java -version 명령어를 입력한 후 위와 같이 버전정보나 나온다면 성공적으로 PATH를 설정한 것이다.

-classpath 옵션 📌

  • .class 파일을 실행할 때 사용할 클래스들의 위치를 가상머신에게 알려주는 역할을 한다.

  • -claspath 옵션을 사용하지 않을 경우 클래스 파일이 위치한 현재 디렉토리를 기본 classpath로 잡아준다

    • -classpath 옵션을 사용하지 않을 때

      • src 디렉토리 안에 AAA.java, BBB.java, WhatYourName.java 파일이 있다
        public class WhatYourName {
            public static void main(String[] args) {
                AAA a = new AAA();
                a.showName();
        
                BBB b = new BBB();
                b.showName();
        
            }
        }
        public class AAA {
            public void showName() {
                System.out.println("AAA");
            }
        }
        public class BBB {
            public void showName() {
                System.out.println("BBB");
            }
        }
  • javac WhatYourName.java 명령어를 이용하여 컴파일을 하면

    각 자바 파일에 해당하는 클래스 파일이 만들어진다.
    이 후 java WhatYourName 명령어를 입력하면 AAA, BBB가 출력되는 결과를 확인할 수 있다.
    만약 AAA.class, BBB.class 파일을 옮긴다면??

    pathtest라는 새로운 디렉토리를 만든 후 그 AAA.class, BBB.class 파일을 옮긴 후에 다시 한번 java WhatYourName을 실행시켜봤다

    AAA 라는 클래스를 찾을 수 없다는 에러가 나왔다. 이 뜻은 WhatYourName에서 AAA 클래스를 참조하고 있는데 참조하고 있는 AAA 클래스를 찾을 수 없다는 것이다. 그 이유는 위에서 AAA.class, BBB.class 파일을 pathtest 디렉토리로 옮겼기 때문이다. 그럼 어떻게 해야할까 바로 이때 사용하는 옵션이 -classpath 옵션이다.

    바로 결과부터 보면

    -classpath 뒤에 오는 "파일 절대 경로"를 입력해주면 된다.

    -classpath 옵션은 자바를 실행할 때 사용할 클래스들의 위치를 가상머신에게 알려주는 역할을 한다. 즉 WhatYoutName.class가 실행될 때 필요한 AAA.class, BBB.class의 위치를 가상머신에게 알려주는다는 것이다.

. : 현재 디렉토리에서 클래스를 찾는 다는 뜻이고
;(:) (윈도우에선 ;, 리눅스나, macOS일 경우 : 사용) : 경로와 경로를 구분해주는 구분자
pathtest (개인별로 디렉토리 명이 다르기 때문에 구분해서 사용하자) : 현재 디렉토리에 없으면 현재 디렉토리의 하위 디렉토리 중 pathtest에서 클래스를 찾으라는 의미이다.

접근지시자 🤔

  • 클래스 내에서 멤버의 접근을 제한하는 역할을 함
    • prviate - 같은 클래스 내에서만 접근이 가능하다
    • default - 같은 패키지 내에서만 접근이 가능하다
    • protected - 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스(상속한 경우)에서 접근이 가능하다.
    • public - 접근 제한이 전혀 없다
제어자같은 클래스같은 패키지자식 클래스전 체적용 대상비고
public접근 가능접근 가능접근 가능접근 가능클래스, 멤버
protected접근 가능접근 가능접근 가능접근 불가능멤버클래스에 적용할 수 없음
default접근 가능접근 가능접근 가능접근 불가능클래스, 멤버접근 지정자를 생략한 경우를 말함
private접근 가능접근 불가능접근 불가능접근 불가능멤버클래스에 적용할 수 없음
  • 접근지시자를 사용하는 이유
    • 클래스의 내부에 선언된 데이터를 보호하기 위해서이다.
    • 데이터가 유효한 값을 유지하도록, 또는 비밀번호와 같은 데이터를 외부에서 함부로 변경하지 못하도록 하기 위해서는 외부로부터의 접근을 제한하는 것도 중요하다.
    • 클래스 내에서만 사용되는, 내부 작업을 위해 사용되는 멤버 변수나, 메소드 등을 클래스 내부에 감추기 위해서이다.

참고자료 🧾

0개의 댓글