Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

DD: Development Diary

[JAVA] 혼공자바 2주차_조건·반복, 참조 타입 본문

STUDY

[JAVA] 혼공자바 2주차_조건·반복, 참조 타입

찹쌀주 2024. 1. 14. 22:48

조건문과 반복문

조건문

C++과 유사하다고 생각했다. if문, else문, else if문이 있고, switch문을 활용할 수 있다. 

if(조건식A){
	실행문A
}
else if(조건식B){
	실행문B
}
else if(조건식C){
	실행문C
}
else{
	실행문D
}
실행문E
  1. 조건식A를 만족 => 실행문A  -> 실행문E 실행
  2. 조건식A 불만족, 조건식B 만족 => 실행문 B -> 실행문E 실행
  3. 조건식A, B 불만족, 조건식C 만족 => 실행문C -> 실행문E 실행
  4. 조건식A, B, C 불만족 => 실행문D -> 실행문E 실행

조건식에 따라서 위와 같은 실행 결과가 나온다. 변수 하나의 값에 따른 결과를 실행, 출력하고 싶다면 switch문을 사용하면 된다. switch문 역시 C++과 유사한 문법을 사용했다. 각 case의 실행문이 끝나면 break를 꼭 입력해주어야 한다.

추가

예제 코드를 통해서 Math class로 난수 추출하는 방법을 알아냈다. 기존과 같이 프로젝트 module 파일에 다음의 코드를 추가해준다면 별도 import 없이 사용할 수 있는 것 같다. 혹시 모르니 requires java.se를 지우고도 실험해본다! 잘 된다.

module chap04 {
	requires java.se;
}

결론: Math 클래스는 별도 import나 module-info 파일 설정 없이도 사용할 수 있다.

확인 문제 (교재 코드는 올리지 않음. 문제는 교재 참고!)

  1. 조건문의 종류 - if문, switch문
  2. ① if문은 조건식의 결과에 따라 실행 흐름을 달리할 수 있다. ( O )
    ② if문은 조건식이 true이면 블록을 실행하고 false이면 블록을 실행하지 않는다. ( O )
    ③ if문의 블록 내부에는 또 다른 if문을 사용할 수 있다. ( O )
    ④ switch문에서 사용할 수 있는 변수의 타입은 int만 가능하다. ( X ) - char, String도 가능한 예시로 나와있다.
  3.  등급은 B입니다.
    - 조건식을 만족할 때에만 if문 블럭 내 실행문을 실행한다.
  4. 어떤 혜택을 원하세요?
    우수 회원 혜택을 받으실 수 있습니다.

    일반 회원 혜택을 받으실 수 있습니다.
    감사합니다.
    - switch문을 사용할 때 break문을 만날 때까지 이하 실행문을 모두 실행한다.

⑤⑥⑦⑧⑨ 

 

반복문

반복문 역시 C++과 유사했다. for문/while문/do-while이 존재했다. for문은 반복 횟수를 알고 있을 때, while문은 조건에 따라 반복할 때 주로 사용한다.

while문은 조건식이 true일 때에만 실행문을 반복하기 때문에 한 번은 반드시 실행하도록 하고싶다면 조건식이 실행문 뒤에 위치해 한 번은 실행하게 되는 do-while문을 사용해야 한다. while과 do-while은 실행문과 조건문의 위치만 다르고 구성과 역할은 동일하다!

break와 continue는 반복문에서 빼먹을 수 없는 존재! 반복문을 아예 그만두고 탈출하고 싶다면 break문을, 다음 순서로 바로 넘어가도록 하고 싶다면(일부 값에 대해서만 실행문을 생략하고 싶다면) continue문을 사용하면 된다.

확인 문제

1. 반복문의 종류: for문, while문, do-while문

2. for문을 이용해 1~100의 정수 중 3의 배수의 총합을 구하는 코드

package sec02.test02;

public class test02 {
	public static void main(String args[]) {
		int sum = 0;
		for(int i = 1; i < 100; i++) {
			if(i % 3 == 0) {
				sum += i;
			}
		}
		System.out.println(sum);
	}
}

- for문과 %연산자를 사용해 3의 배수에 대해서만 sum에 더해주었다. 정답은 1683

3. while문과 Math.random() 메소드를 이용해 2개의 주사위를 던졌을 때 나오는 눈을 (눈1, 눈2) 형식으로 출력하고 눈의 합이 5가 아니면 계속, 5이면 멈춤

package sec02.test03;

public class test03 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int dice1;
		int dice2;
		do {
			dice1 = (int)(Math.random() * 6) + 1;
			dice2 = (int)(Math.random() * 6) + 1;
			System.out.printf("(%d, %d)\n", dice1, dice2);			
		}
		while(dice1 + dice2 != 5);
	}

}

