Java 101 : 패키지는 클래스 및 인터페이스 구성

바퀴를 재발 명하는 이유는 무엇입니까? 이 진부한 표현은 일부 개발자가 다른 프로그램에 대해 동일한 코드를 자주 다시 작성하는 소프트웨어 개발에 적용됩니다. 이러한 접근 방식의 두 가지 단점은 다음과 같습니다.

  1. 시간 낭비
  2. 디버깅 된 코드의 버그 가능성을 소개합니다.

동일한 코드를 다시 작성하는 대신 많은 소프트웨어 개발 환경에서 자주 사용되는 코드를 구성하는 라이브러리 도구를 제공합니다. 개발자가 재사용 가능한 코드 디버깅을 마치면 도구를 사용하여 다양한 프로그램에서 사용하기 위해 자주 사용되는 코드가 포함 된 하나 이상의 파일 인 라이브러리에 해당 코드를 저장 합니다. 프로그램을 빌드하는 동안 컴파일러 또는 라이브러리 도구는 라이브러리에 액세스하여 프로그램의 라이브러리 참조 코드를 프로그램에 연결합니다.

라이브러리는 Java의 기본입니다. 부분적으로 JVM의 클래스 로더가 클래스 파일을 찾을 수 있습니다. (향후 기사에서 클래스 로더를 살펴볼 것입니다.) 이러한 이유로 Java의 라이브러리는 일반적으로 클래스 라이브러리 로 알려져 있습니다. 그러나 Java는 클래스 라이브러리를 패키지 로 참조 합니다.

이 기사에서는 패키지를 살펴 봅니다. 클래스 및 인터페이스 패키지를 만드는 방법, 패키지 클래스 및 인터페이스를 가져 오는 방법 (즉, 프로그램으로 가져 오기), 하드 드라이브에서 패키지를 이동하는 방법, jar 파일을 사용하여 패키지를 캡슐화하는 방법을 보여줍니다.

노트
이 기사의 단일 패키지 실험은 Microsoft Windows에만 해당됩니다. 이 실험을 비 Windows 플랫폼으로 쉽게 추정 할 수 있어야합니다.

패키지 란?

패키지 클래스 및 인터페이스의 집합이다. 각 패키지에는 고유 한 이름이 있으며 최상위 (즉, 중첩되지 않은) 클래스와 인터페이스를 별도의 네임 스페이스 또는 이름 컬렉션으로 구성합니다. 동일한 이름의 클래스와 인터페이스는 동일한 패키지에 나타날 수 없지만 별도의 네임 스페이스가 각 패키지에 할당되기 때문에 서로 다른 패키지에 나타날 수 있습니다.

구현 관점에서 패키지를 디렉토리와 동일시하면 패키지의 클래스와 인터페이스를 디렉토리의 클래스 파일과 동일시하는 것이 도움이됩니다. 패키지 구현에 대한 데이터베이스 사용과 같은 다른 접근 방식을 염두에 두십시오. 따라서 항상 패키지를 디렉토리와 동일시하는 습관을 들이지 마십시오. 그러나 많은 JVM이 디렉토리를 사용하여 패키지를 구현하기 때문에이 기사에서는 패키지를 디렉토리와 동일시합니다. Java 2 SDK는 방대한 클래스 및 인터페이스 컬렉션을 패키지 내의 트리와 같은 패키지 계층 구조로 구성합니다. 이는 디렉터리 내의 디렉터리와 동일합니다. 이러한 계층 구조를 통해 Sun Microsystems는 이러한 클래스와 인터페이스를 쉽게 배포 할 수 있습니다 (그리고 쉽게 작업 할 수 있습니다). Java 패키지의 예는 다음과 같습니다.

  • java.lang:패키지의 하위 패키지에 구성된 Object및 등의 언어 관련 클래스 모음Stringjavalang
  • java.lang.ref:패키지 하위 패키지의 하위 패키지에 구성된 SoftReference및 등의 참조 관련 언어 클래스 모음ReferenceQueuerefjavalang
  • javax.swing:스윙 관련 구성 요소와 같은 클래스의 모음 JButton과 같은, 인터페이스, ButtonModel구성, javax패키지의 swing하위 패키지

마침표는 패키지 이름을 구분합니다. 예를 들어에서 javax.swing마침표 문자는 패키지 이름 javax과 하위 패키지 이름 을 구분합니다 swing. 마침표 문자는 디렉토리 기반 패키지 구현에서 디렉토리 이름을 구분하기위한 슬래시 문자 ( /), 백 슬래시 문자 ( \) 또는 기타 문자, 계층 적 데이터베이스 기반 패키지 구현의 데이터베이스 분기 등에 해당하는 플랫폼 독립적입니다 . .

