제이제이
article thumbnail

 

 패키지(Package)


🤔 패키지란?

  • 클래스를 묶는 수단이자 "다른 클래스" 또는 "다른 클래스들의 묶음"과 구별하기 위한 수단입니다.

 

  • 패키지를 이해하기 위해 이름이 같은 두 클래스를 살펴봅시다.

 

회사의 도메인 주소가 wxfx.com인 회사에서 개발한 클래스

public class Circle{ //원의 넓이 관련 클래스의 정의
		doulbe rad;
		final double PI;

	
		//생성자
		pulbic Circle(double r) {
				rad = r;
				PI = 3.14;

	     }
		public double getArea(){
				return (rad * rade) *PI; //원의 넓이 반환
	}
}

 

인터넷 도메인 주소가 fxmx,com인 회사에서 개발한 클래스

public class Circle{ //원의 둘레 관련 클래스
			double rad;
			final double PI;

			//생성자
			public Circle(double r) {
				rad = r;
				PI = 3.14;
	     	}
			public double getPerimeter() {
				return (rad *2) *PI; //원의 둘레를 반환
		}
}

 

👩🏻‍🏫 설명

  • 위의 두 클래스의 정의는 개별적으로 문제가 없습니다.
  • 그러나 이를 동시에 사용해야 하는 상황에서는 클래스 Circle의 이름이 중복이 문제가 된다.

-> 같은 패키지에 똑같은 이름의 클래스는 충돌 상황이 발생합니다.

-> 그러나 패키지를 이용하여, 클래스를 분리한다면 두 클래스의 이름 충돌 문제에서 벗어날 수 있습니다.

 

  • 두 Circle 클래스를 자세하게 살펴봅시다.
  • 두 클래스의 Cicle의 정의를 살펴보면 다음과 같이 public 선언으로 되어 있음을 알 수 있습니다.
public class Circle{....}

 

  • 다음의 사실을 알 수 있습니다.

1. 하나의 소스 파일에는 public으로 선언된 클래스의 정의를 하나만 둘 수 있다.

2. 소스파일의 이름은 public으로 선언된 클래스의 이름과 동일하다.

-> 즉, 두 Circle 클래스 모두 public으로 선언되어 있기 때문에, 소스 파일의 이름도 Circle.java로 동일합니다.

-> 따라서 이 둘을 정의할 때에는 서로 각각 다른 위치에 저장해야 합니다.

 

패키지 선언을 통한 분리


1. 이름 충돌을 해결합니다.

  • 패키지 선언은 클래스의 접근 방법을 구분할 뿐만아니라 클래스 파일이 공간적으로도 구분되게 한다.

 

-> 또한 패키지 선언은 다음과 같은 두 가지 특성을 만들어 낸다.

 

1. 클래스 접근 방법의 구분

  • 서로 다른 패키지의 두 클래스는 인스턴스 생성 시 사용하는 이름이 다릅니다.

 

2. 클래스의 공간적인 부분

  • 서로 다른 패키지의 두 클래스 파일은 저장되는 위치가 다릅니다.

 

  • 패키지 이름을 지을 때는 다음과 같은 규칙들을 따릅니다.

 

패키지 명명 규칙


1. 클래스 이름과 구별되도록 패키지의 이름은 모두 소문자로 구성한다.

2. 인터넷 도메인 이름의 역순으로 패키지 이름을 구성한다.

3. 패키지 이름의 끝에는 클래스르 정의한 주체 또는 팀을 구분하는 이름을 추가한다.

 

ex) 인터넷 도메인이 wxfx.com인 회사의 smart 팀에서 개발한 클래스를 묶을 패키지 이름을 위의 관례에서 따라 만들면 다음과 같습니다.

→ com.wxfx.smart

ex) 인터넷 도메인이 fxmx.com인 회사의 simple팀에서 개발한 클래스를 묶을 패키지 이름은 다음과 같이 만듭니다.

→ com.fxmx.simple

 

  • 이렇게 패키지의 이름이 결정되고 각 클래스를 패키지로 묶으면 클래스의 인스턴스 생성 방법은 다음과 같이 달라지게 됩니다.

 

패키지 com.wxfx.smart의 Circle 인스턴스 생성 문장

 

패키지 com.fxmx.simple의 Circle 인스턴스 생성 문장

 

  • 이렇게 인스턴스 생성 및 참조변수 선언 시 클래스의 이름 앞에 패키지 이름이 따라붙는 구조가 됩니다.

-> 그리고 다음과 같이 클래스 파일이 저장되는 위치도 다음과 같이 달라지게 됩니다.

 

패키지 com.wxfx.smart의 Circle.class의 저장 위치

→ ….\com\wxfx\smart

 

패키지 com.fxmx.simple의 Circle 인스턴스 생성 문장

→…\com\fxmx\simple

 

패키지의 선언 및 컴파일 방법


  • 클래스를 패키지로 묶을 때에는 해당 클래스를 담고 있는 소스파일의 상단에 패키지 선언을 해야 합니다.
  • ex) 패키지 com.wxfx.smart로 묶고 싶다면 다음의 선언을 소스파일 상단에 삽입하면 됩니다.
package com.wxfx.smart
package com.wxfx.smart; //패키지 선언
public class Circle{ //원의 넓이 관련 클래스의 정의
		doulbe rad;
		final double PI;

	
		//생성자
		pulbic Circle(double r) {
				rad = r;
				PI = 3.14;

	}
		public double getArea(){
				return (rad * rade) *PI; //원의 넓이 반환
	}
}

