ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [whiteship] 온라인스터디 - 7주차.패키지
    카테고리 없음 2020. 12. 30. 21:48

     

    github.com/whiteship/live-study/issues/7

     

    7주차 과제: 패키지 · Issue #7 · whiteship/live-study

    목표 자바의 패키지에 대해 학습하세요. 학습할 것 (필수) package 키워드 import 키워드 클래스패스 CLASSPATH 환경변수 -classpath 옵션 접근지시자 마감일시 2021년 1월 2일 토요일 오후 1시까지.

    github.com

    목표

    자바의 패키지에 대해 학습하세요.

    학습할 것 (필수)

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

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

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

    package 키워드

    클래스의 이름을 정하지만, 클래스의 실제 이름은 패키지 명에 포함된다.
    예를들어 String 클래스의 패키지명을 포함한 이름은 java.lang.String이다. 즉, java.lang 패키지에 속한 String 클래스라는 의미이다.. 그래서 같은 이름의 클래스일 지라도 서로 다른 패키지에 속하면 패키지명으로 구별이 가능하다.

     

    선언 방법

    package 패키지명;

    특징

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

     

    import 키워드

    소스코드를 작성할 때 다른 패키지의 클래스를 사용하려면 패키지명이 포함된 클래스 이름을 사용해야 한다. 하지만, 매번 패키지명을 붙여서 작성하긴 쉽지 않다.

    클래스의 코드를 작성하기 전에 import 문으로 사용하고자 하는 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명은 생략할 수 있다.

    import문의 역할은 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공하는 것이다. 컴파일 시에 컴파일러는 import문을 통해 소스파일에 사용된 클래스들의 패키지를 알아 낸 다음, 모든 클래스 이름 앞에 패키지명을 붙여준다.

     

    선언 방법

    import 패키지명.클래스명;
     또는
    import 패키지명.*;

    일반적으로 IDE에서 자동으로 추가해주거나 유사한 패키지를 추천해준다.

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

     

    static import 문

    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());
        }
    }
    

     

    클래스패스, -classpath 옵션

    자바를 설치할 때, 자연스럽게 따라하는 몇 가지 설정이 있다.

    $JAVA_HOME과 $CLASSPATH 설정이다. 클래스 패스가 무엇인지 먼저 알아본다.

     

    클래스 패스란, 자바의 가상머신 (JVM)이 컴파일된 클래스 파일(.class)을 실행시킬 때, 클래스패스에 설정된 경로에서 해당 파일을 찾는다. 그래서 자바파일을 컴파일 할 때는 아래와 같이 클래스패스 경로를 지정해주어야 한다.

     

    Windows - 세미콜론 사용

    java -classpath ".;lib" ClasspathTest

    Linux, OSX 유닉스 계열의 시스템 - 콜론 사용 

    java -classpath ".:lib" ClasspathTest

    옵션 -classpath를 사용하여 자바를 실행할 때 사용할 클래스들의 위치를 가상머신에 알려주는 역할을 합니다.

     

    ".;lib" 뜯어보기

     

    .

    현재 디렉터리에서 클래스를 찾는다는 의미

    ;

    경로와 경로를 구분해주는 구분자

    lib

    현재 디렉터리에 없다면 현재 디렉터리의 하위 디렉터리 중 lib에서 클래스를 찾는다는 의미

     

    만약 .을 제외한다면, 현재 디렉토리의 클래스를 찾지 못한다. 하지만 하위 lib 디렉토리에 있는 클래스는 찾을 수 있다.

     

     

    CLASSPATH 환경변수

    환경변수는 운영체제에 지정하는 변수로 자바 가상머신과 같은 애플리케이션들은 환경변수 값을 참고해서 동작하게 된다. 자바는 클래스 패스로 환경변수 CLASSPATH를 사용하는데 이 값을 지정하면 실행할 때마다 -classpath 옵션을 사용하지 않아도 된다. 하지만 운영체제를 변경하면 클래스 패스가 사라지기 때문에 이식성면에서 불리할 수 있다.

    windows

    시스템 설정 > 환경변수

     

    리눅스, 유닉스 계열이 시스템

    /etc/profile 에 추가

     

    IDE의 자동 클래스패스 설정

     

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

    접근지시자

    - 접근의 허용 범위를 제한하는 용도

    - 종류 : public, private, protected, default

    지시자 클래스내부 동일패키지 상속받은 클래스 이외의영역
    private 접근 허용 접근 불가 접근 불가 접근 불가
    default 접근 허용 접근 허용 접근 불가 접근 불가
    protected 접근 허용 접근 허용 접근 허용 접근 불가
    public 접근 허용 접근 허용 접근 허용 접근 허용

    메소드나 인스턴스 변수를 선언할 때, 이름 앞에 다음과 같은 접근 지시자가 설정되어있는 것을 볼 수 있다.

    프로그래밍 언어에는 어느 영역까지의 접근을 허용한다.

     

    1. private

    - 인스턴스 변수와 메소드는 선언된 클래스 내부에서 접근 가능

    2. default : 접근 지시자를 선언하지 않은 경우

    - 동일 패키지 내의 접근을 허용

    3. protected

    - 상속 받은 클래스에 접근을 허용

    4. public

    - 어디서든 접근 가능한 인스턴스 변수 및 메소드

     

     

    String class를 확인 하며 위의 내용을 확인해 본다.

    ( String 클래스는 package java.lang; 패키지에 있다 ) 

     

    외부의 Test 클래스에서 String 인스턴스를 생성한 뒤 value 값에 접근해 본다.

    위처럼 value 값에 접근하려면 private access라는 오류와 함께 접근이 불가하다.

    즉 String class 내부에서는 value값에 접근 가능하지만, 외부 클래스에서는 private 변수의 값에 접근을 할 수 없다.

    그렇다면 어떻게 접근해야 할까?? String class 내부에서 value를 사용하는 메서드를 찾아본다.

     

    String () 생성자는 public으로 선언되었기 때문에 외부 클래스 (Test 클래스) 에서 접근 가능한 것을 알 수 있다.

     

    위와 같이 public 으로 생성된 생성자에서 value 값을 할당해주는 것을 알 수 있다.

    빈 생성자로 생성하였으므로, 초기 value 값은 ""로 초기화 된다.

     

    protected는 상속관계에서 접근이 가능하다고 하였다.

    String 클래스에는 protected 지시자를 사용하는 것이 없어, 다른 클래스를 참고해보았다.

    HashMap을 살펴본다.

    HashMap은 AbstractMap을 상속받고 Map, Clonable, Serializable 인터페이스를 구현한다.

    AbstractMap을 살펴본다.

     

    AbstractMap은 Map 인터페이스를 구현한다.

    AbstractMap에서 protected를 사용한 것을 찾아보면, 생성자와 clone() 메서드를 확인 할 수 있다.

    HashMap에서 사용하는 clone 메서드를 확인해본다.

     AbstractMap에서의 clone()
    HashMap에서 override한 clone()

    protected는 상속관계에서 사용이 가능하다고 하였다.

    HashMap은 AbstractMap을 상속하였기 때문에 clone을 사용할 수 있다.

    Test 클래스에서 clone을 사용하려고하면, 접근이 불가하다.

    HashMap에서 clone의 접근 지시자를 public으로 한 것은 AbstractMap에서 protected로 선언된 clone 메서드를 외부 다른 곳에서 사용할 수 있게 하기위하여 public으로 선언했다.

     

    예를 들어, Test 클래스에서 다음과 같이 AbstractMap을 상속받는 TestProtected 클래스를 생성하고  인스턴스로 생성 후 clone을 접근해보면, 접근이 되지않는다. 그리고, TestProtected 클래스에 빨간줄이 생기며 access privileges를 할당하라고 팁을 준다. ( 갓텔리제이 짱... )

     

    public으로 설정하면 정상적으로 외부 클래스에서 접근이 가능하다.

     

    댓글

Designed by Gintire