7주 차 시작!

 

package 키워드

자바의 패키지는 비슷한 성격의 자바 클래스들을 모아 놓은 자바의 디렉터리를 말한다.

크게는 built-in package 와 custom package로 구분할 수 있다.

 

package 키워드는 모든 클래스 파일에 최상단에 존재하여야 하고, 하나의 소스만 존재해야 한다.

 

 

Built-in package? (내장 패키지)

java, lang, javax, net, io, util, math... 등 Java API에 포함된 모든 패키지들을 말한다.

 

Custom package? (사용자 정의 패키지)

사용자(개발자)가 정의한 패키지를 말한다.

 

Sub package? (하위 패키지)

어떤 package 내부에 존재하는 package를 Sub package라고 한다.

이는 하나의 package 에서도 객체의 행위를 기반으로 다시 분류하기 위함이다.

  • 입력, 출력 작업 → io package
  • 네트워크 작업 → net package...

 

package를 사용함으로써 얻을 수 있는 장점

  • 클래스와 인터페이스를 성향, 쓰임세에 맞게 분류하여 쉽게 유지 보수할 수 있다.

  • 접근 지정자를 통한 가시 범위(보호 범위)를 제공한다.

접근 지정자가 명시되지 않은 경우 package-private, 즉 패키지 내에서만 참조 가능하다.

  • 클래스, 인터페이스가 같은 이름을 가짐으로써 발생하는 충돌을 방지한다.

 

package 명명 규칙

  • 패키지 이름은 클래스, 인터페이스 이름과 충돌하지 않도록 소문자로 작성한다.

    → 대문자를 사용하지 않는 것이 좋다. (권고사항)

  • 최상위 도메인/나라 코드. 회사명/팀명/그룹명(회사 내규). 프로젝트명/프로그램 명으로 작성한다.

    → com.example.project (패키지 정의 표준 사항)

  • 자바 예약어를 사용해서는 안된다.

자바 패키지 내부 클래스 실행 방법

// Sample.class
java com.example.project.main.Sample

 

Package Class?

해당 package에 대한 Spec 및 Implement 정보를 얻을 수 있는 메서드를 제공하는 클래스이다.

ClassLoader와 BootLoader를 사용하여 해당 정보를 로드하고 접근한다.

@Test
    void PackageTest() {
        Package aPackage = Package.getPackage("java.lang");
        Package[] aPackages = Package.getPackages();
        System.out.println(Arrays.toString(aPackages));

        System.out.println(aPackages.length);

        // package name
        System.out.println(aPackage.getName());

        // package spec Title
        System.out.println(aPackage.getSpecificationVersion());
        // package spec Vendor
        System.out.println(aPackage.getSpecificationTitle());
        // package spec Version
        System.out.println(aPackage.getSpecificationVendor());

        // package impl Title
        System.out.println(aPackage.getImplementationVersion());
        // package impl Vendor
        System.out.println(aPackage.getImplementationTitle());
        // package impl Version
        System.out.println(aPackage.getImplementationVendor());

        // package annotations
        Annotation[] annotations = aPackage.getAnnotations();
        System.out.println(Arrays.toString(annotations));

        // package declaredAnnotations
        Annotation[] declaredAnnotations = aPackage.getDeclaredAnnotations();
        System.out.println(Arrays.toString(declaredAnnotations));
    }

 

import 키워드

import?

기본적으로 접근할 수 없는 다른 패키지에 접근하기 위해 사용되는 키워드이다.

  • java lang과 현재 패키지에 대해서는 생략할 수 있다.
// 형식
import domain.project(program).subpackage;
import domain.project.*;

// 예시
import org.junit.jupiter.api.Test;

// .* 를 사용함으로써 해당 패키지의 하위 패키지, 클래스를 모두 접근할 수 있다.
import org.junit.jupiter.api.*;

 

static import?

JDK 5에 추가된 기능으로 어떤 클래스의 정적 멤버에게 직접 액세스 할 수 있도록 지원하는 기능이다.

Class 명을 명시하지 않고 static import 설정을 함으로써 정적 멤버만을 명시하여 사용할 수 있다.

  • static variable, static method

