[JAVA기초] 클래스 다이어그램, 가비지 컬렉터

포키·2022년 10월 13일
0

국비과정

목록 보기
15/73

TIP
메소드 하나씩 지우고 같은 결과 나오게 해보기
-> 메소드의 의미가 뭔지, 왜 저 메소드가 필요한지 역으로 따라가며 확인해보는 것.

  • toString
    목적: 객체가 담고있는 내용(멤버변수, 멤버변수로 유도할 수 있는 내용들)을 문자열로 바꾸어 전달하는 것 (누구에게? 불러낸 사람(지금까지는 main)에게!
  • 정해진 형태X 클래스를 만드는 사람이 '문자열'로 내보내고 싶은 내용을 내보내도록 정의하면 됨
    굉~~~장히 많이 쓰임

헤더(특히 이름)는 목적·역할이 명확하게 드러나야

/* 	헤더만 보고 무엇을 하는 메소드인지 어떤 역할인지 알 수 있어야 함
	이름만 봐도 String으로 변환하는 메소드임을 알 수 있음		*/
public String toString(){		
	...
}

프로그래밍에 정답은 없지만 최선은 있다.
같은 목적이라도 다른 형태로 만들 수 있지만, 최선의 코드는 비슷하게 수렴한다.
우리는 그것을 찾아야 한다.

클래스 다이어그램

[UML] UML 다이어그램 종류 및 기본
[UML] Class Diagram 기본

  • UML(Unified Modeling Language)의 구성요소 중 하나

  • 코드의 설계도

  • 사람이 사용하는 말(글)만으로는 설계 과정에서 오차가 생길 수 있음
    (나는 당연히 toString 사용해서 이렇게 처리하겠지~ 하고 넘겼는데, 동료는 다른 방식으로 처리한다던지, 고객의 요구사항이 내가 생각한 것과 다르다던지~)
    그걸 해결하기 위해 그림으로 표현하자! 한 것이 UML

  • 클래스 다이어그램을 통해 어떤 변수를 가지고 있고 어떤 메소드를 가지는지 알 수 있음.
    (클래스 다이어그램에 나오는 헤더 정보로)
  • parameter가 없을 때는 비워도 되고 void를 적어도 된다.
  • parameter가 있을 때는 변수:타입 형태로 적는다.
    ex) ~ plus2 (num : int) : int
    ex2) + sum (num1 : int, num2 : int) : int

    접근설명자 access modify
    public + , private -, protected #, 생략 ~ (앞 두 개가 99%)

  • [0..1] : 적을 수도 비울 수도 있음
  • 변수:타입 = "기본값"
    ex) Language : String [0..1] = "English"

신입 개발자로 들어갈 때는 최소한 UML 종류는 다 알고 가야 할 것
(UML - 클래스 / 유스케이스 / 시퀀스 / ...)

UML 개발자 세 명을 three 아미고스 - 세 명의 선각자로 부름. 레셔널 sw. 레셔널 로즈. 그레디 부치 이바 제이콥슨 제임스 럼바우

현실의 객체 - 특징 뽑기 - 상태와 행위로 분류 - 클래스 다이어그램 -
실제 현실에 있는 기능을 가져와서 사람에게 어떻게 설명할 건지? 가 중요

p. 150 Box클래스의 클래스 다이어그램

class Box {
	int width;
    int length;
    int height;
    double getVoume(){
    	...
        return (double) ...
    }
}

객체 생성 연습 - Television

class Television {
	int channel;		// 채널 번호
	int volume;			// 볼륨
	boolean onOff;		// 전원 상태
	public String toString(){
		return "텔레비전의 채널은 " + channel + "이고 볼륨은 " + volume + "입니다.";
	}
}
class TelevisionTest {
	public static void main(String[] args) {
		Television myTv = new Television();
		myTv.channel=7;
		myTv.volume = 10;
		myTv.onOff = true;
		Television yourTv = new Television();
		yourTv.channel = 9;
		yourTv.volume = 12;
		yourTv.onOff = true;
        // 문자열과 합쳐지며 myTv를 문자열로 변경 -> toString 호출 -> return값 반환
		System.out.println("나의 " + myTv);		
		System.out.println("너의 " + yourTv);
	}
}

가비지 콜렉터

가비지(쓰레기)란?

class Some {
	int num;
	public String toString(){
		return "num: " + num;
	}
}
class UseSome {
	public static void main(String[] args) {
		Some s1 = new Some();
		s1.num = 3;
		Some s2 = new Some();
		s2.num = 7;
		s1 = s2;	//	s1이 s2 객체의 주소를 가져라
		System.out.println("s1: " + s1);
		System.out.println("s2: " + s2);
		// 둘 다 s2의 값을 반환함
	}
}
  • 이때 s1 객체는 '메모리(heap memory)에 존재하지만 사용할 수 없는 객체' = '쓰레기'가 됨

