본문 바로가기

2025/04/29

반응형

✅ 오전 수업 요약

1. final 필드 (Korean 클래스)

  • final은 한 번 값이 설정되면 변경 불가
  • 생성자 또는 선언 시 초기화 가능

2. static final 상수 (Earth 클래스)

  • static final로 고정값(상수) 선언
  • 관례적으로 대문자로 작성
  • 클래스명으로 접근

3. 접근 제한자 (A, B, C 클래스)

  • public : 어디서나 접근 가능
  • (default) : 같은 패키지 내에서만 접근 가능
  • private : 클래스 내부에서만 접근 가능
  • 다른 패키지에서 default, private 접근 시 컴파일 에러

✅ 오후 수업 요약

1. Getter / Setter 메서드 (Car 클래스)

  • private 필드 값을 안전하게 다루기 위해 Getter/Setter 사용
  • 유효성 검사(예: 음수 속도 입력 시 보정) 포함
  • isStop() 메서드는 boolean형 필드 getter로 활용

✅ 자습 내용 요약

1. Member 클래스 생성 및 사용 (mission14)

package ch06.sec99.mission14;

public class Member {
	String name;
	String id;
	String password;
	int age;
	
	Member(String name, String id){
		this.name = name;
		this.id = id;
	}
}
package ch06.sec99.mission14;

public class MemberExample {
	public static void main(String[] args) {
		Member m1 = new Member("홍길동", "hong");
		
		System.out.println("name : " + m1.name + " / id : " + m1.id);
	}
}
  • name, id 필드 설정
  • 생성자를 통해 필드 초기화

2. MemberService 로그인 기능 (mission15)

package ch06.sec99.mission15;

public class MemberService {
	boolean login(String id, String password) {
		if (id.equals("hong") && password.equals("12345"))
			return true;
		else
			return false;
	}

	void logout(String id) {
		System.out.println(id + "님이 로그아웃 되었습니다");
	}
}
package ch06.sec99.mission15;

public class MemberServiceExample {
	public static void main(String[] args) {
		MemberService memberService = new MemberService();
		boolean result = memberService.login("hong", "12345");
		if (result) {
			System.out.println("로그인 되었습니다.");
			memberService.logout("hong");
		} else {
			System.out.println("id 또는 password가 올바르지 않습니다.");
		}
	}
}
  • 로그인 검증 메서드 login()
  • 로그아웃 메서드 logout()

3. Printer 클래스 (mission16, mission17)

  • instance 메서드 버전 (mission16)
package ch06.sec99.mission16;

public class Printer {
	void println(String value){
		System.out.println(value);
	}
	
	void println(int value) {
		System.out.println(value);
	}
	
	void println(boolean value) {
		System.out.println(value);
	}
	
	void println(double value) {
		System.out.println(value);
	}
}
package ch06.sec99.mission16;

public class PrinterExample {
	public static void main(String[] args) {
		Printer printer = new Printer();
		printer.println(10);
		printer.println(true);
		printer.println(5.7);
		printer.println("홍길동");
	}
}
  • static 메서드 버전 (mission17)
package ch06.sec99.mission17;

public class Printer {
	static void println(String value) {
		System.out.println(value);
	}

	static void println(int value) {
		System.out.println(value);
	}

	static void println(boolean value) {
		System.out.println(value);
	}

	static void println(double value) {
		System.out.println(value);
	}
}
package ch06.sec99.mission17;

public class PrinterExample {
	public static void main(String[] args) {
		Printer.println(10);
		Printer.println(true);
		Printer.println(5.7);
		Printer.println("홍길동");
	}
}
  • 다양한 타입(String, int, boolean, double) 출력 가능

4. ShopService 싱글톤 패턴 (mission18)

package ch06.sec99.mission18;

public class ShopService {
	private static ShopService singleton = new ShopService();
	private ShopService() {
	}
	
	public static ShopService getInstance() {
		return singleton;
	}
}
package ch06.sec99.mission18;

public class ShopServiceExample {
	public static void main(String[] args) {
		ShopService obj1 = ShopService.getInstance();
		ShopService obj2 = ShopService.getInstance();
		
		if(obj1 == obj2)
			System.out.println("같은 ShopService 객체입니다.");
		else
			System.out.println("다른 ShopService 객체입니다.");
	}
}
  • 객체를 단 하나만 생성하는 패턴
private static ShopService singleton = new ShopService();
private ShopService() { }
public static ShopService getInstance() { return singleton; }
  • == 비교로 동일 객체 확인

5. Account 클래스 (mission19)

package ch06.sec99.mission19;

