2021. 1. 1.

7주차 과제: 패키지

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

목표

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

학습할 것 (필수)

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


package 키워드

//in the Draggable.java file
package graphics;
public interface Draggable {
    . . .
}

//in the Graphic.java file
package graphics;
public abstract class Graphic {
    . . .
}

//in the Circle.java file
package graphics;
public class Circle extends Graphic
    implements Draggable {
    . . .
}

//in the Rectangle.java file
package graphics;
public class Rectangle extends Graphic
    implements Draggable {
    . . .
}

//in the Point.java file
package graphics;
public class Point extends Graphic
    implements Draggable {
    . . .
}

//in the Line.java file
package graphics;
public class Line extends Graphic
    implements Draggable {
    . . .
}
  • package 선언은 소스 파일 최상단에
  • 1개의 소스 파일은 1개의 패키지만 선언 가능
  • 1개의 소스 파일에 여러 타입을 넣는 경우 한 개의 타입은 'public'이며 소스 파일 이름과 동일해야 함
    ex) 'public class Circle'의 소스 파일 이름 'Circle.java', 'public interface Draggable'의 소스 파일 이름 'Draggable.java', 'public enum Day'의 소스 파일 이름 'Day.java'
  • 'public' 타입과 동일한 파일에 'private' 타입을 포함할 수 있지만('private' 타입이 작고 'public' 타입과 밀접한 관련이 있는 경우를 제외하고는 강력히 권장하지 않음) 'public' 타입만 외부에서 접근 가능

전 세계 프로그래머가 Java 언어를 사용하여 클래스와 인터페이스에 같은 이름을 사용할 가능성이 높다. 예) java.awt 패키지에 이미 Rectangle 클래스가 있을 때 Rectangle 클래스를 정의. 그래도 컴파일러는 두 클래스가 다른 패키지에 있을 경우 같은 이름을 허락한다. Rectangle 클래스의 정규화 이름(fully qualified name)에 패키지 이름이 포함된다. graphics 패키지의 Retangle 클래스의 정규화 이름은 'graphics.Rectangle', java.awt 패키지의 Retangle 클래스의 정규화 이름은 'java.awt.Rectangle'.

두명의 프로그래머가 동일한 패키지 이름을 사용하지 않는한 잘 작동합니다. 이 문제를 방지하는 방법은? 규칙 (Convention)

패키지 명명 규칙

  • 패키지 이름은 클래스 or 인터페이스 이름과 충돌하지 않도록 모두 소문자로 작성
  • 역방향 인터넷 도메인 이름을 사용 ex) example.com에서 만든 mypackage 패키지 → com.example.mypackage
  • 회사 내에서 발생하는 이름 충돌은 회사 이름 뒤에 지역 or 프로젝트 이름 (ex: com.example.region.mypackage)을 포함하여 사내 규칙에 따라 처리)
  • Java 언어 안의 패키지는 java or javax로 시작
  • 도메인 이름이 패키지 이름으로 적절하지 않거나 하이픈, 특수문자, Java 키워드, 이름규칙에 안맞는 숫자 문자가 포함될 경우 다음 예시와 같이 처리

출처: https://docs.oracle.com/javase/tutorial/java/package/createpkgs.html


import 키워드

// 정규화 이름 사용 예
graphics.Rectangle myRect = new graphics.Rectangle();
import graphics.Rectangle;
. . .
// import 사용 예
Rectangle myRectangle = new Rectangle();
. . .
import graphics.*;
. . .
// 패키지 내 모든 내용 import 사용 예
Circle myCircle = new Circle();
Rectangle myRectangle = new Rectangle();
. . .
// 패키지가 계층적으로 보이지만 사실 그렇지 않음
// 예) java.awt.* 이 java.awt 패키지의 모든 내용을 가져올 것 같지만
// java.awt.color, java.awt.font 같은 패키지 내용을 가져오지 않음
import java.awt.*;
import java.awt.color.*;

가져온 두 패키지의 맴버 이름이 동일하면 정규화 이름을 사용

java.awt.Rectangle rect1;
graphics.Rectangle rect2;

Static Import

