WEEK 2-2: Java 기초 문법

ensalada.de.pollo·2025년 4월 27일

be

목록 보기
4/44

변수

변수라는 것은 쉽게 말해서 공간입니다. 어떤 물체를 보관하기 위해서는 공간이 필요한데, 그 물체에 특성에 따라서 필요한 공간의 성질(모양, 크기 등)이 달라집니다. 그리고 그 공간들을 서로 구분하기 위해서는 공간에 이름도 붙여주어야 합니다. 또한 공간을 사용하기 위해서는 이전에 사용했던 지저분한 것들 또한 청소해주어야 합니다.

변수 파트에서 다룰 것들을 이렇게 설명해보았습니다.

  • 공간: 변수
  • 물체의 특성과 필요한 공간의 성질: 자료형
  • 공간의 이름: 변수명
  • 청소: 초기화

앞으로 이것들을 차차 설명해보겠습니다.

자료형

저장할 데이터 규격입니다. 위에서 비유한 바로는 어떤 물체를 담을 공간의 성질입니다. Java에서 주로 사용하는 변수들은 다음과 같습니다.

자료형특징범위크기
byte정수-128 ~ 1271 byte
short정수-32,768 ~ 32,7672 bytes
int정수-2,147,483,648 ~ 2,147,483,6474 bytes
long정수-9,233,372,036,854,775,808 ~9,233,372,036,854,775,8078 bytes
char문자unicode(0 ~ 65535)2 bytes
boolean참, 거짓(논리형)true, false1 byte
float실수약 소수점 6 ~ 7자리4 bytes
double실수약 소수점 15 ~ 17자리8 bytes

위에서 적은 크기라는 것은 변수 하나가 메모리를 몇 칸(한 칸당 1 byte) 차지하는 지를 의미합니다!

변수의 선언과 정의, 값의 할당

변수를 이름을 붙이고 "나 공간 어떻게 사용할거다!"라고 컴파일러에게 알려주는 것고 메모리를 할당받는 것을 선언과 정의(declaration & definition) 라고 합니다.

변수에 값을 넣는 행위를 할당(assign) 이라고 합니다. 그리고 정의된 변수에 값을 처음 할당하는 행위를 초기화라고 합니다. 초기화는 위에서 들었던 예시에서는 공간을 청소하는 것을 의미합니다

int  a; // 변수의 선언과 정의, int이므로 4 bytes 크기의 메모리 공간을 할당
a = 10; // 변수의 초기화(할당)
a = 20; // 이미 값이 있는 변수에 값을 재할당할 수도 있음

int b = 10; // 변수의 선언과 정의 동시에 변수를 초기화
a = b; // 어떤 변수에 다른 변수에 들어있는 값을 할당할 수도 있음

변수의 선언과 정의

선언과 정의는 사실 엄밀히 구분되지만, Java에서는 변수의 선언과 정의가 동시에 이루어집니다.
선언은 그냥 단순히 자료형과 변수명을 컴파일러에게 알려주는 행위이고, 정의는 변수에 메모리 공간을 할당하는 것을 의미합니다.

초기화를 왜 하는가?

어떤 공간을 처음 사용하기 전에 청소를 하는 것처럼, 메모리 공간에도 청소가 필요합니다. 메모리 공간에 존재하면서 사용하지 않는 값을 쓰레기 값이라고 하는데, 이 쓰레기 값을 청소하지 않는다면, 프로그램을 실행했을때 원하는 결과가 나오지 않거나 심하게는 오류가 발생할 수 있습니다.

형변환(casting)

어떤 변수의 자료형을 다른 자료형으로 변경하는 것입니다.

  • UpCasting: implicit하게 변환되므로 자동으로 형 변환이 됩니다. (작은 자료형 -> 큰 자료형)
  • DownCasting: explicit하게 변환되므로 자동으로 변환되지 않고 명시를 해주어야 합니다. (큰 자료형 -> 작은 자료형)

Java에서 형변환을 할 때에는 변환대상인 변수 a 앞에 변환하고자 하는 자료형 b를

(b) a;

와 같은 방식으로 붙여주면 됩니다.

double a = 10.1;
int b = (int) a; // double을 int로 형변환, 이 때 b에는 10이 저장됨

왜 DownCasting은 명시해주어야 하는가?

