백엔드/자바

자바 - 7

study_yeon 2023. 5. 4. 18:47

2023.05.04

1교시

* 접근제한자
public private protected default

* 출력법 : 명령프롬프트 / 콘솔

* CUI
character user interface

* GUI
graphic user interface

* 메인함수에서 객체화 하는 법
class는 이런 것을 하겠다는 그냥 선언이다
객체화해야 실체가 됨
 

● 지금까지 배운거 활용하여 실습


1.프로젝트 패키지 클래스 만들기 
- 프로젝트 2023.05.04, 패키지 menu, 클래스 MemuShowApp

2. 이러한 화면 출력 구조를 가진 프로그램을 만들어보자
----#메뉴#----  //sysout 활용
1. 커피           // 배열 활용
2. 라떼
3. 녹차
4. 종료
메뉴선택 해주세요 :

3. 메뉴를 키보드로부터 입력받기     //scanner 활용
* 선택한 메뉴에 따라 기능을 실행    // if else if 활용
- 1번 메뉴를 선택하면 '커피를 선택하셨습니다.'
- 2번 메뉴를 선택하면 '라떼를 선택하셨습니다.'
- 3번 메뉴를 선택하면 '녹차를 선택하셨습니다.'
- 4번 메뉴를 선택하면 '감사합니다.'
- 메뉴에 없는 선택을 할 경우 '메뉴에서 선택해주세요.'   // 루프 활용(do-while)


2교시 

4. 메뉴판을 고정하여 보여주고 싶다면 do의 위치 조정(상단으로 옮기기)
-> 스캐너는 1회만 만들면 됨
-> 반복문 때문에 계속 새로만들어지면 오류가 발생 함(키보드가 작동을 안함)- 빌려쓰기 기능 사용

5. 빠져나가는(종료) 기능 만들기
- while이 flase 가 되면 종료 
-> 현재 프로그램에서는 boolean menuEnd = false; // 메뉴종료가 기준이라 while이 true가 되면 종료 됨

 

● 코드 작성

package menu;

import java.util.Scanner;

public class MemuShowApp {

	public static void main(String[] args) {
		
// 1. 업그레이드 전
		
		Scanner sc = new Scanner(System.in);  // 키보드로부터 입력(문자열, 정수, 실수 가능)
		boolean menuEnd = false;
		String[] menus = {"커피", "라떼", "녹차", "종료"};
		// 메뉴판 작성
		do {
			System.out.println("------# 메뉴 # ------");
			System.out.println("1. " + menus[0]);
			System.out.println("2. " + menus[1]);
			System.out.println("3. " + menus[2]);
			System.out.println("4. " + menus[3]);
			System.out.println("커피, 라떼, 녹차, 종료 중에 하나를 선택하세요.(커피: 1, 라떼: 2, 녹차: 3, 종료: 4) : ");
			
			int choice = sc.nextInt();  // 지금부터(next) 정수로(int) 입력해주세요.
						
			if (choice == 1) {
				System.out.println("커피를 선택하셨습니다.");
			} else if (choice == 2) {
				System.out.println("라떼를 선택하셨습니다.");
			} else if (choice == 3) {
				System.out.println("녹차를 선택하셨습니다.");
			} else if (choice == 4) {
				System.out.println("감사합니다.");
				menuEnd = true;
			} else {
				System.out.println("메뉴에서 선택해주세요.");
			}
			System.out.println("");
			System.out.println("");
		} while (!menuEnd);  // !menuEnd == true, while == true이면 종료 / false이면 계속 실행 (불리언 사용해서 반대가 됨)
		
	}

}

 

* 공백만들기

System.out.println("");
System.out.println("");
아래와 동일 
System.out.print("\n\n");
->nextInt()와 못씀

 

- System.out.println("");
- System.out.print("\n");

 

* 스캐너 종료 위치
- 스캐너 종료 : sc.close();
- 에러가 날 수 있기 때문에 조정 필요

 

※ 콘솔창 x축 스크롤 고정

- 콘솔창에서 오른쪽 마우스 > Word Wrap 

※ 탐색기 바로 가기 

- Show in > System Explorer  
- 탐색기에서 찾은 파일을 메일로 보내기 등에 활용


3교시


* 하드코딩 
- 문자열, 숫자와 같은 코드가 고정으로 보이는 것
- 하나하나 타이핑 하는 방식

-> 1-2 교시에 하드코딩을 했음(보안에 취약한 프로그램임)

-> 개선(업그레이드)이 필요

●  만든 프로그램 업그레이드 예시


1. 메뉴 자동 수정(입력) 기능
▷ 메뉴를 배열로 활용