가비지 콜렉터

  • 가비지 컬렉터는 사용할 수 없게 된 데이터(쓰레기)를 수거한다(소멸)
    (모든 언어에 있는 건 x! 없으면 개발자가 직접 쓰레기를 책임져야 한다)
  • 언제 지워질지는 알 수 없다!
  • null이란?
    '나타내는 값이 없음'을 의미하는 '값'!
    값이므로 변수에 대입하여 초기화 가능
    ❗❗ 모든 참조형 변수가 가질 수 있는 공통된 값 ❗❗


실행중 에러 (runtime error)

= [Java] 예외가 발생했습니다. (exception error)

class Some {
	int num;
	public String toString(){
		return "num: " + num;
	}
}
class UseSome {
	public static void main(String[] args) {
		Some s1 = new Some();
		s1.num = 3;
		Some s2 = new Some();
		s2.num = 7;
        // s1 = null인데 그 안의 num에 4를 넣으라는 명령
		s1 = null;
		s1.num = 4;
		System.out.println("s1: " + s1);
		System.out.println("s2: " + s2);
	}
}


컴파일 과정에서는 값을 대입하지 않고 '문법'만 확인하므로 에러가 뜨지 않음
하지만 실제로 실행하면 에러가 뜸

에러의 종류

  1. 컴파일 에러 - 문법적으로 틀린 것
  2. 실행중 에러 - 값을 대입하면 오류가 나는 것
    (인간이 판단할 수 없는 부분 - 컴퓨터도 계산할 수 없으므로 에러)
ex) System.out.println(4/0);		// runtime 에러
  1. 논리적 에러 - 사용 중에 개발자가 의도하지 않은 기능상의 문제가 생기는 것
    ex) 게임 내에서 밸런스패치 실패한 경우

에러를 막기 위한 노력

  1. 알파 테스트 - 내부의 개발자들이 검사
  2. 베타 테스트 - 외부인을 데려와 검사 - 오픈베타/클로즈베타 - 엣지케이스를 찾아내기 위함

언제 누가 무슨 목적으로 만들었고 변수는 무슨 의미고 파라미터는 무슨 의미고 - 등등을 주석으로 꼭 적어주기 - 코드가 복잡해질수록 필요 - 자기도 까먹는다

Quiz1. 재고수량 증감하기

/*
	재고 Stock
	===========================
		상품번호 ~ id : String 
		재고수량 ~ count : int
	===========================
		증가() ~ increase(amount:int):void
		감소() ~ decrease(amount:int):void
*/

class Stock {
	String id;						// 상품번호
	int count;						// 재고수량

	void increase(int amount){		
	// 'amount만큼의 양을 count에 더하는' 메소드
		printHeader(amount, "증가");
		if(isPositive(amount)){		// amount가 양수인지 확인
			count += amount;		// amount만큼의 양을 count에 더하는
			printInfo();			// '재고 출력' 메소드
		} 
	}
	void decrease(int amount){
	// 'amount만큼의 양을 count에 빼는' 메소드 + 
		printHeader(amount, "감소");
		if(isPositive(amount)){
			if(amount <= count){
				count -= amount;
				printInfo();
			} else {
				System.out.println("재고가 부족합니다.");
			}
		} 
	}
	public String toString(){		
	// '출력할 문자열(상품번호, 재고수량) 반환' 메소드 
		return id + "(" + count + ")";
	}
	void printHeader(int amount, String what){
	// '증감 명령 확인용 출력' 메소드
		System.out.printf("재고(%s) 수량을 %s(%d) : ", id, what, amount);
	}
	void printInfo(){				
	// ''toString 문자열' 출력' 메소드
		System.out.println(toString());
	}
	boolean isPositive(int amount){	
	// 'amount가 양수인지 확인하는' 메소드
		boolean result = true;
		if(amount <= 0){
			System.out.println("증감 수량은 0보다 큰 값이어야 합니다.");
		}
		return result;
	}
}
class UseStock {
	public static void main(String[] args) {
		Stock s = new Stock();
		s.id = "s001";
		s.count = 30;

		s.increase(40);
		s.decrease(200);
	}
}

Quiz2. 강아지 클래스 만들기 (이름, 종, 색깔)(짖기, 물기, 먹기)

/*
	강아지
		이름
		종
		색깔
		짖기()
		물기()
		먹기()

	Dog
	=========================
	~ name : String
	~ breed : String
	~ color : String
	~ food : int = 0
	~ disk : String = "white"
	=========================
	~ bark(): void
	~ bite(): void
	~ feed(amount:int):void
	~ fill(amount:int):void
    ~ react():void
	~ printflyingDisk():void
*/

