자바 패키지·수식자·캡슐화·Has-a 관계

heeezni·2025년 5월 13일
0

Java 문법

목록 보기
7/14
post-thumbnail

Package와 Import

Package

❗ src 기준 하위 폴더만 패키지 경로로 사용

  • 패키지 : 클래스를 분류해 놓은 디렉토리
  • 하위 패키지는 .으로 구분하고 소문자로 작성함이 관례
  • 클래스 파일의 제일 상단에 선언
  • 패키지 선언 시, 다른 패키지에 위치한 클래스가 접근하도록 하려면 public 으로 설정

classpath

  • 선언된 패키지는 완전한 경로가 아니므로,
    패키지 앞에 생략된 OS의 풀 경로는 classpath에 등록해야함

  • import시 classpath에 등록된 경로는 제외하고, 패키지명과 클래스명만 명시
    (참고: classpath에는 bin까지의 경로를 등록)

  • classpath 사용 이유 : Java가 플랫폼 중립적 언어인데,
    (Java의 "Write Once, Run Anywhere"을 보면 알 수 있음)
    class 코드 안에 풀경로를 넣어버리면 플랫폼 의존적인 코드가 되어 버리기 때문

import

import : 다른 패키지에 있는 클래스 파일의 위치를 참조하는 선언문
❗ 같은 패키지 안에 있는 클래스들끼리는 import 없이도 서로 사용 가능


javadoc 명령어

<다른 사람이 만든 클래스 파일 사용하기 >
누군가에게.class파일을 받았다고 가정해보자,
그 안에 어떤 클래스와 메서드가 들어있는지 알아야 사용할 수 있을 것 아닌가?

따라서 클래스를 제작한 사람은 반드시 설명서를 제공할 의무가 있다.
그래서 해당.class파일에 대한 설명서인 API document(프로그래밍 사용설명서)가 필요하다!

javadoc

  • Java 코드에 작성된 주석을 기반으로 API 문서를 자동으로 생성하는 도구
  • 이를 통해 클래스, 메서드, 필드 등에 대한 자세한 정보를 확인할 수 있음
  • 주석은 /**로 시작해 */로 끝나는 형식으로 작성

javadoc 파일명.java
// 현재 작업 중인 폴더(또는 파일이 있는 폴더)에 API 문서들이 생성

javadoc -d 디렉토리명 파일명.java
// -d 옵션을 사용하면 다른 디렉토리에 문서를 생성

<참고>
java 개발 시 사용되는 필수적이고 중요한 클래스들은
java.lang 패키지에 들어있고,
이 패키지는 개발자가 명시하지 않아도 이미 import 되고 있음
String클래스,Object클래스,Math클래스 등...


수식자 Modifier

메서드 정의하는 기본 형식

public(접근제한자) | static(수식자) | void(반환타입) 메서드 이름(매개변수){...}
여기서 수식자를 알아보자

JAVA에서 가장 기본적인 수식자의 종류 3가지

1️⃣ static - 정적
클래스의 인스턴스와 관계없이 클래스 자체에 속하는 변수나 메서드를 의미
객체를 생성하지 않고도 클래스 이름을 통해 접근할 수 있음

  • static이 붙은 변수는 클래스 변수
  • static이 붙은 메서드는 클래스 메서드

2️⃣ final - 마지막
final은 다양한 방식으로 사용되어, 주어진 요소를 변경 불가능하게 만듦

  • 변수에 사용하면, 해당 변수의 값을 변경할 수 없음 (상수화)
  • 메서드에 사용하면, 자식 클래스에서 부모의 메서드를 재정의(오버라이딩) 할 수 없음
    ➡ 업그레이드 불허🚫
  • 클래스에 사용하면, 해당 클래스는 상속할 수 없음
    ➡ 상속 금지🚫

3️⃣ abstract - 추상적
abstract는 구현되지 않은 메서드 또는 클래스를 정의할 때 사용됨

  • 메서드에 사용되면, 해당 메서드는 구현되지 않은 메서드로, 자식 클래스에서 반드시 구현해야 함
  • 클래스에 사용되면, 해당 클래스는 인스턴스를 생성할 수 없으며, 자식 클래스에서 상속받아 구현해야 함