1. 동일한 종류이므로 배열로 개선하는 것이 낫다
String menuName = "커피";
String menuName1 = "라떼";
String menuName2 = "녹차";
String menuName3 = "종료";
2. 배열로 만들기(항목 추가)
String[] menuNames;
int[] menuPrices;
String[] menuOrigin; 
	
Menu() {   // 변수가 위에서 선언(null)되었기 때문에 초기화
	menuNames = new String[]{"커피", "라떼", "녹차", "종료"}; 
	menuPrices = new int[] {3000, 3500, 3000, -1};
	menuOrigin = new String[] {"콜롬비아", "서울", "보성", "종료"};
}

- 사용자 기본 생성자

- 초기화 -> 생성자함수

- 하드코딩을 안하려면 외부에서 데이터 값이 초기화 값으로 넘어와야 함.

 

▷ 루프  돌리기

2-1. 배열 활용
Menu(String[] menuItems, int[] menuPrices) {
	for(int i = 0; i < menuItems.length; i++) {
		this.menuNames[i] = menuItems[i];
		this.menuPrices[i] = menuPrices[i];
	}
}

2-2. 배열 활용 버전(향상된 for 활용)
protected void show() {
	System.out.println("------# 메뉴 # ------");
	for(var menuItem : this.menuNames) {
		System.out.println(menuItem);
	}
}

 

* 접근제어자

- private를 사용하면 다른 클래스에서 사용을 못하니까 오류가 뜸

-> public 또는 protected 활용하기

 

2. 잘 팔리는 메뉴를 상단에 배치

- 데이터를 누적하여 활용

● 디버그 
- 에러 모니터링 도구
- 상단의 벌레모양

아이콘

- 시간이 걸리며 콘솔이 송출 됨
- 중단점(breakpoint) : 문제의 줄을 더블클릭하면 해당 줄에서 중지가 됨

중단점

- 알림창은 다시 묻지않기 체크

디버그 실행 화면

- 디버그에서 이용하는 아이콘

 

● 업그레이드 하기

 

* Menu 클래스 만들기 - 데이터 클래스와 실행클래스 구분하기 

- 데이터 클래스에서 만들어 한번에 관리하기
- 생성자로 한번에 넘겨줌

1. 데이터 클래스
package menu;

public class Menu {
	// (업그레이드 용) 메뉴판 목록을 저장하는 변수 - 캡슐화 
	String[] menuNames;
	int[] menuPrices;
	String[] menuOrigin; 
	
	Menu() {   // 변수가 위에서 선언(null)되었기 때문에 초기화
		menuNames = new String[]{"커피", "라떼", "녹차", "종료"}; 
		menuPrices = new int[] {3000, 3500, 3000, -1};
		menuOrigin = new String[] {"콜롬비아", "서울", "보성", "종료"};
	}
	protected void show() {
		// 배열활용버전
		System.out.println("------# 메뉴 # ------");
		for(var menuItem : this.menuNames) {
			System.out.println(menuItem);
		}
		System.out.println("커피, 라떼, 녹차, 종료 중에 하나를 선택하세요.(커피: 1, 라떼: 2, 녹차: 3, 종료: 4) : ");
		
	}
	
}
2. 실행클래스
package menu;

import java.util.Scanner;

public class MemuShowApp {

	public static void main(String[] args) {			
		menuPan.show();  // 메뉴 보여주기
		
	}

}

* 생성한 내용을 메뉴판이라는 참조변수에 담아야함
->디버그를 통해 진행 방향 알 수 있음


4교시

* 배열 활용법

- 데이터형[ ] 변수 = {...};  // 변수선언, 초기화 한번에 하기 
- 데이터형[ ] 변수;           // 변수를 선언 후 초기화 하지 않으면 오류 
-> 초기화법

1. 배열의 개수만큼 대입해야함
구조 : 변수[1] = 값1
2. 변수 선언 후 초기화식으로 값을 대입하는 방법
구조 : 배열변수명 = new 데이터형[ ] {초기화 값};   //새로운 메모리 번지에 배열이 초기화 되어 생성


5교시

* 메소드 책 247p

* 메소드 선언
-  구성 : 선언부 / 실행부
-> 리턴타입, 메소드이름, 매개변수선언, 메소드 실행 블록으로 구성
- 선언부 = 메소드 시그니처(리턴타입, 메소드이름, 매개변수선언)

- 구조 : 리턴타입 메소드이름 ( [매개변수선언, ... ] ) {
            메소드 실행 블록(실행할 코드 작성)
             }

* 리턴값이 있으면 리턴타입을 선언부에 명시해줘야함