public class Account {
	private int balance = 0;
	final private int MIN_BALANCE = 0;
	final private int MAX_BALANCE = 1000000;

	public int getBalance() {
		return balance;
	}

	public void setBalance(int balance) {
		if (MIN_BALANCE <= balance && balance <= MAX_BALANCE) {
			this.balance = balance;
		}
	}
}
package ch06.sec99.mission19;

public class AccountExample {
	public static void main(String[] args) {
		Account account = new Account();
		
		account.setBalance(10000);
		System.out.println("현재 잔고 : " + account.getBalance());
		
		account.setBalance(-100);
		System.out.println("현재 잔고 : " + account.getBalance());
		
		account.setBalance(2000000);
		System.out.println("현재 잔고 : " + account.getBalance());
		
		account.setBalance(30000);
		System.out.println("현재 잔고 : " + account.getBalance());
	}
}
  • 잔액 제한 (MIN_BALANCE, MAX_BALANCE)
  • Setter에서 유효한 범위 내일 때만 설정

6. BankApplication - 계좌 관리 프로그램 (mission20)

package ch06.sec99.mission20;

public class Account {
	private String num = null;
	private String name = null;
	private int balance = 0;
	final private int MIN_BALANCE = 0;
	final private int MAX_BALANCE = 1000000;

	public int getBalance() {
		return balance;
	}

	public void setBalance(int balance) {
		if (MIN_BALANCE <= balance && balance <= MAX_BALANCE) {
			this.balance = balance;
		}
	}
	
	public void plusBalance(int balance) {
		this.balance += balance;
	}
	
	public void minusBalance(int balance) {
		this.balance -= balance;
	}

	public String getNum() {
		return num;
	}

	public void setNum(String num) {
		this.num = num;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public static void main(String[] args) {
		
	}
}
package ch06.sec99.mission20;

import java.util.Scanner;

public class BankApplication {
	Scanner sc = new Scanner(System.in);
	Account account[] = new Account[100];

	public static void main(String[] args) {
		BankApplication ba = new BankApplication();
		ba.start();
		System.out.println("프로그램 종료");
	}

	void start() {
		String input;

		while (true) {
			System.out.println("-".repeat(50));
			System.out.println("1.계좌생성 | 2.계좌목록 | 3.예금 | 4.출금 | 5. 종료");
			System.out.println("-".repeat(50));
			System.out.print("선택> ");

			input = sc.nextLine();
			if (input.equals("1"))
				createAccount();
			else if (input.equals("2"))
				accountList();
			else if (input.equals("3"))
				moneyPlue();
			else if (input.equals("4"))
				moneyMinus();
			else
				break;

		}
	}

	void createAccount() {
		String input;
		Account acc = new Account();

		System.out.println("-".repeat(10));
		System.out.println("계좌생성");
		System.out.println("-".repeat(10));

		System.out.print("계좌번호 : ");
		input = sc.nextLine();
		acc.setNum(input);

		System.out.print("계좌주 : ");
		input = sc.nextLine();
		acc.setName(input);

		System.out.print("초기입금액 : ");
		input = sc.nextLine();
		acc.setBalance(Integer.parseInt(input));

		for (int i = 0; i < account.length; i++)
			if (account[i] == null) {
				account[i] = acc;
				break;
			}

		System.out.println("결과: 계좌가 생성되었습니다.");
	}

	void accountList() {
		System.out.println("-".repeat(10));
		System.out.println("계좌목록");
		System.out.println("-".repeat(10));

		for (int i = 0; i < account.length; i++) {
			if (account[i] == null)
				break;
			System.out.println(account[i].getNum() + "\t" + account[i].getName() + "\t" + account[i].getBalance());
		}
	}

	void moneyPlue() {
		String input;
		int money;

		System.out.println("-".repeat(10));
		System.out.println("예금");
		System.out.println("-".repeat(10));

		System.out.print("계좌번호 : ");
		input = sc.nextLine();

		for (int i = 0; i < account.length; i++)
			if (account[i] == null)
				break;
			else if (account[i].getNum().equals(input)) {
				System.out.print("예금액 : ");
				money = Integer.parseInt(sc.nextLine());
				account[i].plusBalance(money);
			}

	}