동일한 디렉토리에 동일한 이름을 가진 파일과 디렉토리를 모두 저장할 수없는 것처럼 동일한 패키지에 동일한 이름을 가진 클래스 또는 인터페이스와 패키지를 저장할 수 없습니다. 예를 들어,라는 이름의 패키지를 제공 accounts, 당신은 패키지라는 이름의 클래스를 모두 저장할 수 없습니다 payable에를 accounts. 이름 충돌을 방지하려면 클래스 및 인터페이스 이름의 첫 글자를 대문자로, 패키지 이름의 첫 글자를 소문자로합니다. 앞의 예를 사용하여 저장 클래스 Payable패키지 accountsaccounts.Payable패키지 payable패키지 accountsaccounts.payable. Sun의 Code Conventions for the Java Programming Language 에서 이것과 기타 명명 규칙에 대해 자세히 알아보십시오 .

클래스 및 인터페이스 패키지 만들기

모든 소스 파일의 클래스와 인터페이스는 패키지로 구성됩니다. 에서 package지침의 부재, 그 클래스와 인터페이스는 이름이없는 패키지 (자바 프로그램이 윈도우를 통해 실행을 시작하는 현재 디렉토리 - 디렉토리와 같은 JVM 안부 디렉토리에 속하는 java.exe, 또는 OS 동등한, 프로그램 및 더 서브 패키지를 포함하지) . 그러나 package지시문이 소스 파일에 나타나면 해당 지시문은 해당 클래스 및 인터페이스의 패키지 이름을 지정합니다. 다음 구문을 사용하여 package소스 코드에서 지시문 을 지정합니다 .

'패키지' packageName [ '.' subpackageName ...] ';'

package지시어는 시작 package키워드. 패키지는 이름 식별자 packageName, 즉시 다음과 같습니다. 클래스와 인터페이스가 내 하위 패키지 (일부 수준)에 표시되는 packageName경우 하나 이상의 마침표로 구분 된 subpackageName식별자가 packageName. 다음 코드 조각은 한 쌍의 package지시문을 나타냅니다 .

패키지 게임; 패키지 game.devices;

첫 번째 package지시문은라는 패키지를 식별합니다 game. 해당 지시문의 소스 파일에 나타나는 모든 클래스와 인터페이스는 game패키지에 구성 됩니다. 두 번째 package지시어를 식별라는 이름의 하위 패키지 devices라는 이름의 패키지에있는, game. 해당 지시문의 소스 파일에 나타나는 모든 클래스와 인터페이스는 game패키지의 devices하위 패키지에 구성됩니다 . JVM 구현이 패키지 이름을 디렉토리 이름에 game.devices매핑하는 경우 game\devicesWindows에서는 game/devices디렉토리 계층, Linux 또는 Solaris 에서는 디렉토리 계층에 매핑됩니다 .

주의
하나의 package지시문 만 소스 파일에 나타날 수 있습니다. 또한 package지시문은 해당 파일의 첫 번째 코드 (주석 제외) 여야합니다. 두 규칙 중 하나를 위반하면 Java 컴파일러가 오류를보고합니다.

패키지에 익숙해지는 데 도움이되도록이 기사의 모든 주제에 적용되는 예제를 준비했습니다. 이 섹션에서는 예제 패키지를 만드는 방법을 알아 봅니다. 이후 섹션에서는이 패키지에서 클래스와 인터페이스를 가져 오는 방법,이 패키지를 하드 드라이브의 다른 위치로 이동하고 프로그램에서 패키지에 계속 액세스하는 방법, 패키지를 jar 파일에 저장하는 방법에 대해 알아 봅니다. . 목록 1은 패키지의 소스 코드를 보여줍니다.

목록 1. A.java

// A.java 패키지 testpkg; 공용 클래스 A {int x = 1; public int y = 2; 보호 된 int z = 3; int returnx () {return x; } public int returny () {return y; } protected int returnz () {return z; } 공용 인터페이스 StartStop {무효 시작 (); 무효 정지 (); }} class B {public static void hello () {System.out.println ( "hello"); }}

목록 1은 첫 번째 명명 된 패키지에 대한 소스 코드를 소개합니다. package testpkg;지시어 이름 패키지 그 testpkg. 내 testpkg클래스는 AB. 내 A세 개의 필드 선언, 세 가지 방법을 선언하고, 내부 인터페이스 선언이다. 내부 B에는 단일 메서드 선언이 있습니다. 공개 클래스 A.java이기 때문에 전체 소스 코드가 저장됩니다 A. 우리의 작업 :이 소스 코드를 두 개의 클래스와 내부 인터페이스 (또는 세 개의 클래스 파일을 포함하는 디렉토리)로 구성된 패키지로 변환합니다. 다음 Windows 관련 단계는 해당 작업을 수행합니다.

  1. Windows 명령 창을 열고 c:드라이브의 루트 디렉토리 (기본 디렉토리-초기 백 슬래시 ( \) 문자로 표시됨)에 있는지 확인합니다 . 이를 수행하려면 c:명령 다음에 명령을 입력하십시오 cd \. (다른 드라이브를 사용하는 경우 c:선택한 드라이브로 교체 하십시오. 또한 명령을 입력 한 후 Enter 키를 누르는 것을 잊지 마십시오.)
  2. testpkg를 입력 하여 디렉토리를 만듭니다 md testpkg. 참고 : 이 문서의 단계를 따를 때 명령 뒤에 마침표를 입력하지 마십시오.
  3. testpkg를 입력하여 현재 디렉토리를 만듭니다 cd testpkg.
  4. 에 목록 1의 소스 코드와 그 코드 저장를 입력 편집기를 사용 A.java에서 파일 testpkg.
  5. A.java을 입력하여 컴파일하십시오 javac A.java. 디렉토리 에 클래스 파일 A$StartStop.class, A.class및이 B.class표시되어야합니다 testpkg.