* 메소드 이름 
- 숫자로 시작 금지, 소문자 시작
- 특수문자 사용 안됨(_와 $는 예외)
- 카멜 표기법 (권장)

● 매개변수의 개수를 모르는 경우 


1. 매개변수를 배열 타입으로 선언
int result = sum(new int[ ] {1,2,3,4,5});
-> 배열을 만들어줘야해서 불편

배열을 이용한 덧셈 계산
	int[] data = {1, 2, 3};
	int retVal = calc.sum1(data);
	System.out.println("배열을 이용한 덧셈 계산 : " + retVal);		
	retVal = calc.sum1(new int[] {1, 2, 3, 4, 5});  // 선언은 1회만 앞의 int 생략
	System.out.println("배열을 이용한 덧셈 계산 : " + retVal);
여러값들의 덧셈
	public int sum1(int[] values) {
		int sum = 0;
		for(int i = 0; i < values.length; i++) {
			sum += values[i];  // 이전 합계(sum) + 현재 값(values[i])을 현재 sum변수에 저장
		}
		return sum;
	}

* 출력 값

배열을 이용한 덧셈 계산 : 6

배열을 이용한 덧셈 계산 : 15

 

2. ...(스프레드연산자) 사용(값의 목록만 넘겨줌)
int sum(int ... values) { }
- 메소드 호출 시 넘겨준 값의 수에 따라 자동으로 배열이 생성되고 매개값으로 사용 됨.

retVal = calc.sum2(1, 2, 3, 4, 5);
	System.out.println("암시배열을 이용한 덧셈계산 : " + retVal);
여러값들의 덧셈(스프레드연산자 ver)
	public int sum2(int ... values) {
		int sum = 0;
		for(int i = 0; i < values.length; i++) {
			sum += values[i];
		}
		return sum;
	}

* 출력값

암시배열을 이용한 덧셈계산 : 15

 

* 유틸클래스
- 내가 원하는 기능(메소드)을 모아둔 클래스
- 데이터는 존재하지 않음
- 클래스를 만드는 이유(순기능)
- 임포트 하여 사용

 

● 메소드 실습 (온오프계산기) - 새로운 패키지 만들기 250p
실행 클래스 CalculatorApp 
데이터 클래스 Calculator

* 계산기의 비즈니스로직 =(내가 컴퓨터로 해결하고 싶은 일)
1. 계산기 전원을 켠다.
2. 계산기 전원을 끈다.
3. 덧셈을 계산해본다.
4. 뺄셈을 계산해본다.
5. 곱셈을 계산해본다.
6. 나눗셈을 계산해본다.

 

● 1. 프로그램 제작 시 큰 틀을 먼저 제작하고

동작 확인
package calc;

public class CalculatorApp {

	public static void main(String[] args) {
		Calculator calc = new Calculator();  // 생성자(클래스 이름과 같음)
		// 계산기의 비즈니스로직 =(내가 컴퓨터로 해결하고 싶은 일)
		// 1. 계산기 전원을 켠다.
		calc.powerOn();
		// 2. 계산기 전원을 끈다.
		calc.powerOff();
		
		// 3. 덧셈을 계산해본다.
		result = calc.add(100, 200);
		// 4. 뺄셈을 계산해본다.
		result = calc.sub(100, 200);
		// 5. 곱셈을 계산해본다.
		result = calc.mul(100, 200);
		// 6. 나눗셈을 계산해본다.
		result = calc.div(100, 200);		
	}
	


}

6교시 

● 2. 세부기능을 추가 함

package calc;

public class CalculatorApp {

	public static void main(String[] args) {
		Calculator calc = new Calculator();  // 생성자(클래스 이름과 같음)
		// 계산기의 비즈니스로직 =(내가 컴퓨터로 해결하고 싶은 일)
		calc.powerOn();
		calc.powerOff();

		// 계산기의 계산결과 저장변수
		double result = 0.0;
		double x = 0.0;
		double y = 0.0;
		
		// 3. 덧셈을 계산해본다.
		x = 100.0;
		y = 200.0;
		result = calc.add(x, y);
		print(x, y, "+", result);
		// 4. 뺄셈을 계산해본다.
		result = calc.sub(x, y);
		print(x, y, "-", result);
		// 5. 곱셈을 계산해본다.
		result = calc.mul(x, y);
		print(x, y, "*", result);
		// 6. 나눗셈을 계산해본다.
		result = calc.div(x, y);
		print(x, y, "/", result);		
		}
		
	public static void print(
		double x, 
		double y, 
		String operator, 
		double result) {
		System.out.printf("%f %s %f = %f\n", x, operator, y, result);	
	}

}

