자바 - 7
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("자동차 시동을 걸었습니다.");
}
}