	void moneyMinus() {
		String input;
		int money;

		System.out.println("-".repeat(10));
		System.out.println("출금");
		System.out.println("-".repeat(10));

		System.out.print("계좌번호 : ");
		input = sc.nextLine();

		for (int i = 0; i < account.length; i++)
			if (account[i] == null)
				break;
			else if (account[i].getNum().equals(input)) {
				System.out.print("출금액 : ");
				money = Integer.parseInt(sc.nextLine());
				account[i].minusBalance(money);
				System.out.println("결과: 출금이 성공되었습니다.");
			}
	}
}
  • 기능:
    • 계좌 생성
    • 계좌 목록 출력
    • 예금
    • 출금
  • 계좌는 Account 배열에 저장
  • Scanner로 사용자 입력 받아 처리
  • 배열에 null 체크하여 빈 공간에 새 계좌 저장
  • 예금/출금 시 계좌번호 일치 여부 검사

📌 12일차 핵심 요약

항목 주요 내용
final 필드 한 번 초기화 후 값 변경 불가
static final 상수 클래스 로딩 시 고정, 대문자 명명
접근 제한자 public, default, private 차이 이해
Getter/Setter 필드 보호 및 안전한 값 조작
메서드 오버로딩 이름 같고 매개변수 다르게 여러 메서드 정의
싱글톤 패턴 하나의 인스턴스만 생성 및 공유
실습 프로젝트 계좌 관리 프로그램 구축 (생성, 목록, 예금, 출금)
댓글
반응형

이번 글에서는 private 필드를 외부에서 직접 접근하지 않고,
gettersetter 메서드를 이용해
안전하게 값을 읽고 변경하는 방법을 학습합니다.
이 방식은 캡슐화(Encapsulation) 라고 하며, 객체 지향 프로그래밍의 핵심 원칙 중 하나입니다.


📦 클래스 코드 (Car.java)

package ch06.sec14;

public class Car {
	private int speed;
	private boolean stop;

	public int getSpeed() {
		return speed;
	}

	public void setSpeed(int speed) {
		if (speed < 0)
			this.speed = 0;
		else
			this.speed = speed;
	}

	public boolean isStop() {
		return stop;
	}

	public void setStop(boolean stop) {
		this.stop = stop;
		if (stop)
			this.speed = 0;
	}
}

📌 실행 코드 (CarExample.java)

package ch06.sec14;

public class CarExample {
	public static void main(String[] args) {
		Car car = new Car();
		
		car.setSpeed(-50);
		System.out.println("현재 속도 : " + car.getSpeed());
		
		car.setSpeed(60);
		System.out.println("현재 속도 : " + car.getSpeed());
		
		if (!car.isStop())
			car.setStop(true);
		System.out.println("현재 속도 : " + car.getSpeed());
	}
}

💬 코드 설명

  • private int speed;, private boolean stop;
    → 외부에서 직접 접근할 수 없는 비공개 필드
  • public int getSpeed()
    speed 값을 외부에서 읽을 수 있게 해주는 메서드
  • public void setSpeed(int speed)
    speed 값을 설정하는 메서드
    → 입력 값이 음수면 0으로 강제 조정 (유효성 검사)
  • public boolean isStop()
    stop 상태를 외부에서 읽을 수 있게 해주는 메서드
  • public void setStop(boolean stop)
    stop 상태를 설정하고, 멈추면 speed를 자동으로 0으로 만듦

💻 실행 결과

현재 속도 : 0
현재 속도 : 60
현재 속도 : 0

📌 간단 정리

메서드 역할
getSpeed() 현재 속도를 읽기
setSpeed(int) 속도를 설정 (0 이상만 허용)
isStop() 현재 멈춤 여부 확인
setStop(boolean) 멈춤 설정 (멈추면 속도 0)

💡 포인트 정리

  • private 필드는 객체 외부에서 직접 접근을 차단
  • getter 메서드로 값을 안전하게 읽을 수 있음
  • setter 메서드로 값을 제어하면서 유효성 검사(Validation) 가능
  • 캡슐화는 객체의 무결성을 유지하고, 버그를 예방하는 데 큰 도움이 됨
  • boolean 타입 getter는 is필드명() 형태로 작성하는 것이 관례
댓글
반응형

이번 글에서는 클래스 내부 필드와 메서드에 적용된
접근 제한자(public, default, private)
같은 패키지 또는 다른 패키지에서 접근할 때
어떤 영향을 미치는지 실습을 통해 확인합니다.


📦 클래스 코드 (A.java)

package ch06.sec13.exam03.package1;

public class A {
	public int field1;
	int field2;
	private int field3;

	public A() {
		field1 = 1;
		field2 = 1;
		field3 = 1;

		method1();
		method2();
		method3();
	}

	public void method1() {
	}

	void method2() {
	}