- 계산은 결과값을 리턴해주는 것이 바람직.

- 상수보다는 변수를 이용하기

- 출력값 찍기

package calc;

public class Calculator {
	void powerOn() {
		System.out.println("계산기의 전원을 켰습니다.");
	}
	void powerOff() {
		System.out.println("계산기의 전원을 껐습니다.");
	}
	
	double add(double x, double y) {
		return x + y;
	}
	double sub(double x, double y) {
		return x - y;
	}
	double mul(double x, double y) {
		return x * y;
	}
	double div(double x, double y) {
		return x / y;
	}

}

- 데이터(기능)클래스 분리하기

출력 값


* static에서는  static메소드만 가능 
로컬에서 객체를 생성하고 그 객체의 메소드를 부르는 방법 (나중에 자세히)


 

7교시 

* 필드의 데이터를 읽고 쓰기만 하는 메소드 = 속성함수 = 프라퍼티(property)
get : 읽기. 메소드 호출 시 삽입된 데이터 값을 반환해줌 

set  : 저장하다. 사용자가 메소드를 호출 시 데이터 삽입

 

 return문

1. 리턴값이  있는 메소드 

return 리턴값;

- 리턴값은 리턴 타입이거나, 리턴타입으로 변환될 수 있어야 함.

 

* 리턴문 이후의 실행문

boolean isLeftGas() {     // 리턴값이 boolean인 메소드
	if (gas == 0) {
		System.out.println("가스가 없습니다.");
		return false;
	}
	System.out.println("가스가 남았습니다.");   
	return true;
}

- if문의 조건식이 false가 될 경우 정상적으로 다음 줄이 실행이 됨

- if문의 조건식이 true가 되면 '가스가 없습니다'가 출력되고 return false; 가 실행되어 메소드가 종료 됨

 

2. 리턴값이 없는 메소드 : void

return;

- 메소드 실행을 강제 종료시키는 역할

void run() {  // 자동차가 계속 달리는 것을 시뮬레이션
	Start();
	while (true) {
		
		if (gas > 0) {
			System.out.printf("달립니다.(gas 잔량: %d)\n", gas );
			gas = gas - 1;   // 자동차가 일정거리를 달리면 가스소비 : 1
		} else {  
			System.out.printf("멈춥니다.(gas 잔량: %d)\n", gas);
			return;   // run() 메소드 종료
		}
	}


● return 실습 - 256p

 

1. Car / CarApp 클래스 만들기

 

* 실행클래스

package car;

public class CarApp {

	public static void main(String[] args) {
		Car mycar = new Car();  // mycar 변수는 Car데이터타입 크기의 객체가 만들어진 힙의 주소를 저장한다 
		
		mycar.setGas(5);  // 생성자를 이용하는 경우 외에 초기화를 해야할 경우 사용

		boolean gasState = mycar.isLeftGas();
		if(gasState) {
			System.out.println("차를 출발합니다.");
			mycar.run();
		}
		
		if(mycar.isLeftGas()) {
			System.out.println("가스를 주입할 필요가 없습니다.");
		} else {  // 가스가 없는 경우
			System.out.println("가스를 주입해주세요.");
		}
	}

}

Car : 데이터타입


* 데이터클래스

package car;

public class Car {
//필드
	int gas;  // gas 없으면 자동차 운전 불가
    
// 생성자	
	Car() {
		gas = 50;
	}
	
// 메소드    
	// 가스를 보충한다.
	void setGas(int gas) {   // set 의미: 데이터 저장
		this.gas = gas;      // 리턴값이 필요 없다.-> gas 필드값 변경
	}
	// 가스가 남아 있는지 없는지 알려주는 함수
	boolean isLeftGas() {     // 리턴값이 boolean인 메소드
		if (gas == 0) {
			System.out.println("가스가 없습니다.");
			return false;
		}
		System.out.println("가스가 남았습니다.");   // if 안쓰는 이유는 주로 사용되는 부분이라(가스는 충전되어있는 경우가 많음)
		return true;
	}

	void run() {  // 자동차가 계속 달리는 것을 시뮬레이션(리턴값이 없는 메소드)
		Start();
		while (true) {
			
			if (gas > 0) {
				System.out.printf("달립니다.(gas 잔량: %d)\n", gas );
				gas = gas - 1;   // 자동차가 일정거리를 달리면 가스소비 : 1
			} else {  // gas가 0보다 작은 경우
				System.out.printf("멈춥니다.(gas 잔량: %d)\n", gas);
				return;   // 메소드의 종료를 명시화할 때
			}
		}
	}
	
	void Start() {
		System.out.println("자동차 시동을 걸었습니다.");
	}
}