접근제한자·오버로딩·패키지·생성자

heeezni·2025년 5월 13일

Java 문법

목록 보기
6/14
post-thumbnail

메서드 (Method)

클래스에 소속된 함수를 메서드라고 함

public(접근제한자) | static(수식자) | void(반환타입) 메서드 이름(매개변수){...}
└── 접근제한자, 수식자는 순서 바뀌어도 상관없지만 관례적으로 이렇게 씀
└── 접근제한자, 수식자(modifier), 매개변수는 생략 가능

ex. public void 메서드명(){...} //반환형이 없는 메서드

접근제한자

🔓public:

  • 외부의 있는 모든 코드가 어디서든 접근 가능 (패키지 상관 없음)

🛡️protected:

  • 같은 패키지(디렉토리) + 자식 클래스는 접근 가능
  • 다른 패키지에 있어도 상속받은 클래스라면 접근 가능

📦default:

  • 접근 제한자를 명시하지 않으면 기본값(default)
  • 같은 패키지 안에서는 접근 가능
  • 자식 클래스여도 같은 패키지가 아니면 접근 금지

🔒private:

  • 같은 클래스 내부에서만(같은 멤버끼리만) 접근 가능
  • 다른 클래스에서는 절대 접근 불가 (같은 패키지, 자식 클래스여도 ❌)

클래스 외부 공개 여부

위치publicprotecteddefaultprivate
같은 클래스
같은 패키지
다른 패키지-상속
다른 패키지-비상속

메서드 오버로딩 (Method Overloading)

하나의 클래스 내에서 같은 이름의 메서드를 여러 개 정의할 수 있도록 허용하는 기법
→ 기능은 유사하지만 입력이 다른 경우, 같은 이름을 쓰되 다르게 처리할 수 있음.

프로그램 작성 시, 개발자는 변수와 메서드명에 상당한 공을 들여 이름을 부여한다.
하지만 비슷한 기능의 메서드임에도 불구하고,
메서드명 중복 금지라는 원칙을 너무 고수하다보면
메서드를 여러개 만들어야 하는 상황이 옴 → 효율성 떨어짐 → 메서드 오버로딩을 쓰자!

오버로딩이 인정되기 위한 조건

  1. 메서드 이름이 같아야 함
  2. 매개변수의 ‘자료형’ 또는 ‘개수’가 달라야 함
class Duck{
	
	//오리가 난다
	public void fly(){ //매개변수 없음
	}
	//오리가 조금 더 높은 높이에서 난다
	public void fly(int height){//오버로딩o 매개변수 타입 다름
     // 매개변수로 높이(height) 받음
    }
	//public String fly(){//오버로딩x : 반환 타입만 다르고 매개변수는 같음
    //⚠ 반환 타입이 다른 것은 오버로딩에 영향을 미치지 않음
    }
	//pulic void fly(int x){//오버로딩x : 이미 존재하는 'fly(int height)'랑 매개변수 동일
    }
	public void fly(int x, boolean k){//오버로딩o : 매개변수 개수 다름
	}
}

오버로딩 사용하는 이유

  • 가독성 향상: 같은 동작이면 같은 이름을 쓰는 게 직관적
  • 유지보수 용이: 한눈에 같은 동작이라는 걸 알 수 있음
  • 메서드 이름 고민 줄이기: 일관성 있는 이름 사용 가능

생성자

자바의 생성자는 자바스크립트의 constructor()와 매우 비슷한 역할

Java의 생성자와 JS의 constructor()

역할Java 생성자JavaScript constructor()
객체 초기화new로 객체 만들 때 호출됨new로 객체 만들 때 호출됨
필드(속성) 초기화생성자 안에서 this.필드 = 값;constructor 안에서 this.속성 = 값;
오버로딩(다양한 매개변수 가능)가능불가능 (1개만 가능)
super()로 부모 호출가능가능 (ES6 클래스에서만)
  • 자바의 생성자는 클래스명과 완전 동일해야함 → 클래스명( ){...}

  • 직접 생성자를 정의하지 않으면, 자바 컴파일러가 기본 생성자(디폴트 생성자)를 자동으로 만들어주는데, 이 생성자는 아무 일도 하지 않음. (단, super(); 호출은 예외다)

super(); : 부모 클래스의 생성자를 호출하는 코드인데, 자바는 클래스가 Object를 상속하므로 자동으로 들어감
(자동으로 삽입. 그래서 소스 코드엔 안 보이지만, 실제로는 존재)

이 코드는

class Animal {
}

class Dog extends Animal {
}

컴파일 시 실제로는 아래처럼 처리됨

class Animal {
    Animal() {
        super(); // Object의 생성자 호출
    }
}

class Dog extends Animal {
    Dog() {
        super(); // Animal의 생성자 호출
    }
}
  • 생성자도 메서드 → 메서드 오버로딩의 원칙이 당연히 적용됨
    하나의 클래스내에 생성자 여러개 가능!
    public Cat(){…}
    public Cat(int age){…} : 생성자 오버로딩

  • 생성자에 반환형을 두는 순간, 일반 메서드가 되어버림.
    반환형 절대X

클래스,생성자,객체 명칭비교

class Car {
    Car() {
        System.out.println("생성자 호출됨");
    }
}
public class Main {
    public static void main(String[] args) {
        Car car = new Car();
    }
}
부분의미
Car클래스 이름 (사용자 정의 자료형)
Car()생성자 (클래스 이름과 같음)
car참조 변수 이름 (우리가 지은 변수 이름)
new Car()객체 생성 + 생성자 호출

Call by value

참조값(주소)를 매개변수로 전달했을 때의 동작 이해

자바는 항상 Call by Value
(Call by Reference: 원래 변수 자체를 직접 넘기는 방식 C++)