➡ 상속 개념을 배운 후 다시 체크할 것!

상속

<참고> 오버로딩과 오버라이딩

구분오버로딩 (Overloading)오버라이딩 (Overriding)
정의같은 이름의 메서드를 매개변수리턴 타입을 다르게 정의하는 것.부모 클래스의 메서드를 자식 클래스에서 재정의하는 것.
목적메서드 이름을 재사용하여 코드 중복을 줄이기 위해.상속받은 메서드의 기능을 자식 클래스에서 변경하거나 확장하기 위해.
메서드 이름동일동일
매개변수매개변수의 개수타입이 달라야 함부모 클래스의 메서드와 매개변수가 동일해야 함
리턴 타입리턴 타입도 동일하거나 달라도 됨리턴 타입은 부모 메서드와 같아야
접근 제어자자식 클래스에서 변경 가능, 부모 클래스의 접근 제어자보다 넓게 설정 가능부모 클래스의 메서드보다 좁게 설정 불가
  • 오버로딩은 메서드 이름은 같고, 매개변수가 다르거나 리턴 타입이 다르게 정의하는 것.
  • 오버라이딩은 부모 클래스의 메서드를 자식 클래스에서 재정의하여 기능을 변경하는 것.

캡슐화와 은닉화

1️⃣ 캡슐화 (Encapsulation)

  • 데이터 보호와 데이터에 대한 접근 제한을 위해 객체 내부에서 데이터를 숨김
  • 객체는 데이터와 행위(메서드)를 하나의 단위로 묶고, 외부에서 객체의 데이터를 직접적으로 수정하거나 접근할 수 없도록 막음
  • 대신, 외부에서 데이터를 수정하거나 조회할 수 있도록 공개된 메서드 (버튼)를 제공합니다.
    이 메서드들은 객체와 외부의 상호작용을 가능하게 함

2️⃣ 은닉화 (Hiding)

  • 객체의 내부 상태나 구현 세부 사항을 외부에서 알 수 없도록 구체적 구현 숨기기
  • 객체는 외부에서 접근할 수 있는 인터페이스만 제공
    → 객체의 내부 구현이 바뀌더라도 외부에 미치는 영향 최소화
    (API도 은닉화의 일종)

캡슐화와 은닉화의 핵심

데이터를 private으로 선언해 외부에서 그 데이터에 직접 접근하지 못하게 하고, 메서드를 통해 데이터를 읽거나 쓸 수 있게 하는 것

package use;
public class Account {
	
	private String num = "110-409-513991";  // 계좌번호
	private String bank = "신한은행";  // 은행명
	private String owner = "HJ";  // 계좌 소유자
	private int balance = 500000;  // 잔액
	
	// getter 메서드들
	public int getBalance() {  // 잔액 조회
		return balance;
	}
	public String getBank() {  // 은행명 조회
		return bank;
	}
	public String getOwner() {  // 계좌 소유자 조회
		return owner;
	}
	public String getNum() {  // 계좌번호 조회
		return num;
	}
	
	// setter 메서드들
	public void setBalance(int balance) {  // 잔액 설정
		this.balance = balance;
	}
	public void setBank(String bank) {  // 은행명 설정
		this.bank = bank;
	}
	public void setOwner(String owner) {  // 계좌 소유자 설정
		this.owner = owner;
	}
	public void setNum(String num) {  // 계좌번호 설정
		this.num = num;
	}
}

메서드 접근은 나만 제어할 수 있음
ex) 잔액이 음수로 설정되지 않도록 하는 조건을 넣기

결론

캡슐화(Encapsulation)은닉화(Encapsulation)는 거의 같은 개념으로 함께 이루어짐
둘은 아주 밀접하게 연결되어 있으며, 실질적으로 캡슐화를 구현하는 중요한 방법 중 하나가 은닉화임!

위 예제에서 엄밀하게 말하자면
gettersetter로 데이터와 메서드를 하나로 묶는 것은 캡슐화(Encapsulation)의 구현 방식
private 필드를 사용해 내부 데이터를 보호한 것은 은닉화(Encapsulation)의 구현 방식


⭐Has a 관계⭐