	private void method3() {
	}
}

📦 클래스 코드 (B.java)

package ch06.sec13.exam03.package1;

public class B {
	public void method() {
		A a = new A();

		a.field1 = 1; // (O) public
		a.field2 = 1; // (O) default - 같은 패키지라서 가능
		a.field3 = 1; // (X) private - 접근 불가

		a.method1();  // (O) public
		a.method2();  // (O) default - 같은 패키지라서 가능
		a.method3();  // (X) private - 접근 불가
	}
}

📦 클래스 코드 (C.java)

package ch06.sec13.exam03.package2;

import ch06.sec13.exam03.package1.A;

public class C {
	public C() {
		A a = new A();

		a.field1 = 1; // (O) public
		a.field2 = 1; // (X) default - 다른 패키지라서 접근 불가
		a.field3 = 1; // (X) private - 접근 불가

		a.method1();  // (O) public
		a.method2();  // (X) default - 다른 패키지라서 접근 불가
		a.method3();  // (X) private - 접근 불가
	}
}

💬 코드 설명

  • public
    → 어디서든 접근 가능 (같은 패키지 + 다른 패키지 모두)
  • default (아무 키워드 없음)
    같은 패키지 안에서는 접근 가능, 다른 패키지에서는 접근 불가
  • private
    클래스 내부에서만 접근 가능. 다른 클래스에서는 절대 접근 불가

📌 간단 정리

접근 제한자 같은 패키지 다른 패키지 같은 클래스 내부
public O O O
default (생략) O X O
private X X O

💻 실행 결과

  • B 클래스에서는 field1, field2, method1(), method2() 사용 가능
    → field3, method3() 사용 불가 (private 때문)
  • C 클래스에서는 field1, method1()만 사용 가능
    → field2, field3, method2(), method3() 모두 접근 불가

💡 포인트 정리

  • public은 모두에게 공개
  • default같은 패키지끼리만 공개
  • private자기 클래스 내부에서만 사용 가능
  • 다른 패키지에서 접근하려면 반드시 public이어야 함
  • private 필드는 외부에서 직접 수정하거나 읽을 수 없기 때문에 getter/setter를 통해 우회 접근함
댓글
반응형

이번 글에서는 여러 패키지에 동일한 이름을 가진 클래스를 사용할 때
import 구문을 활용해 클래스를 가져오는 방법과,
패키지 경로를 직접 명시하는 방법을 학습합니다.
패키지를 나누어 관리하면 코드가 깔끔해지고 충돌을 방지할 수 있습니다.


📌 클래스 코드 (Car.java)

package ch06.sec12.hyundai;

import ch06.sec12.hankook.SnowTire;
import ch06.sec12.kumho.AllSeasonTire;

public class Car {
	ch06.sec12.hankook.Tire t1 = new ch06.sec12.hankook.Tire();
	ch06.sec12.kumho.Tire t2 = new ch06.sec12.kumho.Tire();

	SnowTire t3 = new SnowTire();
	AllSeasonTire t4 = new AllSeasonTire();
}

💬 코드 설명

  • package ch06.sec12.hyundai;
    → Car 클래스가 hyundai 패키지에 속해 있다는 선언
  • import ch06.sec12.hankook.SnowTire;
    → SnowTire 클래스를 별도의 패키지에서 가져옴 (짧게 사용 가능)
  • import ch06.sec12.kumho.AllSeasonTire;
    → AllSeasonTire 클래스를 가져옴
  • ch06.sec12.hankook.Tire / ch06.sec12.kumho.Tire
    → 서로 다른 패키지에 동일한 이름(Tire)이 존재하므로 패키지명을 직접 명시하여 구분
  • SnowTire, AllSeasonTire
    → import 덕분에 패키지명 없이 클래스명만 사용 가능

📌 간단 정리

사용 방법 설명
import 패키지명.클래스명; 클래스를 가져와 짧게 사용
패키지명.클래스명 직접 지정 같은 이름이 여러 패키지에 있을 때 충돌 방지

💻 실행 흐름 요약

  • Tire는 직접 패키지명을 써야 한다 (충돌 방지용)
  • SnowTire, AllSeasonTire는 import로 짧게 사용 가능
  • 모든 객체가 정상적으로 생성되며 패키지 구성이 깔끔하게 관리됨

💡 포인트 정리