그림 1은 3 ~ 5 단계를 보여줍니다.

축하합니다! 방금 첫 번째 패키지를 만들었습니다. 이 패키지에는 두 개의 클래스 ( AB) A와의 단일 내부 인터페이스 ( StartStop)가 포함되어 있다고 생각하십시오 . : 당신은 또한 세 개의 클래스 파일을 포함하는 디렉토리로이 패키지 생각할 수있는 A$StartStop.class, A.class하고 B.class.

노트
패키지 이름 충돌 (특히 상용 패키지 간)을 최소화하기 위해 Sun은 회사의 인터넷 도메인 이름이 패키지 이름을 반대로 바꾸고 접두사를 붙이는 규칙을 제정했습니다. 예를 들어, x.com인터넷 도메인 이름과 a.b패키지 이름 ( a) 뒤에 하위 패키지 이름 ( b) 접두사 com.xa.b있는 회사는 com.x.a.b. testpkg패키지가 교육 목적으로 만 설계된 일회용 이기 때문에 내 기사는이 규칙을 따르지 않습니다 .

패키지의 클래스 및 인터페이스 가져 오기

Once you have a package, you will want to import classes and/or interfaces—actually, class and/or interface names—from that package to your program, so it can use those classes and/or interfaces. One way to accomplish that task is to supply the fully qualified package name (the package name and all subpackage names) in each place where the reference type name (the class or interface name) appears, as Listing 2 demonstrates:

Listing 2. Usetestpkg1.java

// Usetestpkg1.java class Usetestpkg1 implements testpkg.A.StartStop { public static void main (String [] args) { testpkg.A a = new testpkg.A (); System.out.println (a.y); System.out.println (a.returny ()); Usetestpkg1 utp = new Usetestpkg1 (); utp.start (); utp.stop (); } public void start () { System.out.println ("Start"); } public void stop () { System.out.println ("Stop"); } } 

By prefixing testpkg. to A, Usetestpkg1 accesses testpkg's class A in two places and A's inner interface StartStop in one place. Complete the following steps to compile and run Usetestpkg1:

  1. Open a Windows command window and make sure you are in the c: drive's root directory.
  2. Ensure the classpath environment variable does not exist by executing set classpath=. (I discuss classpath later in this article.)
  3. Use an editor to enter Listing 2's source code and save that code to a Usetestpkg1.java file in the root directory.
  4. Compile Usetestpkg1.java by typing javac Usetestpkg1.java. You should see classfile Usetestpkg1.class appear in the root directory.
  5. Type java Usetestpkg1 to run this program.

Figure 2 illustrates Steps 3 through 5 and shows the program's output.

According to Usetestpkg1's output, the main() method's thread successfully accesses testpkg.A's y field and calls the returny() method. Furthermore, the output shows a successful implementation of the testpkg.A.StartStop inner interface.

For Usetestpkg1, prefixing testpkg. to A in three places doesn't seem a big deal. But who wants to specify a fully qualified package name prefix in a hundred places? Fortunately, Java supplies the import directive to import a package's public reference type name(s), so you do not have to enter fully qualified package name prefixes. Express an import directive in source code via the following syntax:

'import' packageName [ '.' subpackageName ... ] '.' ( referencetypeName | '*' ) ';' 

An import directive consists of the import keyword immediately followed by an identifier that names a package, packageName. An optional list of subpackageName identifiers follows to identify the appropriate subpackage (if necessary). The directive concludes with either a referencetypeName identifier that identifies a specific class or interface from the package, or an asterisk (*) character. If referencetypeName appears, the directive is a single-type import directive. If an asterisk character appears, the directive is a type-on-demand import directive.

Caution
As with the package directive, import directives must appear before any other code, with three exceptions: a package directive, other import directives, or comments.

The single-type import directive imports the name of a single public reference type from a package, as the following code fragment demonstrates:

import java.util.Date; 

The previous single-type import directive imports class name Date into source code. As a result, you specify Date instead of java.util.Date in each place that class name appears in source code. For example, when creating a Date object, specify Date d = new Date (); instead of java.util.Date d = new java.util.Date ();.

단일 유형 import지시문으로 주의를 기울이십시오 . 컴파일러 import가 소스 파일에도 선언 된 참조 유형 이름을 지정 하는 단일 유형 지시문을 감지하면 컴파일러는 다음 코드 조각이 보여주는 것처럼 오류를보고합니다.

import java.util.Date; 클래스 날짜 {}

컴파일러는 코드 조각을 동일한 Date이름 의 두 참조 유형을 도입하려는 시도로 간주합니다 .