장점

  • 자주 사용하는 정적 메서드(기능)를 한결 쉽게 사용할 수 있다.

      import org.junit.jupiter.api.Assertions;
      import org.junit.jupiter.api.Test;
    
      import static org.junit.jupiter.api.Assertions.assertEquals;
    
      @Test
      void staticImportTest() {
          // non-static-import
          Assertions.assertEquals("A", "A");
    
          // static-import
          assertEquals("A", "A");
      }

단점

  • 과도하게 사용하는 경우 (정적 메서드 이름 중복 등) 어떤 클래스의 정적 메서 드을 가져온 것인지 확인하여야 한다. (의도한 동작이 발생하지 않을 수 있고, 로직을 하나하나 찾아보아야 한다.)

 

클래스패스

JVM에서 사용하는 매개변수로 Java 프로그램을 컴파일 및 실행하는 데 사용되며, Built-in package와 Custom package에 경로를 지정하여 Application ClassLoader를 통해 참조, 접근할 수 있다.

 

CLASSPATH를 설정하는 경우

  • 현재 Directory나 Sub Directory에 없는 Class를 사용하여야 하는 경우
  • 지정한 위치에 존재하지 않는 Class를 불러와야 하는 경우

 

CLASSPATH 형식

CLASSPATH는. class 파일이 포함된 디렉터리와 파일을 콜론으로 구분한 목록이다.

  • CLASSPATH의 기본 값은 . 이며, 현재 검색된 Directory를 의미한다.

    → 이는 CLASSPATH 변수나 -classpath 명령에 의해 변경할 수 있다.

  • 여러 클래스 경로를 설정하려면 (새미 콜론) ; 를 사용하여 CLASSPATH를 구분하여야 한다.

 

CLASSPATH를 설정하는 항목에 따라 다른 형식을 가진다

// 지정할 파일이 JAR 또는 zip 인 경우
C:\Program Files\Java\jdk-1.8.0.252-2\jre\lib\resources.jar
C:\Program Files\Java\jre1.8\MySQL-Connector Java.jar
C:\Users\xxx\Downloads\example.zip

// 클래스 파일 이름이 지정되지 않은 패키지에 있는 경우
C:\Users\xxx\someDirectory

 

자바에서 사용되는 CLASSPATH Library는 GNU CLASSPATH라는 opensource이다.

 

GNU CLASSPATH Properties

  • gcj.dumpobject

    빈 문자열이 아닌 문자열을 설정한 경우, Library Debug build에 사용되는 Serialize Debuging을 활성화시킨다.

  • gnu.classpath.vm.shortname

    VM의 간결한 이름을 나타낸다.

  • gnu.classpath.home.url

    시스템 속성 파일을 찾는 데 사용되는 기본 URL Pattern 값을 지정한다.

    기본적으로 java.home의 lib Directory를 가리키는 값을 가진다.

추가! )

Spring Framework에서 사용되는 표준 Resolver인 PathMatchingResourcePatternResolver는 리소스에 접근할 때 CLASSPATH Pattern으로 매개변수를 받아 접근한다.

PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
resolver.getResources("classpath:mybatis/mapper/*.xml")

 

CLASSPATH 환경변수

고급 시스템 설정 / CLASSPATH 변수 설정

Window의 경우 win + Pause key를 눌러 제어판 \ 모든 제어판 항목 \ 시스템으로 이동할 수 있다.

여기서 고급 시스템 설정으로 들어간다.

여기서 환경 변수를 클릭하면 사용자 변수와 시스템 변수를 수정, 추가할 수 있다.

CLASSPATH 속성이 있는 경우 편집 버튼을 클릭하고 ;을 입력한 뒤 파일 경로를 추가하면 된다.

없는 경우에는 새로 만들기를 클릭하고 변수의 이름을 CLASSPATH로 설정한 뒤 값을 지정한다.

 

명령 프롬프트 설정

명령 프롬프트를 실행시킨 뒤

// 클래스 패스 속성이 이미 설정된 경우
SET CLASSPATH=%CLASSPATH%;C:\Program Files\Java\jdk-1.8.0.252-2\jre\lib\resources.jar

// 없는 경우
SET CLASSPATH=C:\Program Files\Java\jdk-1.8.0.252-2\jre\lib\resources.jar