  • 패키지를 나누어 관리하면 클래스 이름 충돌을 방지할 수 있음
  • 서로 다른 패키지에 같은 이름의 클래스가 있을 경우, 패키지명까지 명시해야 구분 가능
  • import 구문을 활용하면 패키지명을 생략하고 클래스명만 사용할 수 있음
  • 패키지 구조를 잘 설계하면 대규모 프로젝트에서도 유지보수가 쉬워짐
댓글
반응형

이번 글에서는 클래스 내부에 변하지 않는 고정값을 선언할 때 사용하는
static final 조합, 즉 상수(Constant)를 정의하는 방법을 학습합니다.
상수는 프로그램 전체에서 같은 값을 공유하고, 변경되지 않도록 보장할 수 있습니다.


📦 클래스 코드 (Earth.java)

package ch06.sec11.exam02;

public class Earth {
	static final double EARTH_RADIUS = 6400;
	static final double EARTH_SURFACE_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS;
}

📌 실행 코드 (EarthExample.java)

package ch06.sec11.exam02;

public class EarthExample {
	public static void main(String[] args) {
		System.out.println("지구의 반지름 : " + Earth.EARTH_RADIUS + "km");
		System.out.println("지구의 표면적 : " + Earth.EARTH_SURFACE_AREA + "km^2");
	}
}

💬 코드 설명

  • static final double EARTH_RADIUS = 6400;
    → 지구 반지름 상수, 프로그램 어디서나 동일하게 사용
  • static final double EARTH_SURFACE_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS;
    → 구의 표면적 공식(4πr²)을 이용해 계산한 값
    → 반지름을 이용해 다른 상수도 정의 가능
  • Earth.EARTH_RADIUS, Earth.EARTH_SURFACE_AREA
    클래스 이름으로 직접 접근 (객체 생성 없이 사용)

💻 실행 결과

지구의 반지름 : 6400.0km
지구의 표면적 : 514718540.2467583km^2

📌 간단 정리

선언 형태 의미
static 클래스에 소속, 객체 없이 사용 가능
final 한 번 초기화되면 변경 불가
static final 변하지 않는 고정값(상수)을 클래스에 소속시킴

💡 포인트 정리

  • static final은 상수를 정의할 때 사용
  • 상수 이름은 관례적으로 모두 대문자로 작성 (ex. EARTH_RADIUS)
  • 프로그램 어디서든 일관된 값을 사용할 수 있음
  • 수식에 상수를 활용하면 코드 가독성유지보수성이 높아짐
  • 상수는 변경될 가능성이 없는 공통 데이터(물리 상수, 시스템 설정) 등을 정의할 때 사용
댓글
반응형

이번 강의에서는 자바 클래스와 필드, 메서드 등에 적용할 수 있는
접근 제한자(access modifier)에 대해 학습합니다.
접근 제한자는 코드의 보안성과 설계 구조를 명확하게 만들기 위해 사용되며,
패키지 또는 객체 간 접근을 제어합니다.


📦 클래스 코드 (Korean.java)

package ch06.sec11.exam01;

public class Korean {
	final String nation = "대한민국";
	final String ssn;
	String name;

	public Korean(String ssn, String name) {
		this.ssn = ssn;
		this.name = name;
	}
}

📌 실행 코드 (KoreanExample.java)

package ch06.sec11.exam01;

public class KoreanExample {
	public static void main(String[] args) {
		Korean k1 = new Korean("123456-1234567", "자바킴");

		System.out.println(k1.nation);
		System.out.println(k1.ssn);
		System.out.println(k1.name);

		k1.name = "김자바";
	}
}

💬 코드 설명

  • final String nation = "대한민국";
    → 선언과 동시에 초기화한 필드 → 절대 변경 불가
  • final String ssn;
    → 생성자에서만 초기화할 수 있음 → 이후 변경 불가
  • String name;
    → 일반 필드 → 자유롭게 읽고 쓸 수 있음
  • 생성자 Korean(String ssn, String name)
    → 객체 생성 시 주민등록번호와 이름을 초기화
  • k1.name = "김자바";
    → name 필드는 수정 가능 (final이 아님)

💻 실행 결과

대한민국
123456-1234567
자바킴

※ name을 "김자바"로 변경했지만 출력은 안 했기 때문에 변경 내용은 확인되지 않음.


📌 간단 정리

필드명 final 여부 설명
nation O "대한민국" 고정, 변경 불가
ssn O 생성자에서만 초기화 가능, 이후 변경 불가
name X 자유롭게 변경 가능

💡 포인트 정리

  • final 필드는 한 번만 초기화 가능하며 이후 수정 불가
  • 선언과 동시에 초기화하거나, 생성자에서 초기화해야 함
  • 개인 식별정보(ssn 등)처럼 절대 변하지 않아야 하는 값에 final을 적용
  • 일반 필드는 자유롭게 읽고 쓸 수 있지만, 설계에 따라 final 적용 여부를 결정
댓글