package com.fxmx.simple; //패키지 선언

public class Circle{ //원의 둘레 관련 클래스
			double rad;
			final double PI;

			//생성자
			public Circle(double r) {
				rad = r;
				PI = 3.14;
		}
			public double getPerimeter() {
				return (rad *2) *PI; //원의 둘레를 반환
		}
}

 

패키지로 묶은 클래스의 접근

  • 다음의 코드를 살펴봅시다.

 

💻 예시 코드

public class CircleUsing {
    public static void main(String[]args){
        part8.com.wxfx.smart.Circle c1 = new part8.com.wxfx.smart.Circle(3.5);
        System.out.println("반지름 3.5 원 넓이:" + c1.getArea());

        part8.com.fxmx.simple.Circle c2 = new part8.com.fxmx.simple.Circle(3.5);
        System.out.println("반지름 3.5 원 둘레:" + c2.getPerimeter());
    }
}

 

  • 자바 컴파일러는 다음 문장을 어떻게 해석하고 해당 클래스 파일을 찾은 것일까요?
    part8.com.wxfx.smart.Circle c1 = new part8.com.wxfx.smart.Circle(3.5);

 

1. 자바 컴파일러는 먼저 패키지를 찾습니다.

  • 즉, 위의 문장을 접했을 때 com.wxfx.smart 패키지를 찾습니다.
  • 이때 클래스 파일을 찾아와 마찬가지로 '클래스 패스'를 참조하여 패키지를 찾습니다.
  • 클래스 패스가 별도로 지정되어 있지 않다면 다음과 같이 현재 디렉터리를 기준으로 패키지를 찾습니다.
-> 현재 디렉터리를 기준으로 com\wxfx\smart 디렉터리를 찾습니다.

 

  • 패키지의 이름과 디렉터리 경로가 일치하기 때문에 같은 방식으로 패키지를 찾게 됩니다.
  • 그리고 패키지를 찾았으면 이제 그 안에서 Circle.class를 찾아서 인스턴스를 생성합니다.

 

  • 마찬가지로 다음 문장을 접하면 클래스 패스를 참조하여 com\fxmx\simple 디렉터리를 찾습니다.

-> 그리고 그 안에서 Circle.class를 찾아서 인스턴스를 생성합니다.

com.fxmx.simple,.Circle c2 = new com.fxmx.simple.Circle(3.5);

 

 

import 선언

  • 앞서 보인 상황 즉 동일한 이름의 두 클래스를 생성하는 인스턴스를 생성해야 하는 상황이라면 패키지의 이름은 생략이 불가능하다.
    하지만 필요로 하는 클래스가 다음 하나가 아니라면 패키지의 이름을 늘 붙이고 다니는 것은 번거롭습니다.
com.wxfx.smart.Circle

 

 

  • 따라서 이러한 상황에서 , 득 동일한 이름의 클래스가 사용되지 않는 상황에서의 패키지 이름의 생략법을 자바는 제공하고 있습니다.

 

💻 예시 코드

import part8.com.wxfx.smart.Circle;

public class ImportCircle {
    public static void main(String[]args){
        Circle c1 = new Circle(3.5);
        System.out.println("반지름 3.5 원 넓이 : " + c1.getArea());

        Circle c2 = new Circle(5.5);
        System.out.println("반지름 5.5 원 넓이 : " + c2.getArea() );
    }
}

 

👩🏻‍🏫 설명

  • 위의 예의 일부인 다음 문장을 살펴봅시다.
import com.wxfx.smart.Circle;

 

  • 해당 문장을 통해서 컴파일러에게 전달하는 내용은 다음과 같다.

"지금부터 Circle이라고 하면 com.wxfx.smart.Circle을 의미하는 것으로 간주해라”

 

  • 따라서 위의 import 선언 이후로는 다음과 같이 인스턴스를 생성할 수 있습니다.

 

circle c1 = new Circle(3.5(;

 

  • 물론 다음과 같이 동일한 이름의 클래스를 대상으로 동시에 import 선언을 하는 것은 불가합니다.
    이러한 상황에서는 Circle이라는 이름에 대해서 ‘이름 충돌’이 발생합니다.
import com.wxfx.smart.Circle;
import com.fxms.simple.Cirlce;

 

  • 그리고 클래스가 아닌 패키지를 대상으로 다음과 같이 import 선언을 하는 것도 가능합니다.
import com.wxfx.smart.*;

 

  • 해당 문장을 통해 컴파일러에게 전달하는 내용은 다음과 같다.
“지금부터 com.wxfx.smart 패키지로 묶인 클래스는 패키지 선언을 생략하겠다.”

 

  • 예를 들어 com.wxfx.smart 패키지로 묶인 클래스로 Circle과 Triangle이 있다면,
    위의 import 선언 이후로는 이 둘 모두 다음과 같이 클래스의 이름만으로 인스턴스를 생성할 수 있습니다.
Cicle c = new Circle(1.0);
Triangle t = new Triangle(2.0);

 

  • 끝으로 패키지 대상의 import 선언은 이름 충돌이 발생할 수 있고, 의도하지 않은 클래스의 인스턴스를 생성하는 상황으로 이어질 수 있어 사용하는데 주의해야 합니다.

 

📒 Reference (참고 자료)


  1. 윤성우의 열혈 자바
profile

제이제이

@아사비치즈스틱

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!