클래스 객체에서 getPackage 메소드를 호출하면 클래스가 위치한 패키지를 설명하는 패키지 개체를 얻을 수 있습니다 (패키지 클래스는 java.lang에 정의됩니다). 또한 패키지 이름을 사용하여 정적 메소드 getPackage를 호출하거나 정적 메소드 getPackages (시스템에서 알려진 모든 패키지로 구성된 배열을 반환)를 호출하여 패키지 개체를 얻을 수 있습니다. getName 메소드는 패키지의 전체 이름을 반환 할 수 있습니다.
패키지 개체의 사용은 다른 반사 유형과 완전히 다릅니다. 즉 런타임에 패키지를 만들거나 조작 할 수 없습니다. 패키지 개체를 사용하여 패키지의 목적, 패키지를 만든 패키지, 패키지 버전 등과 같은 패키지에 대한 정보를 얻을 수 있습니다. 나중에 자세히 논의 할 때까지 이러한 내용을 연기합니다.
패키지의 이름 지정
패키지 이름은 다른 패키지와의 충돌을 피해야하므로 의미 있고 독특한 이름을 선택하는 것은 패키지 디자인의 중요한 측면입니다. 그러나 전 세계의 프로그래머가 패키지를 개발하고 있으며 누가 패키지 이름을 사용했는지 알 수있는 방법이 없으므로 유일한 패키지 이름을 선택하는 것은 문제입니다. 패키지가 조직 내에서만 사용된다고 판단하면 프로젝트 간의 이름 충돌이 없는지 확인하기 위해 내부 중재인을 가질 수 있습니다.
그러나 전 세계의 경우이 접근법은 실용적이지 않습니다. 패키지 식별자는 모두 간단한 이름이며 패키지 이름이 인터넷 도메인 이름을 사용하는 것이 더 좋은 방법입니다. 우리가 일하는 회사가 Magic.lnc이고 회사의 도메인 이름이 Magic C.com이면 속성 패키지의 선언은 다음과 같습니다.
패키지 com.magic.attr;
여기서 도메인 이름 구성 요소는 기존 도메인 이름의 역 순서로 배열됩니다.
우리 가이 관용구를 채택하면, 우리가 사용하는 패키지 이름은 조직 내의 갈등을 제외하고 다른 사람과 충돌하지 않습니다. 우리 조직 (아마도 대규모 기업) 내에 충돌이 실제로 있다면, 우리는보다 구체적인 도메인 이름을 사용하여 더 많은 자격을 갖추 수 있습니다. 많은 대기업에게는 동부 및 유럽과 같은 내부 하위 도메인이 있으며, 이는 패키지 이름을 추가로 예약하는 데 사용할 수 있습니다.
Package Corn.magic.japan.attr;
이 솔루션을 사용하면 패키지 이름을 매우 길게 만들 수 있지만 비교적 안전합니다. 이 기술을 사용하는 프로그래머는 동일한 패키지 이름을 선택하지 않으며이 기술을 사용하지 않는 프로그래머는 우리가 사용하는 이름을 선택하지 않습니다.
패키지 콘텐츠
패키지의 내용은 기능적으로 관련된 클래스와 인터페이스 만 포함하도록 신중하게 설계되어야합니다. 패키지의 클래스는 패키지의 다른 클래스의 비 개인적인 구성원에게 자유롭게 액세스 할 수 있으며 일부 클래스는 다른 클래스의 내부 세부 사항에 액세스하기에 충분한 권한이있을 수 있습니다. 이러한 수업이 수업 회원을 오해하는 것을 피하려면 클래스 멤버를 보호해야합니다. 비공개로 선언되지 않은 모든 회원은 동일한 패키지의 다른 모든 유형에서 액세스 할 수 있으므로 관련없는 클래스는 예상보다 더 조정될 가능성이 높습니다.
패키지는 또한 유용한 인터페이스 및 클래스를 찾는 프로그래머를위한 논리적 그룹화를 제공합니다. 관련이없는 클래스로 구성된 패키지는 프로그래머가 어떤 인터페이스와 클래스가 유용한 지 알기가 어렵고, 논리적 인 클래스 그룹화는 프로그래머가 논리적 그룹화를 통해 더 쉽게 필요한 것을 찾을 수 있기 때문에 프로그래머 재사용 코드를 도울 수 있습니다. 패키지에 관련적이고 밀접하게 연결된 유형 세트 만 포함 된 경우 유형에 이름 충돌을 피하기 위해 더 직관적 인 이름을 제공 할 수 있습니다.
패키지는 중첩 될 수 있습니다. 예를 들어, Java.lang은 패키지 Lang이 더 큰 패키지 Java에 중첩되어있는 중첩 패키지이며, Java 패키지에는 다른 패키지도 포함되어 있습니다. 중첩은 관련 패키지가 계층 구조를 가진 명명 시스템을 형성합니다.
예를 들어, 신경망 및 유전자 알고리즘과 같은 적응 형 시스템을위한 패키지 세트를 만들려면 중첩 된 패키지를 만들기 위해 도트 구분 이름이있는 패키지를 지명 할 수 있습니다.
패키지 적응 형. 신경 그물;
위의 선언문을 포함하는 소스 파일은 Adaptive.neuralnet 패키지에 있으며 Adaptive.neuralnet 패키지 자체는 적응 형 패키지의 하위 포장입니다. 적응 형 패키지에는 일반화 문제 설명 클래스 또는 벤치 마크 클래스와 같은 일반적인 적응 알고리즘과 관련된 일부 클래스가 포함될 수 있습니다. 계층 구조에서 더 깊은 위치에있는 패키지 (예 : Adaptive.neu-Ralnet 또는 Adaptive.genetic)에는 특정 유형의 적응 형 알고리즘과 관련된 클래스가 포함되어 있습니다.
패키지의 중첩은 관련 패키지를 구성하는 도구 일뿐 아니라 패키지간에 특별한 액세스 권한을 제공하지 않습니다.
Adaptive.genetic 패키지의 클래스 코드는 패키지 액세스 권한이있는 Adaptive 또는 Adaptive.neuralnet 패키지의 구성원에게 액세스 할 수 없으며 패키지 범위는 특정 패키지에만 적용됩니다. 패키지의 중첩은 관련 패키지를 그룹화하고 프로그래머가 원하는 클래스를 논리적 수준에서 더 편리하게 찾는 데 도움이 될 수 있지만 그 외에도 다른 이점을 가져 오지 않습니다.
패키지 노트
패키지에는 주석이있을 수도 있습니다. 그러나 문제는 패키지가 소스 코드 엔티티가없는 조직 구조이며 실제 정의가 없기 때문에 클래스 나 메소드와 같이 주석을 달 수 없으므로 패키지 주석은 소스 파일에 패키지의 선언문에 주석을 달 때만 달성 할 수 있다는 것입니다. 그러나 각 패키지에는 하나의 패키지 선언 만있을 수 있으며, 이에 대한 주석이있는 주석이있을 수 있습니다.
그렇다면 패키지에 어떻게 주석을 달 수 있습니까? 실제로 Java는 프로그래머가 "단일 주석이 달린 패키지 문"규칙을 다루기 위해 어떤 방법을 사용하도록 강요하지 않습니다. 권장되는 방법은 패키지 디렉토리에서 package-i nfo.java라는 파일을 만드는 것입니다. 여기서 패키지 문과 패키지의 주석 만 다른 것을 배치하지 않고 저장됩니다. 예를 들어, att
@packagespec (이름 2 "attr project", version = "1.0"@developmentite ( "attr.project.org") @developmentModel ( "Open-Source") 패키지 attr;
PackagesPec, Developments 및 Development OpmentModel은 주석 유형을 수정하는 데 사용됩니다. 물론, 그들은 런타임 절약 전략을 가지고 있습니다. Package-Info.java 파일은 패키지의 다른 소스 파일과 함께 컴파일해야합니다.
모든 패키지 관련 정보를 Package-Info.java 파일에 배치하는 것이 좋습니다. 이렇게하면 파일의 시작 부분에 문서 주석을 배치하여 이러한 문서가 패키지 문서로 주석을 달 수 있습니다.
패키지 액세스
패키지에서 최상위 클래스 및 최상위 인터페이스의 접근성을 선언 할 때는 패키지 액세스 (패키지)와 공개 액세스 (공개)의 두 가지 옵션이 있습니다. 공개적으로 수정 된 클래스 또는 인터페이스는 패키지 외 코드로 액세스 할 수 있으며, 공개로 장식되지 않은 유형에는 패키지 범위가 있습니다. 동일한 패키지의 다른 코드로 액세스 할 수 있습니다. 그러나 그들은 포장되지 않은 코드, 서브 포장 코드에도 숨겨져 있습니다. 유형을 선언 할 때는 다른 프로그래머가 공개적으로 사용해야하는 유형을 선언하고 패키지의 구현 세부 정보에 속하는 유형을 숨기려면됩니다. 이 기술은 우리에게 큰 유연성을 제공하며 프로그래머는 액세스 할 수없는 이러한 유형의 구현 세부 사항에 의존하지 않기 때문에 구현 세부 정보를 변경하려면 자유롭게 변경할 수 있습니다.
공개, 보호 또는 개인으로 선언되지 않은 클래스 멤버는 패키지 내부의 모든 코드에서 직접 액세스 할 수 있지만 패키지 외부에서 숨겨져 있습니다. 다시 말해, 기본 액세스 수정자는 인터페이스의 멤버를 제외하고 "패키지"이며 기본 액세스 수정자는 "공개"입니다.
패키지 내에서 비공개로 선언되지 않은 필드 또는 메소드는 해당 패키지의 다른 모든 코드에서 액세스 할 수 있으므로 동일한 패키지의 클래스는 "친숙한"또는 "신뢰할 수있는"것으로 간주됩니다. 이를 통해 사전 정의 된 코드와 자리 표시 자 코드를 결합한 애플리케이션 프레임 워크를 정의 할 수 있습니다. 여기서 자리 표시 자 코드는 프레임 워크 클래스의 서브 클래스로 재정의됩니다. 사전 정의 된 코드는 패키지 액세스 수정자를 사용하여 패키지 내의 다른 협업 코드가 직접 액세스 할 수 있지만 패키지 외 사용자의 경우 이러한 코드는 액세스 할 수 없습니다. 그러나이 코드가 위치한 패키지의 서브 포장은 신뢰할 수 없으며 그 반대도 마찬가지입니다. 예를 들어, 패키지 DIT의 패키지 액세스 수정 자로 수정 된 코드는 하위 패키지 Dit.dat의 코드에서 액세스 할 수 없으며 그 반대도 마찬가지입니다.
따라서 각 유형은 세 가지 계약을 정의합니다.
.publi. 계약 : 유형의 주요 기능을 정의합니다.
. 보호 계약 : 전문화 목적으로 서브 클래스에 사용할 수있는 기능을 정의합니다.
.Package Contract : 패키지의 다른 코드에서 얻을 수있는 기능을 정의하여 패키지의 유형 간의 협업을 달성합니다. 이러한 모든 계약은 신중한 고려와 설계가 필요합니다.
접근성 및 표지 방법
슈퍼 클래스에서 액세스 할 수있는 메소드 만 서브 클래스로 덮어 쓸 수 있습니다. 슈퍼 클래스의 메소드에 액세스 할 수없는 경우 서브 클래스의 메소드가 메소드와 동일한 이름을 갖는 경우에도 서브 클래스에서 메소드를 재정의 할 수 없습니다. 런타임에 메소드가 호출되면 시스템은 접근성을 고려하여 실행중인 구현을 결정합니다.
특별히 구성된 예제는 더 명확하게 설명됩니다. P1 패키지에서 추상 기반 클래스를 선언한다고 가정 해 봅시다.
패키지 P1; {ab ab abab public acc } protected void pro () {print ( "stractbase.pro ()"); } public void pub () {print ( "stractbase.pub ()");} public final void show () pri (); pac (); 찬성(); 선술집(); }}이 클래스에서는 각각 다른 액세스 수정자가있는 4 가지 방법을 정의하고 방법의 본문은 자체 만 식별합니다. 이 메소드 쇼는 현재 객체 에서이 4 가지 메소드를 차례로 호출합니다. 이 메소드를 다른 서브 클래스 객체에 적용 할 때 이러한 방법의 구현이 호출되는 것을 설명 할 수 있습니다.
이제 우리는 AbstractBase 클래스를 확장하는 클래스 Concretel을 정의하지만 P2 패키지에 있습니다.
패키지 P2; P1.ABSTRANTBASE Public Class Concretel은 AbstractBase를 확장합니다 {public void pri () {print ( "Concretel.pri ()";} public void pac () {print ( "concretel.pac ()"); }슈퍼 클래스의 4 가지 방법은이 클래스에서 다시 고정되고 구현이 변경되어 Con-Cretel 클래스에 속한다고보고합니다. 동시에 다른 코드에 액세스 할 수 있도록 액세스 권한이 공개되었습니다. 다음 코드를 실행하십시오
New Concretel (). show () :
다음 출력이 생성됩니다.
AbstractBase.pri () AbstractBase.pac () Concretel.pro () Concretel.pub ()
개인 메소드 PRI는 서브 클래스 (또는 다른 클래스)로 액세스 할 수 없으므로 쇼 메소드는 항상 AbstractBase 클래스에서 PRI 메소드의 구현을 호출합니다. AbstractBase 클래스에 패키지 액세스 권한이있는 PAC 메소드는 Concretel에서 액세스 할 수 없으므로 Concretel 클래스에서 PAC 메소드의 구현은 AbstractBase 클래스에서 정의를 무시할 수 없으므로 Show 메소드는 AbstractBase.pac 메서드를 호출합니다. Pro Method와 Pub 방법은 Concretel 클래스에서 모두 액세스 할 수 있으며 덮어 쓰기도 할 수 있으므로 Show Method는 Concretel 클래스 에서이 두 가지 메소드의 구현을 호출합니다.
우리의 발 의미 클래스 Concrete2를 따라 클래스 Concretel을 확장 한 다음 AbstractBase 클래스와 동일한 패키지 P1에 넣습니다. '
패키지 P1; Procletel {public void pri () {print ( "concrete2.pri ()";} public void pac () {print ( "concrete2.pac ()")} public void pro () {print ( "concrete2.pro ()"); public void pub () {print ( "print (") {print ( "print (") {print ( ")Concretel의 방법에는 공공 접근 권한이 있기 때문에 Concrete2에서 액세스 할 수 있으며 Concrete2의 각 방법은 해당 방법을 개별적으로 다룹니다. 또한 Concrete2 및 AbstractBase는 동일한 패키지에 있으므로 AbstractBase.pac 방법은 Concrete2에서도 액세스 할 수 있으며 Method Concrete2.pac을 재정의 할 수 있습니다. Concrete2 객체에서 쇼 메소드를 호출하면 인쇄 결과는 다음과 같습니다.
AbstractBase.pri () Concrete2.pac () Concrete2.pro () Concrete2.pub ()
마지막으로, 클래스 콘크리트 3을 정의하여 클래스 Concrete2를 확장하고 패키지 p3에 넣습니다.
패키지 P3 가져 오기 P1.concrete2; Public Class Concrete3은 Concrete2 {public void pri () {print ( "concrete3.pri ()";} public void pac q {print ( "concrete3.pac ()");} public void pro () {print ( "contrete3.pro ()");} public void pub () {print ( "concrete3.pub ());Concrete3 객체에서 쇼 메소드를 호출하면 인쇄 결과는 다음과 같습니다.
AbstractBase.pri () Concrete3.pac () Concrete3.pro () Concrete3.pub ()
여기서 Method Concrete3.pac은 접근 가능한 AbstractBase.pac 메서드를 무시하는 것처럼 보이지만 실제로 Method Concrete3.Pac은 Method Concrete2.pac을 재정의하고 Method Concrete2.pac는 Method AbstractBase.pac를 재정의하므로 Method AbstractBase.pac을 간접적으로 무시합니다. Class Concrete2의 PAC 방법을 공개 액세스 권한을 갖는 것으로 재고함으로써 모든 서브 클래스로 액세스하고 덮어 쓸 수 있습니다.
패키지 개체 및 사양
패키지는 일반적으로 일부 사양을 구현하며 일반적으로 조직에서 나옵니다. 패키지 개체는 다른 반사 유형과 다르며 패키지를 만들거나 작동하는 데 사용할 수 없지만 패키지 (제목, 공급 업체 및 버전 번호)에서 구현 된 사양에 대한 정보와 패키지 자체의 구현 (제목, 공급 업체 및 패키지 번호)에 대한 정보를 제공하는 정보를 제공하기위한 지식 기반으로만 사용될 수 있습니다. 패키지는 일반적으로 개별 조직에서 나오지만, 통계 분석 라이브러리와 같은 사양은 다른 조직에서 정의 할 수 있습니다. 패키지를 사용하는 프로그램은 패키지에서 구현 한 사양의 버전을 알아야하므로 특정 버전에서만 정의 된 기능을 사용할 수 있습니다. 마찬가지로, 이러한 프로그램은 주로 다른 버전의 가능한 결함을 처리하기 위해 어떤 구현 버전이 제공되는지 알아야 할 수도 있습니다. 패키지 클래스의 주요 방법 중 일부는이 정보에 액세스 할 수 있습니다.
public stri ng getName () : 패키지 이름을 반환합니다.
.public String getSpecificationTitle P : 패키지에서 구현 된 사양의 제목을 반환합니다. 제목을 알 수없는 경우 NULL을 반환하십시오.
.public string getSpecificationVersion () : 패키지에서 구현 된 사양의 버전 정보를 설명하는 문자열을 반환합니다. 버전 정보를 알 수없는 경우 NULL을 반환하십시오.
.public String getSpecificationvendor Q : 패키지에서 구현 한 사양을 소유하고 유지하는 공급 업체의 이름을 반환합니다. 공급 업체가 알 수없는 경우 NULL을 반환하십시오.
.public String getImplerentationTitle () : 패키지에서 제공 한 구현 제목을 반환합니다. 제목을 알 수없는 경우 NULL, ・ 공개 문자열 getImplementationVersion () : 패키지에서 제공 한 구현의 버전 정보를 설명하는 문자열을 반환합니다. 버전 정보를 알 수 없으면 NULL을 반환합니다.
public public String getImplementationVendor () : 구현을 제공하는 조직 이름 (공급 업체)을 반환합니다. 조직이 알려지지 않은 경우 NULL을 반환하십시오.
예를 들어, 시스템의 Java.Lang 패키지에서 이러한 정보를 추출하면 다음과 같은 결과를 얻을 수 있습니다.
사양 제목 : Java 플랫폼 API 사양 사양 버전 : 1.4 사양 공급 업체 : Sun Microsystems, Inc. 구현 제목 : Java 런타임 환경 구현 버전 : 1.5.0_02 구현 공급 업체 : Sun Microsystems, Inc.
표준 버전 번호는``2.0 ''또는 '11 .0.12 '와 같은주기 구분자로 분리 된 비 음성 숫자로 구성됩니다. 이 패턴을 사용하면 iscompatiblewith 메소드를 호출 하여이 패턴을 따르는 버전 번호를 패키지의 버전 번호와 비교할 수 있습니다. 패키지의 버전 번호가 후임자의 버전 번호보다 크거나 같으면 메소드가 true를 반환합니다. 이 비교는 한 번에 기간 분리 된 숫자 만 비교합니다. 이 숫자 중 하나가 전달 된 버전 번호의 해당 위치보다 작 으면 두 버전은 호환되지 않습니다. 버전 번호 중 하나가 다른 버전보다 길면 짧은 버전 숫자의 누락 된 부분은 0으로 간주됩니다. 예를 들어, 패키지의 표준 버전 번호가 "1.4"이고 "1.2", "1.3.1 '. 또는".1.81.와 비교하면 true가 반환됩니다. 그러나 "1.4.2 '. 또는".5 "와 비교하면 거짓이 반환됩니다.이 결론은 사양 버전과 호환 가능하다고 가정하기 때문에이 결론이 그려집니다.
구현을 제공하는 다른 조직이 구현 버전을 다르게 정의하기 때문에 구현 버전 번호에는 지정된 형식이 없습니다. 구현 버전간에 이루어질 수있는 유일한 비교는 버전이 동일한 지, 후진 호환성의 가정이 없는지 테스트하는 것입니다.
패키지를 봉인 할 수 있으므로 클래스를 더 이상 패키지에 추가 할 수 없습니다. 언급되지 않은 패키지에는 클래스 검색 경로의 여러 다른 위치의 클래스가 포함될 수있는 반면, 봉인 된 패키지의 내용은 특정 아카이브 또는 URL로 지정된 위치에 있어야합니다. 패키지가 봉인되었는지 확인하는 두 가지 방법이 있습니다.
.public boolean issealed p : 패키지가 봉인 된 경우 Trueo를 반환합니다.
.public boolean issealed (URL URL) : 주어진 URL에 대해 패키지가 밀봉 된 경우, 즉 패키지의 클래스를 주어진 URL에서로드 할 수 있습니다. 패키지의 클래스를 주어진 URL에서로드 할 수 없거나 패키지가 밀봉되지 않은 경우 False가 반환되고 패키지의 사양 및 구현 정보는 일반적으로 패키지에 저장된 매니페스트 파일의 일부로 제공됩니다 (예 : 섹션 25.9.2)에 설명 된대로 Java Archive (JAR)의 일부 매니페스트 파일의 일부로 제공됩니다. 패키지의 클래스가로드되면이 정보는 사람이 읽습니다. 클래스 로더는로드하려는 클래스의 패키지 개체를 동적으로 정의 할 수 있습니다.
. 보호 된 패키지 DENEPACKAGE (문자열 이름, 문자열 Spectitle, String Specversion, String Specvendor, String Imptitle, String Implversion, String Implvendor, URL Sealbase) :이 메소드는 주어진 패키지 이름 및 사양 및 해당 견적으로 설정된 구현 값을 갖는 패키지 개체를 반환합니다. 매개 변수 SEALBASE가 NULL 인 경우 패키지가 밀봉되지 않으면 패키지가이 URL에 대해 패키지가 밀봉되어 있습니다. 클래스의 패키지 개체는 클래스가 정의되기 전에 정의되어야하며 패키지 이름은 클래스 로더에서 고유해야합니다. 패키지 이름이 기존 이름으로 반복되면 작업 11ega1argumentexception이 발생합니다.
주어진 클래스의 클래스 객체의 getPackage 메소드를 호출 하여이 클래스의 패키지 개체를 얻을 수 있습니다. 주어진 패키지 이름으로 static package.getPackage를 호출하여 패키지 개체를 가져 오거나 정적 패키지를 호출 할 수 있습니다. 두 가지 방법 모두 코드를 호출하는 클래스 로더와 관련이 있습니다.이 코드는 클래스 로더의 get-package 또는 getpackages 메소드를 호출하기 때문입니다. 이 클래스 로더의 방법은 특정 클래스 로더 및 모든 상위 클래스 로더를 검색하며 현재 클래스 로더에 대한 설정이 없으면 현재 시스템 클래스 로더가 사용됩니다. 패키지를 알 수없는 경우 현재 패키지의 유형이로드되지 않았기 때문에 클래스 로더 메소드는 NULL을 반환합니다.