하나 or 두 개의 클래스에서 static final fields (constants 상수)와 static 메소드에 자주 접근해야 하는 상황이 있습니다. 이러한 클래스 이름을 반복해서 붙이면 코드가 복잡해질 수 있습니다. static import 선언을 사용하면 상수와 static 메소드를 가져오는 방법을 제공하므로 해당 클래스의 접두사를 지정할 필요가 없습니다.

java.lang.Math 클래스는 PI 상수와 많은 static 메소드, 사인, 코사인, 탄젠트 등등을 포함합니다. 예를 들어

public static final double PI 
    = 3.141592653589793;
public static double cos(double a)
{
    ...
}

일반적으로 다른 클래스의 객체를 사용하려면 다음과 같이 클래스 이름을 접두사로 지정

double r = Math.cos(Math.PI * theta);

static import를 사용하면 'java.lang.Math'의 static members를 가져올 수 있으므로 Math 접두사를 붙일 필요가 없습니다. Math의 static members는 개별적으로 불러올 수 있습니다.

import static java.lang.Math.PI;
import static java.lang.Math.*;

// 불러온 static members는 제한없이 사용할 수 있다.
double r = cos(PI * theta);

// 자주 사용하는 상수와 static 메소드를 포함하는 클래스를 작성한 다음
// import 문을 사용할 수 있습니다.
import static mypackage.MyConstants.*;

'static import'는 매우 절약해서 사용하세요. 과도하게 사용하면 코드를 읽는 사람이 특정 static 객체가 어느 클래스에서 정의됐는지 알 수 없기 때문에 코드를 읽고 유지 관리하기 어려울 수 있습니다. 올바르게 사용하면 static import 사용해 클래스 이름의 반복을 제거해 코드를 더 쉽게 읽을 수 있습니다.

출처: https://docs.oracle.com/javase/tutorial/java/package/usepkgs.html


클래스패스

컴파일러와 JVM이 .class 파일을 찾을 수 있도록 설정하는 경로

<출력 파일의 상위 디렉터리 경로>\com\example\graphics\Rectangle.class
<출력 파일의 상위 디렉터리 경로>\com\example\graphics\Helper.class
<path_one>\sources\com\example\graphics\Rectangle.java
<path_two>\classes\com\example\graphics\Rectangle.class

이렇게 하면 소스를 공개하지 않고 다른 프로그래머에게 클래스 디렉토리를 제공할 수 있다. 또한 컴파일러와 JVM이 프로그램에서 사용하는 모든 타입을 찾을 수 있도록 이러한 방식으로 소스 및 클래스 파일을 관리해야 한다.

현재 CLASSPATH 값 확인
In Windows:   C:\> set CLASSPATH
In UNIX:      % echo $CLASSPATH

현재 CLASSPATH 값 삭제
In Windows:   C:\> set CLASSPATH=
In UNIX:      % unset CLASSPATH; export CLASSPATH

CLASSPATH 설정 예시
In Windows:
C:\> set CLASSPATH=C:\users\george\java\classes
In UNIX:
% CLASSPATH=/home/george/java/classes; export CLASSPATH

출처: https://docs.oracle.com/javase/tutorial/java/package/managingfiles.html


CLASSPATH 환경변수

읽어보기: https://hyoje420.tistory.com/7

https://effectivesquid.tistory.com/entry/자바-클래스패스classpath란


-classpath 옵션

클래스 경로를 지정하는 기본 방법은 -cp 명령어를 사용. 이를 통해 다른 애플리케이션에 영향을 주지 않고 각 애플리케이션에 개별적으로 CLASSPATH를 설정할 수 있다.

javac -cp C:\Java\jdk1.7.0\bin;C:\Windows\System32\
java -cp C:\Java\jdk1.7.0\bin;C:\Windows\System32\

출처: https://docs.oracle.com/javase/tutorial/essential/environment/paths.html


접근지시자

패키지 레벨과 관련있는 접근지시자

출처: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

public: 제한없이 접근 가능

protected: 자신의 패키지 내에서만 접근 가능

default(접근 지시자가 없는 경우): 자신의 패키지 내에서만 접근 가능

private: 클래스 내에서만 접근 가능

댓글 없음:

댓글 쓰기