class Dog {
	String name;
	String breed;
	String color;
	int food = 0;
	String diskColor = "하양";

	void bark(){
		System.out.printf("멍멍\n강아지가 별로 좋아하지 않는 것 같아\n\n");
	}
	void bite(){
		System.out.printf("강아지가 원반을 꽉 물었어\n강아지가 무척 좋아하는 것 같아\n\n");
	}
	
	void feed(int amount){
		System.out.println("강아지가 사료를 먹고 있어");
		printCmd("-",amount);
		if(isPositive(amount)){
			if(amount <= food){
				food -= amount;
			} else {
				System.out.printf("사료가 부족한 것 같아 \n채워주자 \n");
			}
		}
		printInfo();
	}
	void fill(int amount){
	    System.out.println("주인이 사료를 채우고 있어");
	    printCmd("+",amount);
	    if(isPositive(amount)){
	        if(amount + food <= 100){
			food += amount;
	        } else {
	            System.out.printf("사료가 넘칠 것 같아 \n강아지가 먹을 때까지 기다리자\n");
	        }
	    }
		printInfo();
	}
	public String toString(){
		return "현재 사료량: " + food + "\n\n";
	}
	void printInfo(){
	    System.out.printf(toString());
	}
	void printCmd(String symbol, int amount){
	    System.out.printf("사료: %d %s %d \n", food, symbol, amount);
	}
	boolean isPositive(int amount){
	    boolean result = amount > 0;
	    if(!result){
	        System.out.println("0 이상의 숫자를 써주세요");
	    }
	    return result;
	}
	void printFlyingDisk(){
	    System.out.printf("%s 원반을 던졌다\n", diskColor);
	}
	void react(){
		printFlyingDisk();
		if(diskColor == "하양"){
			bite();
		} else {
			bark();
		}
	}
}
public class Quiz2 {
	public static void main(String[] args) {
		Dog d = new Dog();
		d.name = "황구";
		d.breed = "시바견";
		d.color = "노랑";
		d.food = 100;

		d.printInfo();

		d.feed(50);
		d.fill(30);
		d.feed(-10);
		d.fill(-10);
		d.feed(90);
		d.fill(30);
		
		System.out.println("강아지는 하얀 원반을 좋아해\n");

		d.react();

		d.diskColor = "검정";
		
		d.react();
	}
}

Quiz3. 은행 계좌를 나타내는 BankAccount 클래스를 입력하고 다양한 실험을 하여 보자.

BankAccount는 잔고를 나타내는 정수형 멤버 변수(balance)를 가지고 있고 예금을 인출하는 메소드( withdraw)와 예금을 입금하는 메소드(deposit), 현재의 잔고를 반환하는 메소드(getBalance), 현재 잔액에 대하여 연 7.5% 의 이자를 계산하여 추가하는 메소드(addlnterest) 를 가지고 있다.

/*
===========================================
	BankAccount
===========================================
 ~ balance : int
===========================================
 ~ deposit(amount:int):void
 ~ withdraw(amount:int):void
 ~ getBalance():int
 ~ addInterest(year:int):void
===========================================	
*/

class BankAccount{
	int balance;
	void withdraw(int amount){		
		// balance withdraw (amount) M
		printInfo(amount, "인출");
		if(isPositive(amount)){
			balance -= amount;
			printBalance();
		} 
	}
	void deposit(int amount){		
		// balance deposit (amount) M
		printInfo(amount, "입금");
		if(isPositive(amount)){
			balance += amount;
			printBalance();
		} 
	}
	int getBalance(){			
		// return balance(int) M
		return balance;
	}
	void addInterest(int year){	
		// 7.5% per year M
		int interest = (int) (balance * 0.075 * year);
		printInfo(interest, "이자");
		balance += interest;
		printBalance();
	}
	void printBalance(){	
		// print balance M
		System.out.println("deposit: " + getBalance() + "원");
	}
	boolean isPositive(int amount){	
		// amount > 0 ? M
		boolean result = amount > 0;
		if(!result){
			System.out.println("입출액은 0보다 커야 합니다.");
		}
		return result;
	}
	void printInfo(int amount, String what){
		// command review M
		System.out.printf("----- %s: %d원 -----\n", what, amount);
	}
}
public class Quiz3 {
	public static void main(String[] args) {
		BankAccount ba = new BankAccount();
		ba.balance = 100000;

		ba.printBalance();

		ba.withdraw(50000);
		ba.deposit(70000);
		ba.withdraw(-50000);
		ba.deposit(-70000);

		ba.addInterest(10);
	}
}
profile
welcome

0개의 댓글