;을 우선 작성하고 추가할 파일의 경로를 작성한다.

→ %으로 묶여 있는 변수는 기존의 환경 변수를 뜻한다.

 

CLASSPATH 옵션

. java 파일을 컴파일하기 전에 해당 파일이 필요로 하는 클래스들을 찾기 위해 사용하는 옵션이다.

-classpath 뒤에 Directory Path를 작성하면 컴파일 시 해당 Directory를 탐색하게 된다.

// javac -classpath <find-Directory-path> <Executable-file-path>
javac -classpath C:\Java\example example.java

 

접근 지시자

public : 모든 클래스에서 해당 클래스를 참조 가능하다.

public class PublicExample {

    public static void main(String[] args) {
        PublicExample example = new PublicExample();
        example.run();
    }

    public void run() {
        PublicClass publicClass = new PublicClass();
        publicClass.getName();
    }
}

public class PrivateClass {
    private final String name = "Lob!";

    private void getName() {
        System.out.println("PrivateClass.getName = " + name);
    }
}
PublicClass.getName = Lob!

 

package-private : 해당 클래스가 포함된 패키지 내에서만 참조 가능하다. (지정이 없는 경우)

public class PackagePrivateExample {

    public static void main(String[] args) {
        PackagePrivateExample example = new PackagePrivateExample();
        example.run();
    }

    public void run() {
        PackagePrivateClass packagePrivateClass = new PackagePrivateClass();
        // error: getName() is not public in PackagePrivateClass; cannot be accessed 
        // from outside package packagePrivateClass.getName();
        packagePrivateClass.getName();
    }
}

public class PackagePrivateClass {
    final String name = "Lob!";

    void getName() {
        System.out.println("PackagePrivateClass.getName = " + name);
    }

}

 

protect : 서브, 하위 클래스와 동일 패키지 내부에 존재하는 클래스만 참조 가능하다.

  • 기본적인 Class 에는 적용할 수 없으며, 중첩, 내부 클래스에는 적용 가능하다.
public class ProtectExample extends ProtectClass{

    public static void main(String[] args) {
        ProtectExample example = new ProtectExample();
        example.run();
    }

    public void run() {
        ProtectClass protectClass = new ProtectClass();
        protectClass.getName();
    }
}

public class ProtectExample2 {

    public static void main(String[] args) {
        ProtectExample example = new ProtectExample();
        example.run();
    }

    public void run() {
        ProtectClass protectClass = new ProtectClass();
        protectClass.getName();
    }
}

public class ProtectClass {

    private final String name = "Lob!";

    protected void getName() {
        System.out.println("ProtectClass.getName = " + name);
    }
}

--------------------------
// (패키지 외부) = 상속시 사용 가능
public class ProtectExample3 {

    public static void main(String[] args) {
        ProtectExample example = new ProtectExample();
        example.run();
    }

    public void run() {
        ProtectClass protectClass = new ProtectClass();
        // error: getName() has protected access in ProtectClass protectClass.getName();
        protectClass.getName();
    }
}
// ProtectExample 
ProtectClass.getName = Lob!

// ProtectExample2 
ProtectClass.getName = Lob!

 

private : 자기 자신인 객체 내부에서만 참조 가능하다. (인터페이스도 JDK9부터 사용 가능)

public class PrivateExample {

    public static void main(String[] args) {
        PrivateExample example = new PrivateExample();
        example.run();
    }

    public void run() {
        PrivateClass privateClass = new PrivateClass();

                // 'getName()' has private access in 'example.accessmodifiers.PrivateClass'
        privateClass.getName();
    }
}

-----------------------------

public class PrivateClass {
    private final String name = "Lob!";

    private void getName() {
        System.out.println("PrivateClass.getName = " + name);
    }
}
error: getName() has private access in PrivateClass privateClass.getName();

 

참고 자료

'Live Study' 카테고리의 다른 글

Live Study_Week 09. 예외 처리  (0) 2021.01.11
Live Study_Week 08. 인터페이스  (0) 2021.01.05
Live Study_Week 06. 상속  (0) 2020.12.21
Live Study_Week 05. 클래스  (0) 2020.12.15
Live Study_Week 04. 제어문 + 과제  (0) 2020.12.01

+ Recent posts