패키지 (package)
파일 시스템의 폴더처럼 여러 클래스들의 이름을 디렉터리로 계층 구조화해 체계적으로 관리하는 것이다.
위 그림처럼 CustomerManager라는 클래스가 있다면 그 앞에 오는 com.bit.videoshop.customer가 패키지 이름이 되는것다.
도메인은 일반적으로 com.sun 이나 com.bit 처럼 회사를 나타내는 단어를 사용하고
그 이후에 API나 프로젝트 구조가 도트(.)를 기준으로 차례대로 위에서 아래로 되는 것이다.
패키지의 목적
마치 디렉터리처럼 계층 구조화가 돼있어서 코드 작성시 도트(.)를 통해 하위 패키지 또는 클래스까지 접근이 가능하고 파일 관리가 용이하다는 장점도 있겠지만, 결국 FQCN으로 같은 클래스 이름이라도 패키지로 이를 구분짓기 위해 사용한다.
이 구분짓는 것을 클래스의 고유성을 보장한다고도 말한다.
💡 FQCN (Fully Qualified Class Name)
모든 클래스에는 정의된 클래스 이름과 패키지 이름이 있다.
이 둘을 합쳐야 완전하게 한 클래스를 표현할 수 있으며 이를 FQCN(Fully Qualified Class Name)이라 한다.
String 클래스의 패키지는 "java.lang"이며 FQCN은 ""이 된다.
패키지의 특징
- 클래스의 전체 이름은 "패키지 + 클래스명"이다.
- 패키지가 상, 하위로 구분되어 있다면 도트(.)를 사용해서 표현한다. (상위패키지.하위패키지.클래스)
- String 클래스가 java.lang 패키지에 속해있다면?
- String 클래스가 java.lang 패키지에 속해있다면?
- 모든 클래스는 반드시 하나의 패키지에 속해야 한다.
따라서 자바에서는 패키지를 명시적으로 선언하지 않으면
해당 클래스를 기본적으로 제공하는 이름없는 패키지(Unnamed Package)로 포함한다.
💡 이름 없는 패키지(Unnamed Package)
자바의 모든 클래스는 반드시 하나 이상의 패키지에 포함되어야 한다.
하지만 자바 컴파일러는 소스 파일에 어떠한 패키지의 선언도 포함되지 않으면,
기본적으로 이 이름 없는 패키지(Unnamed Package)라는 것에 포함해 컴파일한다.
따라서 패키지를 명시하지 않은 모든 클래스와 인터페이스는 모두 같은 패키지에 포함되게 된다.
네임스페이스(Namespace)
네임스페이스란 파일을 구분할 수 있게 해주는 공간을 의미한다.
ABC\Water.java 와 DEF\Water.java 가 있다면 컴퓨터는 이를 디렉터리 이름으로 구별한다.
여기서 ABC와 DEF가 네임스페이스 역할을 한다.
위 예시에서는 디렉터리가 공간이고, 자바에서는 패키지(Package)가 바로 그 공간이다.
이러한 특성으로 패키지는 이름 중복으로 인한 문제를 방지할 수 있다.
그래서 하나의 패키지 안에는 똑같은 이름의 클래스를 만들 수 없다.
💡 JAVA 패키지에는 없지만 C# 네임스페이스에는 있는 기능 - 별칭(alias)
C# 에서는 이름 중복으로 인한 문제 말고도 공간에 대한 별칭(alias)을 만들 수도 있다.
using generics = System.Collections.Generic;
namespace AliasExample
{
class TestClass
{
static void Main()
{
generics::Dictionary<string, int> dict = new generics::Dictionary<string, int>()
{
["A"] = 1,
["B"] = 2,
["C"] = 3
};
foreach (string name in dict.Keys)
{
System.Console.WriteLine($"{name} {dict[name]}");
}
// Output:
// A 1
// B 2
// C 3
}
}
}
위 코드는 System.Collections.Generics 네임스페이스를 generics라는 별칭(alias)으로 설정한 후
Key-Value 형식의 C# 자료구조인 Dictionary에 접근하기 위해 별칭 generics와 별칭 한정자(::)를 사용한 예시이다.
별칭을 사용했으므로 모든 네임스페이스 경로를 입력하지 않아도 Dictionary 클래스에 접근이 가능하다.
패키지는 언제 생성되는가?
패키지는 클래스를 컴파일하는 과정에서 생성되는 폴더이다.
컴파일러는 클래스에 포함되어 있는 패키지 선언을 보고 파일 시스템의 폴더로 생성한다.
패키지 선언 규칙
패키지 이름은 개발자 임의로 정의해도 되지만 지켜야 할 규칙이 있다.
- 숫자로 시작해서 안된다.
- _ 이나 $ 를 제외한 특수문자를 사용해서는 안된다.
- java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 선언해서는 안된다.
- 모두 소문자로 작성하는 것이 관례이다.
패키지가 회사마다 서로 중복되지 않도록 회사의 도메인 이름으로 패키지를 만든다.
도메인 이름으로 패키지 이름을 만들 경우, 도메인 이름 역순으로 패키지 이름을 지어준다.
포괄적인 이름이 패키지 명의 최상위가 되도록 하기 위함이다.
마지막에는 프로젝트 이름을 붙여주는 것이 관례이다.
빌트-인 패키지(Built-in Package)
자바는 개발자들이 사용할 수 있도록 여러 많은 패키지 및 클래스를 제공한다.
가장 자주 쓰이는 패키지로는 java.lang과 java.util이 있다.
빌트-인 패키지는 자바에서 import 명령어로 불러오지 않아도 미리 포함이 돼있어 개발자가 바로 사용할 수 있다.
대표적 빌트-인 패키지 종류
- java.lang : JAVA 프로그래밍에 가장 기본적인 클래스들이 모여있는 패키지
- 자동으로 import 되기 때문에 개발자는 해당 패키지의 클래스를 바로 사용할 수 있다.
대표적으로 System.out.println() 의 System 클래스는 java.lang 패키지이다.
- 자동으로 import 되기 때문에 개발자는 해당 패키지의 클래스를 바로 사용할 수 있다.
- java.io : 입출력 기능을 지원하는 클래스를 포함하는 패키지
- java.util : 자료구조 구현을 위한 유틸리티 클래스를 포함하는 패키지
- java.applet : Applets을 생성하기 위한 클래스를 포함하는 패키지
- java.awt : GUI 컴포넌트를 구현하기 위한 클래스를 포함하는 패키지
- java.net : 네트워킹 기능을 지원하기 위한 클래스를 포함하는 패키지
import 키워드
같은 패키지에 속하는 클래스들은 접근지시자가 package-private이냐 private이냐를 따진 후 사용할 수 있지만,
다른 패키지에 속하는 클래스를 사용하려면 2가지 방법 중 하나를 선택해야 한다.
- 패키지와 클래스를 모두 기술하는 방법
ex) "com.beststar" 패키지에 소속된 Star 클래스를 이용해서 필드 선언 후 객체 생성
public class Universe {
com.beststar.Star star = new com.beststar.Star(); // 객체생성
}
패키지 이름이 짧을 경우 불편함이 없지만,
길거나 이렇게 사용해야 할 클래스가 많다면 전체적으로 코드의 가독성이 떨어진다.
- import 문 사용
사용하고자 하는 패키지를 import 문으로 선언하고, 클래스를 사용할 때는 패키지를 생략한다.
import com.beststar.Star; // 혹은, import com.beststar.*;
public class Universe {
Star tire = new Star();
}
import 문 작성 위치는 패키지 선언과 클래스 선언 사이이다.
패키지에 포함된 다수 클래스를 사용해야 한다면, 모든 클래스를 의미하는 [*] 기호를 사용한다.
import 문의 개수 제한은 없다.
⚠ 주의사항
import문으로 지정된 패키지의 하위 패키지는 import 대상이 아니다.
만약 하위 패키지의 클래스를 이용하고 싶다면 import 문을 하나 더 작성해야 한다.
// com.mycompany 패키지의 클래스와 com.mycompany.project 패키지의 클래스를 둘다 사용시
// 각각 import문을 사용해야 한다.
import com.mycompany.*;
import com.mycompany.project.*;
static import
static import는 메서드나 변수를 패키지, 클래스명 없이 접근 가능하게 해준다.
static import를 사용하면 매우 편리해진다.
그 예시로 자바 테스트 프레임워크인 JUnit를 보면 static import의 다양한 예를 살펴볼 수 있다.
// static import 사용 전
@Test
public void nonStaticImport()
{
org.assertj.core.api.AssertionsForClassTypes.assertThat(1, CoreMatchers.is(1));
}
// static import 사용 후
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@Test
public void staticImport()
{
assertThat(1, is(1));
}
위 테스트는 static import를 적용하지 않은 경우이고, 아래는 static import를 적용한 예시이다.
static import를 사용하게 되면 테스트 코드를 읽을 때, That ~ is ~ 로만 읽어서 의도를 쉽게 파악할 수 있다.
출처
패키지
kils-log-of-develop.tistory.com/430
www.notion.so/ed8e346f88f54849a06ff968b1877ca5
C# 네임스페이스 - 별칭
docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/namespaces/using-namespaces
C# 네임스페이스 와의 비교
pediaa.com/what-is-the-difference-between-namespace-and-package/
'JAVA' 카테고리의 다른 글
자바 표준 - JLS(Java Language Specification), JSR(Java Specification Request), JEP(Java Enhancement Proposal) (0) | 2021.04.16 |
---|---|
예외(Exception) - 커스텀 예외(Custom Exception) (0) | 2021.04.14 |
접근 지시자(Access Identifier) (0) | 2021.04.13 |
클래스패스(Classpath) (0) | 2021.04.13 |
예외(Excepton) - 정의, 목적, 구조, 사용 방법 (0) | 2021.01.16 |