큰 자료형은 그만큼 더 큰 메모리 공간을 할당 받았습니다. 작은 메모리 공간으로 줄이려고 한다면 그 값 중 일부가 소실되거나 원치않는 결과가 나올 수 있으므로 자동으로 형변환되지 않으며 명시가 필요한 것입니다.

입력과 출력

입력

Java 프로그램에 입력을 하기 위해서는 Scanner라는 객체가 필요합니다. 이 객체를 통해서 Java 프로그램에 입력을 할 수 있습니다.

import java.util.Scanner; // Scanner 객체를 생성하기에 앞서 패키지 import가 필요

public class Example {
	public static void main(String[] args) {
    	Scanner scan = new Scanner(System.in); // 스캐너 객체 scan 생성
        String a = scan.nextLine(); // 문자열 데이터를 String 변수 a에 전달
        int b = scan.nextInt(); // 정수 데이터를 정수 변수 b에 전달
    }
}

위 예시에서 nextInt()는 공백을 기준으로 nextLine()은 개행문자(\n)를 기준으로 입력을 받습니다.

출력

Java에서 출력을 하는 메서드는 여러가지가 존재합니다.

  • print: 평범한 출력
  • println: 출력 마지막에 개행문자(\n)가 들어감
  • printf: c, c++에서 주로 사용하는 포맷팅 방식을 사용

보통 print와 println을 사용하며, printf는 필요에 따라 사용합니다.

public class Example {
	public static void main(String[] args) {
    	System.out.print("Hello world!");
        System.out.println("Hello world!");
    }
}