날 멘붕에 빠뜨린..

  • 생성자(Constructor): 생성자는 객체가 생성될 때 호출되는 특별한 메서드 객체의 초기 상태를 설정하고, 인스턴스를 생성하는 역할

    생성자는 객체가 생성되는 시점에 초기화를 담당하기 때문에,
    특히 "Has a" 관계로 포함된 다른 객체들을 함께 생성할 때 매우 유용

  • Has a 관계: "Has a" 관계는 객체가 다른 객체를 포함하고 있다는 관계를 나타냄
    집합 관계로, 하나의 객체가 다른 객체를 속성으로 갖고 있다는 의미

    현실에 존재하는 모든 사물은 단독으로 존재할 수 없으며, 객체와 객체 사이에 관련성을 맺으며 존재할 수 밖에 없다.
    Java 언어에서는 특정 객체가 다른 객체를 멤버로 보유하고 있는, 즉 부품 관계를 가리켜 "Has a" 관계라고 한다.

(예제) 현실을 반영하여 자동차를 정의해보자

자동차(Car)는 다음 부품을 가진다.

  • 핸들(Handle)
  • 바퀴(Wheel)
  • 문(Door)
//현실의 핸들 부품객체 생성
package use;
public class Handle {
	String name="파워핸들";
	String color="핑크색";
	
	public void rotate(){
		System.out.println("핸들을 돌려요");
	}
}
//현실의 바퀴 부품객체 생성
package use;
public class Wheel{
	String brand="Hankook";
	int price=170;
	
	public void roll(){
		System.out.println("굴러가요");
	}
}
//현실의 문 부품객체 생성
package use;
public class Door{ // 현실의 문 
	String type="자동";
	
	public void  open(){
		System.out.println("문이 열려요");
	}
	public void  close(){
		System.out.println("문이 닫혀요");
	}
}

주 객체 Car.class

package use;
public class Car{
	int price; //0
	String name; //null

	Handle handle; //null →객체 자료형
	Wheel wheel; //null
	Door door; //null
	
	//생성자는 사물을 태어나게 하는 시점에 초기화에 관여하므로
	//특히 has a car관계에 있는 객체의 인스턴스를 생성할 때 아주 유용
		public Car(){
			price=5000;
			name="k9";
			handle=new Handle(); // → 부품객체 생성
			wheel=new Wheel();
			door=new Door();
		}
}

❗ has a 관계: 객체가 다른 객체를 멤버변수로 보유한 관계

  • Car has a handle
  • Car has a wheel
  • Car has a door

JVM 메모리구조로 뜯어보기

MethodStackHeap
class Handlemain() frameHandle @a → name: "파워핸들"
class Wheel└─ myCar → @d        color: "핑크색"
class DoorWheel @b → brand: "Hankook"
class Car        price: 170
Door @c → type: "자동"
Car @d → handle: @a
      wheel: @b
      door: @c
      price: 5000
      name: "k9"

🚗 UseCar.class

package use;
public class UseCar{
		
	public static void main(String[] args) {
		Car car=new Car(); //본체 (주 객체)
		
		System.out.println(car.handle.color); //출력: 핑크색
		System.out.println(car.wheel.brand); //출력: Hankook
		car.door.open(); //출력: 문이 열려요
	}
}

생성자 안(Car(){...})에서 handle, wheel, door를 new 해주면
👉 주석 내용은 틀린 것이고, 실행은 정상

생성자 안에서 아무것도 하지 않았다면
👉 주석이 맞고, 실행 시 오류

✅ 각 부품객체의 값을 변경하는 방법

방식장점단점
직접 접근car.wheel.brand = "Michelin";간단, 직관적캡슐화 위반 위험
setter 사용car.wheel.setBrand("Michelin");안정성, 유지보수 용이코드 좀 길어짐

요점

  • Handle, Wheel, Door: 각각 현실 부품을 객체로 표현
  • Car: 이 부품들을 멤버변수로 포함 → Has a 관계
  • 생성자에서 new 키워드로 각각의 부품을 초기화 → "자동차 조립"
profile
아이들의 가능성을 믿었던 마음 그대로, 이제는 나의 가능성을 믿고 나아가는 중입니다.🌱

0개의 댓글