- do-while 문을 사용해 합이 5가 되더라도 한 번은 출력하도록 하였다.

4. 중첩 for문을 이용해 4x + 5y = 60의 모든 해를 구해서 (x, y) 형태로 출력해보기 (단, x와 y는 10 이하의 자연수)

package sec02.test04;

public class test04 {
	public static void main(String[] args) {
		int i, j;
		for(i = 1; i < 11; i++) {
			for(j = 1; j < 11; j++) {
				if(4 * i + 5 * j == 60) {
					System.out.printf("(%d, %d)\n", i, j);
				}
			}
		}
	}
}

- 10이하의 자연수이므로 1에서 10까지 반복할 수 있도록 for 반복문의 조건식을 달아준다. 

 

참조 타입

참조 타임과 참조 변수

  • 기본 타입: 일반적인 변수로 정수(int), 실수(float, double), 문자(char) 등을 포함
  • 참조 타입: 객체의 번지를 저장하는 타입의 변수로, String과 배열(array)이 대표적

객체의 번지수와 참조의 개념을 이해하기 위해서 다음의 그림을 참고할 수 있다. 바이트 코드 파일-기계어 사이의 번역기 JVM의 메모리 사용 영역

크게 메소드 영역, 힙 영역, JVM 스택으로 구분된다.

메소드 영역

이번 파트에서는 자주 등장하지 않지만 메소드 영역에서 어떤 일을 하는지 알기 어려워 좀 더 찾아보았다.

메소드 영역은 클래스 영역, static(정적) 영역이라고도 불린다고 한다. 

JVM 내부의 클래스로더로 바이트코드 (~.class)들을 읽고, 전역변수나 static으로 선언되는 변수, 상수 등을 저장한다.

JVM이 시작할 때 생성되고, 종료될 때까지 유지된다. 

힙 영역

객체가 생성되는 메모리 영역

객체를 만들면 이곳에 저장된다.

JVM 스택 영역

기본 자료형을 생성할 때 저장하는 영역

참조 변수를 생성하면 이곳에 새로운 변수가 생성되고, 힙 영역에 생성된 객체를 참조하는 형식으로 작동한다. 바이트코드에서 기본 타입 변수와 참조 타입 변수를 각각 생성했을 때 JVM 메모리 영역 내부에서는 어떻게 생성되는지 다음 그림으 이해할 수 있다. 

Null

변수가 힙 영역의 객체를 참조하지 않도록 하고싶다면 null(널) 값을 사용할 수 있다. 힙 영역을 참조하지 않기 때문에 참조 타입 변수를 생성해도 기본 타입 변수처럼 stack 영역에서 생성되어 저장된다. 초기값으로 지정할 수도 있고, 기존에 값을 참조하고 있었던 변수에 null을 대입해줄 수도 있다.

new 연산자

String 타입 변수를 생성할 때는 다음과 같이 문자열 리터럴과 new 연산자로 생성할 수 있다.

String name1 = "문자열"; // 문자열 리터럴 사용
String name2 = "문자열"; // 문자열 리터럴 사용
String name3 = new String("문자열"); // new 연산자 사용

문자열 리터럴을 사용한 두 개의 문자열은 서로 동일한 객체를 참조한다. 한편, new 연산자를 사용하면 힙 영역에 새로운 객체를 생성해 위의 예시에서는 name3만 다른 객체를 참조하고 있게 된다.

배열

  • 배열: 같은 타입의 데이터를 연속된 공간에 나열하고, 각 데이터에 인덱스를 부여한 자료구조

한 번 생성된 배열은 길이를 바꿀 수 없기 때문에 신중하게 생성해야 한다. 또한 위에 제시된 것처럼 같은 타입의 데이터로만 생성할 수 있다. 배열 선언은 다음의 두 가지 방식 모두 사용할 수 있다.

int[] scores;
int scores[];

배열을 생성할 때에는 위의 선언과 함께 중괄호 안에 값을 담아 정의한다.

int[] scores = {91, 92, 93, 44, 89};

※주의할 점※

배열 변수를 이미 선언한 후에는 다른 실행문에서 중괄호를 사용한 배열 생성을 할 수 없다. 

또한 매개변수로 새로운 배열을 사용하고 싶을 때에도 중괄호를 사용할 수 없다.

이 두 가지 상황에는 반드시 new 연산자를 사용해야 한다.

int scores[];
scores = {91, 92, 93, 94, 44, 81}; // 컴파일 에러

int scores[];
scores = new int[] {91, 92, 93, 94,44, 81};

 

명령문 해석

우리가 새로운 바이트코드 파일을 생성할 때마다 입력해주는 아래 명령문을 해석해보기도 했다.

public static void main(String[] args) {~}

JVM은 길이가 0인 String 배열 args를 먼저 생성하고, 이후에 main() 메소드를 호출한다고 한다.