추가로, String 안에 double quote(")는 기본적으로 사용이 불가능합니다. 이를 사용하려면 escape character(\)를 사용하면 double quote를 사용할 수 있습니다.

public class Example {
	public static void main(String[] args) {
    	System.out.println("\"Hello world!\"");
        // 출력결과: "Hello world!"
    }
}

연산자

산술 연산자

기본적인 사칙연산에 사용되는 연산자들입니다.

  • a + b: a와 b를 더한 값
  • a - b: a에서 b를 뺀 값
  • a * b: a와 b를 곱한 값
  • a / b: a를 b로 나누었을 때의 몫
  • a % b: a를 b로 나누었을 때의 나머지

대입 연산자

대입 연산자는 "="를 사용합니다. 추가로, 여러가지 의미를 가지는 복합 대입 연산자가 존재하기도 합니다.

  • a += b: a에서 b를 더한 만큼 a에 대입(a = a + b)
  • a -= b: a에서 b를 뺀 만큼 a에 대입(a = a - b)
  • a *= b: a에서 b를 곱한 만큼 a에 대입(a = a * b)
  • a /= b: a를 b로 나눈 몫을 a에 대입(a = a / b)
  • a %= b: a를 b로 나눈 나머지를 a에 대입(a = a % b)

증감 연산자

단순히 1을 증가하거나 감소시킬 때는 증감 연산자를 사용합니다.

  • a++: a에 1 더한 만큼 a에 저장(a = a + 1)
  • a--: a에 1 뺀 만큼 a에 저장(a = a - 1)

전위 연산과 후위 연산

증감연산자는 피연산자의 앞에 위치하느냐 뒤에 위치하느냐에 따라서 작동 방식이 다릅니다.
피연산자의 앞에 위치하는 경우(++a), 이 식이 들어있는 코드를 실행시킬 때 a에 증감연산자를 먼저 적용한다는 뜻입니다.
반대로 피연산자의 뒤에 위치하는 경우(a++), 이 식이 들어있는 코드를 실행시킬 때 a에 증감연산자를 나중에 적용한다는 뜻입니다.

예를 들어서 현재 a의 값이 1이라고 가정했을 때,
1. System.out.println(++a);
2. System.out.println(a++);

1번 출력문의 결과는 2,
2번 출력문의 결과는 1입니다.
하지만 출력문 다음 줄로 넘어가게 되면 a값은 1번 2번 모두 2입니다.

비교 연산자

수학에서와 다르게 어떤 수를 다른 수와 비교할 때 "=="를 사용합니다.
비교 연산자를 사용한 결과는 boolean(참 또는 거짓)입니다.

  • a == b: a와 b가 같다면 true, 아니면 false
  • a != b: a와 b가 다르다면 true, 아니면 false
  • a < b: a가 b보다 작다면 true, 아니면 false
  • a <= b: a가 b보다 작거나 같다면 true, 아니면 false
  • a > b: a가 b보다 크다면 true, 아니면 false
  • a >= b: a가 b보다 크거나 같다면 true, 아니면 false

"=="는 기본형에서만 통한다.

참조형(String 등)은 메모리 주소를 비교하기 때문에 "==" 연산자가 아닌 .equals 메서드를 사용해야합니다.
예를 들어서
String a = "Hello";
String b = "Hello";
System.out.println(a == b);
System.out.println(a.equals(b));
라는 코드가 있다면
첫 번째 출력문은 false, 두 번째 출력문은 true가 출력되게 됩니다.
각 객체마다 주소가 다르므로 같은 문자열을 넣어도 주소를 비교하게 되니 false가 반환되는 것입니다.

논리 연산자

비교 연산자와 마찬가지로 논리 연산자의 결과 또한 boolean(참 또는 거짓)입니다.

  • !a: a가 true면 false, false라면 true
  • a && b: a와 b 모두 true이면 true, 아니라면 false
  • a || b: a 또는 b가 true이면 true, 둘 다 거짓이라면 false

연산자 우선 순위

  • 산술 연산자: 기본적인 대수법칙을 따릅니다.
  • 논리 연산자: 부정 연산자(!) > and 연산자(&&) > or 연산자(||)
  • 여러 개가 섞여있다면?: 산술 > 비교 > 논리 > 대입

조건문

if 문

코드를 작성하여도, 프로그램 흐름(입력 값 등등)에 따라서 실행되어야 할 코드, 실행되지 말아야 할 코드들이 있을 것입니다. 여기서 코드가 실행되어야 할 조건을 명시해주기 위해서 조건문을 사용할 수 있습니다.

if (조건문) {
	실행문;
}

이런 식으로 작성하게 되면 조건문이 참이 될 경우, 내부의 실행문이 실행됩니다.

if-else 문

만약, 조건문이 거짓인 경우에도 다른 실행문을 실행시키고 싶다! 라면 아래와 같이 작성하면 됩니다.

if (조건문) {
	실행문1;
} else {
	실행문2;
}

조건문이 참이라면 실행문1을, 조건문이 거짓이라면 실행문2를 실행합니다.

else-if 문

하지만 가위바위보 결과(승, 패, 무승부)처럼 여러 개의 조건이 발생할 수 있습니다. 이러한 경우에는 아래와 같이 작성할 수 있습니다.

if (조건문1) {
	실행문1;
} else if (조건문2) {
	실행문2;
} else if (조건문3) {
	실행문3;
} ... {
	실행문n;
} else {
	실행문m;
}

조건문1이 참이라면 실행문1을 실행시킵니다. 여기서 조건문1이 거짓이 되었다면 아래 조건문2를 검사하게 됩니다. 이러한 방식으로 여러 조건들을 탐색하고 맞는 조건이 있다면 그에 대응되는 실행문을 실행하게 됩니다.

위에서 참이 한 번 나왔으면 그걸로 땡이다

만약 조건문1도 참이고 조건문3도 참이라면 어떡하는가?라는 의문이 생길 수 있습니다.
이 때에는 조건문1과 조건문3 중 먼저 출현한 조건문에 대응되는 실행문만 실행시키게 됩니다.

switch 문

switch 문은 어떤 값을 비교합니다.
a를 놓고 비교했을 때, a가 만약 b에 해당된다면, 그에 대한 실행문, c에 해당된다면 그에 대한 실행문, ... 이런 방식으로 작동하게 됩니다.

switch (a) {
	case b:
    	실행문1;
        break;
    case c:
    	실행문2;
        break;
    ...
    default:
    	// 모든 case와 일치하지 않는 경우 실행합니다.
}

switch 문에서 break는 중요한 역할을 합니다. break를 생략하게 된다면 아래 코드가 전부 실행된다는 등의 큰 불상사가 발생할 수 있기 때문에 주의해야합니다.

반복문

for 문

for 문의 구조는 다음과 같습니다.

for (시작 조건; 종결 조건; 조건 변화 수식) {
	...
}

예를 들어서, 숫자를 1부터 차례대로 10까지 출력하는 구문을 작성해보겠습니다.

for (int i = 1; i <= 10; i++) {
	System.out.println(i); // 조건문에 사용한 변수 또한 사용 가능
}

continue와 break

아래와 같이 코드를 작성해보겠습니다.

for (int i = 1; i <= 10; i++) {
	if (i == 5) continue;
    if (i == 8) break;
    System.out.println(i);
}
  • if (i == 5) continue;: i가 5라면, 아래 코드를 실행하지 않고 다음 반복문으로 넘어갑니다.
  • if (i == 8) break;: i가 8이라면 반복문을 탈출합니다.

이런 식으로 반복 중에 원치 않는 반복이 있거나, 반복문을 탈출해야 할 때에는 continue와 break를 사용할 수 있습니다.

while 문

while 문의 구조는 아래와 같습니다.

while (조건문) {
	실행문;
}

조건문이 참인 경우 계속해서 실행문을 실행시킵니다. 반복 중에 조건문이 거짓이 된다면 반복을 끝냅니다.

무한루프를 주의하자!

while 문의 조건문에 들어가는 식에 사용되는 변수가 있을 것입니다. 만약, 이 변수를 실행문에서 조작하지 않는다면, 조건문이 항상 일정한 상태(참 또는 거짓)이 될 것입니다. 여기서 거짓이라면 단순히 실행이 되지 않는 반복문에 그치겠지만, 항상 참이 되는 경우에는 무한 번 반복하는 반복문이 될 것입니다.

do-while 문

while 문에서 조건문이 처음부터 거짓이라면 while 문은 실행되지 않을 것입니다.
여기서 무조건 한 번은 실행시키고 조건을 체크해야한다면 do-while문을 사용할 수 있습니다.

do {
	실행문;
} while (조건문);

여기서 실행문을 먼저 실행시키고 조건문을 그 다음에 확인하므로 무조건 한 번은 실행문을 실행시키게 됩니다.

배열

배열은 비슷한 성질의 데이터들을 하나로 묶는 것을 의미합니다.
한 반의 학생들을 관리한다고 했을 때, 배열을 사용하지 않는다면, 아래와 같이 학생의 이름을 저장해야합니다.

public class Example {
	public static void main(String[] args) {
    	String name1 = "철수";
        String name2 = "영희";
        ...
        String name30 = "민철";
    }
}

이런 식으로 저장을 해버린다면, 변수를 선언하기도 상당히 귀찮고, 나중에 명단에 문제가 생기는 등 중간에 불필요한 데이터가 들어가버린다면, 유지보수에도 문제가 발생합니다.
이러한 단점을 해결하기 위해서 배열을 사용합니다.

String name[] = new String[30]; // 길이가 30인 String 배열 생성

그리고 각각의 데이터를 넣을 때에는 다음과 같이 작성합니다.

name[0] = "철수";
name[1] = "영희";
...

여기서 대괄호 안에 들어가는 숫자를 인덱스라고 합니다. 0부터 시작하고 길이가 30이니 29가 최대 인덱스가 될 것입니다.
배열은 연속된 메모리 공간을 할당받기 때문에 길이를 처음에 한 번 정하면 고정이 됩니다. 만약, 여기서 name[30]을 부르게 된다면, 가능한 인덱스를 벗어났다는 오류 메세지(ArrayIndexOutOfBoundsException)를 마주할 수 있을 것입니다.

왜 0부터 시작인가?

사실 인덱스는, 배열의 시작점으로부터 얼마만큼 떨어져있는가를 의미합니다.
name[0]은 name이라는 배열로부터 0만큼 떨어져있고, name[1]은 name이라는 배열로부터 1만큼 떨어져있다는 것을 의미합니다. 사실 여기서 0과 1은 0 byte, 1 byte 만큼 떨어져있음을 의미하는 것은 아닙니다. 편의상 나타낸 숫자이고, 자료형에 따라서 실제 길이(offset)는 달라질 것입니다.

그리고 배열에 들어있는 값은 수정이 가능합니다.

name[0] = "철수";
name[0] = "영희";

위와 같은 행위가 가능하다는 것입니다.

자료 및 코드 출처: 스파르타 코딩클럽

0개의 댓글