객체를 넘기면 참조값(주소) 이 복사되므로 → 객체 내부는 수정 가능
객체 자체를 새로 할당하면 → 원본과 무관

🏠 "집 주소를 주면, 그 집을 찾아가서 내부를 바꿀 수는 있지만,
새로운 집으로 이사시키는 건 불가능해요."
→ 자바에서 객체를 매개변수로 넘길 때의 핵심 개념
참조값(집 주소) = 값이기 때문에 복사돼서 전달됨
복사된 주소로 같은 객체에 접근하니까 → 내부 속성 변경 가능
하지만 원래 변수가 어떤 객체를 가리키는지 자체는 못 바꿈

  • 참조형 (Computer p) → "같은 집 주소를 전달받고 그 집 내부를 바꾸는 것"
    → 원본 객체 수정 가능
  • 기본형 (int price) → "종이에 써 있는 숫자만 복사해서 받은 것이라 원본 종이는 안 바뀜"
    → 복사본만 바뀌고 원본은 그대로
class Computer{
	int speed=300;
}

class UseComputer {
	public void setting(Computer c , int s){ 
    //c는 같은 객체(com) 참조 → heap에 speed 직접 접근 가능
		c.speed=s; 
		s=50; //(기본형: k의 값만 복사되어 왔기 때문에 원본 k는 그대로)
	}
	
	public static void main(String[] args) {
		int k=500; 
		
		UseComputer uc = new UseComputer();
		Computer com = new Computer();

		com.speed=100;
		
		uc.setting(com , k); 
		
		System.out.println(com.speed); 
		System.out.println(k);
	}
}

예제의 흐름을 JVM 메모리 구조로 확인

(헷갈리니까 이제부터 stack은 LIFO구조로 안쓰고 위에서부터 순서대로 작성)

methodstackheap
main()k = 500@101 (Computer)
uc → @201└─ speed = 500
com → @101
@201 (UseComputer)
호출: uc.setting(com, k)(내용 없음)
├─ c → @101 (com과 같은 객체 참조)
└─ s = 500 (값 복사됨, 지역변수)
→ s = 50 (📌 값만 바뀌고 k는 유지)

uc.setting(com, k) 호출 시:

c는 같은 객체(com) 참조 → heap에 있는 객체의 speed변수에 직접 접근 가능
s는 k 값(500)만 복사됨 → 이후 s = 50 해도 k는 변하지 않음

변수타입전달 방식원본 변경 여부결과값설명
c참조형주소 전달Ocom.speed = 500메서드 안에서 객체의 속성을 바꾸면 원본도 바뀜
s기본형값 전달Xk = 500 유지메서드 안에서 변경해도 원본 안 바뀜

Package

❗ 같은 패키지 안에 있는 클래스들끼리는 import 없이도 서로 사용 가능

Java 프로젝트 기본 구조

project
└── src : 원본 소스 코드 (.java)
└── bin : 컴파일된 바이트 코드 (.class)

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

Package의 역할

  1. 관련성 있는 프로젝트끼리 묶기 위함

  2. 클래스 이름의 중복 방지
    서로 다른 패키지에 같은 이름의 클래스가 있어도 충돌하지 않음

  3. 유일성을 보장하기 위해 기업의 도메인과 프로젝트명으로 네이밍관례
    보통 도메인을 거꾸로 써서 시작함
    예) com.google.search, com.회사명.프로젝트명.기능구분


Java 환경 변수 설정 + 패키지 클래스 활용

1️⃣ CLASSPATH 등록하기 (~bin까지)
목적: 컴파일된 .class 파일을 JVM이 찾을 수 있도록 설정

방법: 환경변수 CLASSPATH에 bin까지의 경로를 추가
(윈도우 기준) 시스템 환경 변수 → 새로 만들기

  • 변수 이름: CLASSPATH
  • 변수 값:
    C:\lecture_workspace\back_workspace\java_workspace\testproject\bin
    (변수값 추가 시 bin까지의 경로 다음에 공백없이;찍고 다음 경로 추가)

2️⃣ EditPlus에 편리한 Java 개발환경 등록
목적: EditPlus 내에서 컴파일과 실행을 빠르게 할 수 있도록 도구 등록

방법: EditPlus 실행 → [도구] > [사용자 도구 그룹 선택] > [사용자 도구 구성]

🔹 컴파일 등록

  • 명령: C:\jdk-21.0.2\bin\javac.exe (javac.exe)
  • 인수: -d 경로(~bin까지) $(FileName)

    javac -d 경로 파일명.java

  • 초기 디렉터리: 파일 디렉토리 $(FileDir)

🔹 실행 등록

  • 명령: C:\jdk-21.0.2\bin\java.exe (java.exe)
  • 인수: $(Prompt)(=인수내용묻기).$(FileNameNoExt)(=확장자 뺀 파일이름)

    java (패키지명).클래스명

  • 초기 디렉터리: 파일 디렉토리 $(FileDir)

3️⃣ 패키지 구조와 클래스 사용 예제

src/
└── com/
    └── sinse/
        └── testproject/
            ├── plant/
            │   └── Rose.java
            └── use/
                └── UseRose.java

Rose.java

package com.sinse.testproject.plant;

public class Rose {
    public void bloom() {
        System.out.println("The rose is blooming.");
    }
}

UseRose.java

package com.sinse.testproject.use;
import com.sinse.testproject.plant.Rose;

class UseRose {
	public static void main(String[] args) {
		Rose rose=new Rose();
		rose.bloom();
	}
}

→컴파일(ctrl+1) 후, 실행(ctrl+2)하면 The rose is blooming. 출력

profile
아이들의 가능성을 믿었던 마음 그대로, 이제는 나의 가능성을 믿고 나아가는 중입니다.🌱

0개의 댓글