Argument(전달인자)는 메소드 호출시 전달되는 값으로, 교재 187쪽과 같이 [Run] - [Run Configurations] - [Arguments] 탭에서 [Program Arguments] 창에 값을 추가해 변경할 수도 있고, 아래 캡쳐화면처럼 cmd에서 코드로 동일한 결과를 출력할 수도 있다.

 

다차원 배열

다차원 배열은 배열 변수 하나가 힙 영역의 배열 하나를 참조하고, 그 배열들이 각각의 배열을 참조해서 행마다 열의 배열 길이가 모두 다를 수도 있다. 바깥 배열(1번)의 각각 데이터가 하나의 배열을 참조하고 있다는 설명에 이해가 빨리 됐다.

향상된 for문

처음 보는 개념이다! 자바에서만 지원하는 것 같기도 하다. 다음과 같이 사용할 수 있다.

for (int score : scores){
	System.out.println(score);
}

scores 배열의 데이터를 하나씩 뽑아 score 변수에 대입하고 하나씩 출력하는 코드이다.

열거 타입

열거 타입: 한정된 열거 상수 중에서 하나의 상수를 저장하는 타입

아래와 같은 코드를 통해서 열거 상수와 타입을 정의할 수 있다. 

public enum Week {~}

Week가 열거 타입의 이름이고, 이를 이용해서 '열거 타입 변수'를 선언 및 생성할 수 있다.

여기서 열거 '상수'는 일반적인 변수와 달리 메소드 영역에 생성되고, 힙 영역에 생성된 각각의 열거 객체를 참조한다. 

기본 미션

기본 미션은 142p swith 실습예제 출력 확인하기! random() 함수로 임의의 난수가 생성됐는데, 첫번째 결과는 1이었다.

선택 미션

선택한 번호에 따라 기능을 수행하도록 실행문을 구성했는데, 각각의 기능은 다음과 같이 작성했다!

if(selectNo == 1) {
    System.out.print("학생수> ");
    studentNum = Integer.parseInt(scanner.nextLine());
    scores = new int[studentNum];

첫번째 기능, 학생수 입력받기

else if(selectNo == 2) {
        for(int i = 0; i < studentNum; i++) {
            System.out.printf("scores[%d]> ", i);
            scores[i] = Integer.parseInt(scanner.nextLine());
        }
}

두번째 기능, 학생들의 점수를 배열로 입력받기. 이걸 위해서 학생수를 입력 받은 뒤 점수 배열 길이를 초기화해주었다.

else if(selectNo == 3) {
    for(int i = 0; i < studentNum; i++) {
        System.out.printf("scores[%d]> %d\n", i, scores[i]);
    }
}

세번째 기능, 학생들 점수 출력하기

else if(selectNo == 4) {
    int scoreMax = 0;
    int scoreSum = 0;
    for(int score : scores) {
        scoreMax = Math.max(score, scoreMax);
        scoreSum += score;
    }
    System.out.println("최고 점수: "+scoreMax);
    System.out.println("평균 점수: "+((double)scoreSum/(double)studentNum));
}

네번째 기능, 최고 점수와 평균 점수 구하기. Math.max 함수와 향상된 for문을 사용한 점이 특히 재미있었다. 다른 언어로는 구현해보지 못한 코드라 그런 것 같다. 

한가지 유의할 점은 평균 점수를 구할 때 연산이 다 끝난 뒤에 (double) 강제 변환을 해주면 당연히! 소수점이 0만 나온다. 나는 이걸 까먹고 처음에 (int)/(int) 결과를 (double)로 강제변환해주었다...🫠

결과창은 위처럼 나온다.

 

2주차 후기

지난주부터 벼르고 있던 프로젝트가 끝나서 이제 정말 시간 조금씩 모아서 내 공부를 할 수 있게 되었다... 정말 뿌듯하다! 그리고 지난 블로그 내용을 다시 돌아보니 너무너무 부족해서(물론 이번에도 부족하지만ㅎㅎ) 1주차 우수혼공단 분들의 게시글을 요리조리 보면서 참고했다. 확인 문제도 조금씩 풀어보고 예제도 해보고, 더 많이 배우는 방법을 알아가고 있다!

새롭게 알아낸 혼공단의 장점! 다른 사람은 어떻게 공부하고 게시글을 올리는지 가까이서 보며 참고할 수 있다! 떨어져 있어도 같이 공부하는 사람이 있다는 건 정말 힘이 되는 것 같다. 꼼꼼히 읽어주시는 혼족장님 감사합니다~!

'STUDY' 카테고리의 다른 글

[JAVA] 혼공자바 1주차_개발 환경 구축부터 데이터 타입까지  (2) 2024.01.07
231110 Daily English  (0) 2023.11.10
20231109 daily English  (0) 2023.11.09