방송대 Java프로그래밍 2강: 자료형 선택과 제어 흐름
Java 문법은 기호를 외우는 목록처럼 보이지만 실제 코딩에서는 연속된 판단이다. 이름이 문법에 맞는지, 값이 어디에 얼마나 오래 저장되는지, 변환이 허용되는지, 다음에 실행할 문장이 무엇인지 차례로 결정해야 한다. 이 글은 식별자부터 자료형·연산자·제어문까지를 “코드를 읽고 결과를 예측하는 규칙”으로 연결한다.
코드 한 줄은 이름·저장·계산·흐름의 규칙을 동시에 따른다
int total = score1 + score2;라는 짧은 문장에도 여러 판단이 숨어 있다. total이 올바른 식별자인지, int가 값을 담을 수 있는지, 두 피연산자에 +를 적용할 수 있는지, 선언된 변수를 어디까지 사용할 수 있는지를 모두 확인해야 한다. 여기에 if나 for가 붙으면 실행 순서까지 추적해야 한다.
따라서 오류를 만났을 때 문법 전체를 다시 외우기보다 질문을 분리하는 편이 낫다. 컴파일 전에 이름과 자료형을 확인하고, 실행 결과가 예상과 다르면 연산 순서와 제어 흐름을 따라간다. 이 구분은 긴 프로그램에서도 오류가 생긴 층을 빠르게 찾게 해 준다.
판단 순서: 이름이 가능한가 → 변수의 종류와 범위는 무엇인가 → 값과 연산의 자료형이 맞는가 → 어느 문장이 실행되는가를 차례로 묻는다.
클래스 경계가 달라도 객체의 상태와 동작은 함께 읽는다
강의자료의 성적 처리 예제는 두 가지 구성을 비교한다. 첫 번째는 점수와 기능을 가진 Grade 클래스와 실행을 담당하는 GradeOutput 클래스를 분리한다. 두 번째는 필드, 메소드와 main()을 하나의 GradeOutput 클래스에 둔다. 파일 배치는 달라도 객체마다 영어·수학 점수를 저장하고, 메소드로 입력과 합계 출력을 수행한다는 핵심은 같다.
다음은 두 클래스 구성을 학습용으로 간결하게 다시 작성한 코드다. g1과 g2는 같은 클래스에서 생성되지만 각 객체의 english와 math는 별도 상태다. 실행 결과는 차례로 175와 160이다.
class Grade {
int english;
int math;
void setScores(int englishScore, int mathScore) {
english = englishScore;
math = mathScore;
}
void printTotal() {
System.out.println(english + math);
}
}
public class GradeOutput {
public static void main(String[] args) {
Grade g1 = new Grade();
Grade g2 = new Grade();
g1.setScores(90, 85);
g2.setScores(80, 80);
g1.printTotal();
g2.printTotal();
}
}
main()은 실행을 시작하고 객체를 조립하며, Grade는 성적 상태와 관련 동작을 묶는다. 한 클래스에 모두 넣는 것도 문법상 가능하지만, 코드를 읽을 때는 어떤 클래스가 데이터를 표현하고 어떤 클래스가 실행을 시작하는지 구분해야 한다.
식별자는 다섯 가지 질문으로 판정한다
식별자는 프로그래머가 클래스, 변수, 메소드와 레이블에 붙이는 이름이다. Java는 대소문자를 구분하고 식별자 길이를 제한하지 않는다. 영문 대소문자, 한글, 숫자, 밑줄과 달러 기호를 사용할 수 있지만 숫자로 시작할 수 없고, 키워드와 true·false·null은 이름으로 쓸 수 없다.
| 판정 질문 | 가능한 예 | 불가능한 예 | 이유 |
|---|---|---|---|
| 첫 글자가 허용되는가? | score2 | 2score | 숫자는 첫 글자에 올 수 없다. |
| 허용 문자만 있는가? | my_score | my-score | 하이픈은 뺄셈 연산자로 해석된다. |
| 예약된 단어인가? | className | class | 키워드는 정해진 문법 의미로만 사용한다. |
| 리터럴 이름인가? | isTrue | true | 논리·널 리터럴은 식별자가 아니다. |
| 대소문자가 일치하는가? | total | Total을 같은 변수로 사용 | 서로 다른 식별자로 취급된다. |
문법을 통과한 이름이 곧 좋은 이름은 아니다. 관례상 클래스 이름은 GradeBook처럼 대문자로 시작하고, 변수와 메소드 이름은 totalScore처럼 소문자로 시작한다. 상수는 MAX_SCORE처럼 대문자와 밑줄로 구분한다. 관례는 컴파일 조건이 아니라 사람이 역할을 빠르게 알아보게 하는 약속이다.
변수의 종류는 선언 위치와 static 여부로 가른다
변수를 분류할 때 이름보다 선언 위치를 먼저 본다. 클래스 몸체에 선언된 데이터 필드는 객체마다 따로 가지는 인스턴스 변수이거나, static을 붙여 같은 클래스의 객체들이 공유하는 클래스 변수다. 메소드나 블록 안에서 선언하면 지역 변수이고, 메소드 호출 때 전달받는 선언은 파라미터다.
| 종류 | 판정 기준 | 수명·공유 관계 | 주의점 |
|---|---|---|---|
| 인스턴스 변수 | 클래스 몸체의 non-static 필드 | 객체마다 별도의 값 | 어느 객체의 필드인지 참조가 필요하다. |
| 클래스 변수 | 클래스 몸체의 static 필드 | 클래스에 하나, 동종 객체가 공유 | 객체별 상태로 오해하면 값 변화가 예상과 달라진다. |
| 지역 변수 | 메소드 또는 블록 내부 선언 | 해당 블록이 끝날 때까지 유효 | 사용하기 전에 값을 초기화해야 한다. |
| 파라미터 | 메소드 선언부의 입력 변수 | 호출 동안 전달된 값을 보관 | 지역 변수처럼 메소드 범위 안에서 사용한다. |
지역 변수와 파라미터 선언에는 접근 제어자를 붙이지 않는다. 반면 데이터 필드는 클래스 외부에서 사용할 수 있는 범위를 public, protected, private 등의 접근 제어자로 정할 수 있다. 범위와 접근 권한은 다른 문제이므로 함께 섞지 않는다.
자료형은 값의 종류·범위·허용 연산을 함께 결정한다
변수를 선언할 때 자료형을 적는 이유는 저장될 값의 종류를 정하기 위해서다. 메소드에서는 파라미터와 반환값의 자료형도 선언한다. 자료형에 따라 표현 범위와 적용 가능한 연산이 달라지므로 “숫자니까 아무 형이나 된다”라고 판단하면 안 된다.
| 분류 | 자료형 | 강의자료 기준 크기 | 판정 기준 |
|---|---|---|---|
| 논리 | boolean | 1바이트 | true 또는 false |
| 문자 | char | 2바이트 | 16비트 Unicode 문자 한 개 |
| 정수 | byte, short, int, long | 1, 2, 4, 8바이트 | 필요한 정수 범위에 맞춰 선택 |
| 실수 | float, double | 4, 8바이트 | 소수와 필요한 정밀도에 맞춰 선택 |
이 표는 강의자료의 학습용 크기 표기를 따른다. 시험에서는 각 기본형의 분류와 크기, 정수형의 표현 범위를 연결해 기억하되 자료형 선택은 실제 값의 범위와 연산 목적을 기준으로 판단한다.
리터럴의 접두사·접미사는 값의 해석 방식을 바꾼다
리터럴은 소스 코드에 직접 적는 실제 데이터 값이다. 정수 리터럴은 기본적으로 int로 해석되며 L이나 l을 붙이면 long이 된다. 0b11010, 032, 0x1a는 각각 2진수·8진수·16진수 표기지만 모두 십진수 26과 같은 값을 나타낸다.
소수점이 있는 리터럴은 기본적으로 double이며 f나 F를 붙이면 float이다. 문자 리터럴은 작은따옴표로 한 문자를 표현한다. 예를 들어 'A', '\u0041', (char)65는 같은 문자를 뜻하고, '가'와 '\uAC00'도 같은 문자를 뜻한다.
final을 붙인 변수는 한 번 값이 할당되면 다시 바꿀 수 없는 상수로 사용한다. 선언과 동시에 초기화하거나 이후 한 번만 값을 넣을 수 있지만, 이미 값이 정해진 뒤 재대입하면 컴파일 오류가 난다.
기본형은 값을 복사하고 참조형은 가리키는 대상을 공유할 수 있다
기본형 변수는 저장 공간에 값 자체를 보관한다. 참조형 변수는 객체를 가리키는 참조 값을 보관하며 클래스, 배열, 인터페이스와 열거형 등이 대표적이다. 이 차이를 가장 쉽게 확인하는 방법은 대입 뒤 한쪽 값을 바꾸어 보는 것이다.
int first = 7;
int second = first;
second = 9;
System.out.println(first); // 7
int[] original = { 7 };
int[] alias = original;
alias[0] = 9;
System.out.println(original[0]); // 9
second에는 정수값 7이 복사되므로 이후 변경이 first에 영향을 주지 않는다. 반면 alias와 original은 같은 배열 객체를 가리키므로 한 참조를 통해 원소를 바꾸면 다른 참조로도 바뀐 값이 보인다. “참조형 변수 안에 객체 전체가 들어 있다”는 생각은 이 현상을 설명하지 못한다.
형변환은 크기보다 정보 손실 가능성을 먼저 본다
묵시적 형변환은 대입이나 수식에서 변환을 코드로 쓰지 않아도 자동으로 일어나는 경우다. 강의자료는 byte → short → int → long → float → double의 흐름을 제시한다. 반대 방향처럼 더 작은 표현 범위로 바꾸려면 (자료형) 피연산자를 쓰는 명시적 형변환이 필요하다.
int count = 25;
double exactEnough = count; // int에서 double로 자동 변환
double average = 25.8;
int truncated = (int) average; // 명시적 변환, 결과는 25
float ratio = (float) 5.5; // double 리터럴을 float으로 변환
float direct = 5.5F; // 처음부터 float 리터럴
명시적 형변환은 값이 안전하게 보존된다는 보증이 아니라 개발자가 변환을 요청했다는 표시다. 25.8을 int로 바꾸면 소수 부분이 사라진다. 또한 자동 변환이라도 정수의 큰 값을 실수형으로 옮길 때 정밀도가 달라질 수 있으므로 “자동이면 정보가 절대 손실되지 않는다”라고 일반화하면 안 된다.
형변환 판단: 목표 자료형이 값을 표현할 수 있는지 확인하고, 축소 변환이면 캐스트 필요 여부와 잘림·정밀도 변화를 함께 점검한다.
연산자는 종류뿐 아니라 우선순위와 적용 방향을 가진다
Java 연산자는 산술, 비교, 논리, 비트, 대입과 형변환 등으로 나뉜다. 같은 기호도 피연산자의 자료형에 따라 결과가 달라질 수 있고, 여러 연산자가 한 수식에 있으면 우선순위와 결합 방향에 따라 계산 순서가 정해진다. 의도가 헷갈리면 괄호로 순서를 명시하는 것이 가장 안전하다.
| 판단 목적 | 대표 연산자 | 결과를 읽는 질문 |
|---|---|---|
| 값 계산 | + - * / % ++ -- | 피연산자 자료형과 계산 순서는 무엇인가? |
| 관계 판정 | > >= < <= == != instanceof | 결과가 boolean이며 무엇을 비교하는가? |
| 조건 결합 | && || ! ?: | 어떤 조건을 결합하거나 반전하는가? |
| 비트 계산 | & | ^ ~ << >> >>> | 논리값이 아니라 비트 단위 연산인가? |
| 값 저장 | = += -= *= /= %= 등 | 계산 뒤 어느 변수에 결과를 대입하는가? |
| 자료형 변환 | (자료형) | 변환으로 범위나 정밀도가 달라지는가? |
문장은 수식문, 변수 선언문과 제어문으로 나눌 수 있다. 여러 문장을 중괄호로 묶으면 블록문이 되고, 레이블문·예외처리문·동기화문도 Java 문장의 형태다. 제어문은 기본적인 위에서 아래로의 실행 순서를 바꾼다.
명령행 매개변수는 문자열 배열의 인덱스로 읽는다
프로그램을 실행할 때 클래스 이름 뒤에 적은 값은 main()의 String[] args에 문자열로 전달된다. 배열 인덱스는 0부터 시작하므로 첫 번째 인수는 args[0], 두 번째는 args[1]이다.
public class Main {
public static void main(String[] args) {
System.out.println(args[0] + ", " + args[1]);
}
}
java Main test1 test2로 실행하면 test1, test2가 출력된다. 인수를 하나만 전달하면서 args[1]을 읽으면 두 번째 원소가 없으므로 실행 오류가 발생한다. 따라서 실전 코드에서는 필요한 인수 개수를 먼저 확인해야 한다.
선택문은 조건뿐 아니라 결합 규칙과 중단 지점을 확인한다
if는 boolean 수식이 참일 때 문장을 실행하고, if-else는 두 경로 중 하나를 선택한다. 중괄호가 없는 중첩문에서는 else가 아직 짝이 없는 가장 가까운 if와 결합한다. 들여쓰기는 사람의 의도를 보여 줄 뿐 문법적 결합을 바꾸지 않는다.
int a = 2;
int b = 2;
if (a == 1)
if (b == 2)
System.out.println("both");
else
System.out.println("a only");
이 코드에서 else는 안쪽 if (b == 2)의 짝이다. 그러나 바깥 조건 a == 1이 거짓이므로 내부 문장 전체를 건너뛰고 아무것도 출력하지 않는다. 원하는 구조를 분명히 하려면 중괄호로 블록을 표시한다.
switch는 하나의 값에 대해 여러 case를 비교한다. 일치한 case부터 실행하며 break를 만나거나 switch가 끝날 때까지 다음 문장으로 계속 내려간다. 여러 case가 같은 동작을 공유하도록 의도적으로 이어 둘 수 있지만, break 누락은 예상하지 못한 fall-through를 만들 수 있다.
반복과 점프는 다음에 실행할 위치를 추적해야 이해된다
반복문에는 for, while, do-while이 있다. 향상된 for문은 배열이나 컬렉션의 원소를 처음부터 끝까지 차례로 다룰 때 편리하다. 인덱스 자체가 필요하거나 일부 위치만 선택해야 한다면 일반 for문이 더 적합할 수 있다.
break는 가장 가까운 반복문이나 switch를 끝내고 바깥으로 나간다. continue는 반복문 전체를 끝내지 않고 현재 회차의 나머지를 건너뛰어 다음 반복으로 이동한다. 레이블을 붙이면 중첩 구조에서 특정 반복문을 대상으로 삼을 수 있다.
int sum = 0;
myLoop:
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
continue myLoop;
}
sum += i;
}
System.out.println(sum);
실행을 추적하면 짝수일 때 sum += i를 건너뛰고 홀수 1, 3, 5, 7, 9만 더한다. 중간 합은 1 → 4 → 9 → 16 → 25이므로 최종 출력은 25다. 같은 자리에 break를 쓰면 i == 2에서 반복문 자체가 끝나 결과는 1이 된다.
핵심 개념 정리
- 식별자는 시작 문자, 허용 문자, 키워드·리터럴 여부와 대소문자를 순서대로 검사한다.
- 변수는 선언 위치와
static여부로 인스턴스 변수·클래스 변수·지역 변수·파라미터를 구분한다. - 기본형은 값 자체를, 참조형은 객체를 가리키는 참조 값을 저장하므로 대입 뒤 변화가 다르게 전파된다.
- 형변환은 자동·명시 여부만 보지 말고 값의 범위, 소수 잘림과 정밀도 변화까지 확인한다.
- 제어문의 결과는 조건식뿐 아니라
else의 결합,switch의 중단 지점,break와continue의 이동 위치로 결정된다.
Java 코드를 읽을 때는 식별자의 유효성을 확인하고 → 선언 위치로 변수의 종류와 범위를 판정하고 → 리터럴·연산 결과가 자료형에 맞는지 점검하고 → 형변환에서 사라질 정보를 찾고 → 조건·반복·점프가 다음 실행 위치를 어디로 바꾸는지 한 단계씩 추적한다. 이 순서를 습관화하면 문법을 암기 항목이 아니라 실행 결과를 예측하는 도구로 사용할 수 있다.
예상문제 10선
1. 다음 중 Java 식별자로 사용할 수 있는 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
- ① 오답: 숫자는 식별자의 첫 글자에 올 수 없다.
- ② 정답: 문자로 시작하고 뒤의 숫자도 허용되며 예약된 단어가 아니다.
- ③ 오답: 하이픈은 식별자 문자가 아니라 뺄셈 연산자로 해석된다.
- ④ 오답:
false는 논리 리터럴이므로 이름으로 사용할 수 없다.
2. 클래스 몸체에 static int count;로 선언한 변수의 분류와 공유 관계는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
- ① 오답: 지역 변수는 메소드나 블록 안에서 선언되며 클래스 전체가 공유하지 않는다.
- ② 오답: 파라미터는 메소드 선언부에서 전달값을 받는 변수다.
- ③ 오답: 객체마다 따로 가지는 필드는
static이 없는 인스턴스 변수다. - ④ 정답:
static필드는 클래스에 하나 존재하여 동종 객체 사이에 공유된다.
3. 정수 리터럴 0x1a의 십진수 값은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ①
- ① 정답: 16진수 1a는
1×16 + 10이므로 26이다. - ② 오답: 32는 16진수 20의 십진수 값이며 현재 각 자릿값과 다르다.
- ③ 오답:
11010은 같은 값을 나타내는 2진수 숫자 배열이지 십진수 답이 아니다. - ④ 오답:
0x는 실수 표기가 아니라 16진 정수 접두사다.
4. 다음 형변환 설명으로 옳은 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
- ① 오답: double 리터럴을 int에 넣는 축소 변환에는 명시적 캐스트가 필요하다.
- ② 오답: 캐스트는 변환 요청이며 소수 잘림이나 정밀도 손실을 막아 주지 않는다.
- ③ 정답: int에서 더 넓은 double 방향은 대입 과정에서 묵시적으로 변환된다.
- ④ 오답: 소수 리터럴의 기본형은 double이므로
5.5F또는 캐스트가 필요하다.
5. 다음 코드 실행 후 first와 original[0]의 값은?
int first=7; int second=first; second=9; int[] original={7}; int[] alias=original; alias[0]=9;
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
- ① 오답: 기본형 복사는 독립적이지만 두 배열 변수는 같은 객체를 가리킨다.
- ② 오답:
second변경은 값만 복사받은first를 바꾸지 않는다. - ③ 오답: 참조형 변화는 공유되지만 기본형 변수까지 함께 바뀌지는 않는다.
- ④ 정답: 정수값은 별도로 복사되고 배열 참조는 같은 객체를 공유한다.
6. java Main red blue로 실행하고 args[0] + ", " + args[1]을 출력한 결과는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
- ① 오답: 클래스 이름
Main은 실행 대상이며args원소에 포함되지 않는다. - ② 정답: 첫 인수 red가 인덱스 0, 둘째 인수 blue가 인덱스 1에 문자열로 저장된다.
- ③ 오답: 배열은 명령행에 적은 순서를 유지하며 인덱스도 0부터 증가한다.
- ④ 오답: 인덱스 숫자가 아니라 해당 위치에 저장된 문자열을 출력한다.
7. 중괄호가 없는 중첩 if에서 else의 짝을 찾는 규칙은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
- ① 오답: 들여쓰기는 가독성 표현이며 Java 문법의 짝짓기 기준이 아니다.
- ② 오답: 가장 앞선 조건이 아니라 구문상 가장 가까운 미결합 if가 기준이다.
- ③ 정답: dangling else는 아직 짝이 없는 가장 가까운 if에 연결된다.
- ④ 오답: 결합 구조는 실행 결과가 아니라 컴파일할 때 구문으로 결정된다.
8. switch에서 일치한 case의 문장을 실행한 뒤 break가 없으면 어떻게 되는가?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ①
- ① 정답: 일치 지점 이후 제어가 아래로 흐르는 fall-through가 발생한다.
- ② 오답: 자동 종료되지 않으므로 종료하려면
break같은 중단 지점이 필요하다. - ③ 오답: 일치한 뒤에는 case 조건을 처음부터 다시 비교하는 반복이 아니다.
- ④ 오답:
default는 어느 case도 일치하지 않을 때 사용할 선택 경로다.
9. 1부터 10까지 반복하면서 짝수일 때 continue하고 나머지 값을 합산하면 결과는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
- ① 오답: 1은 짝수에서
break로 반복을 끝냈을 때의 결과이며 현재는 계속 반복한다. - ② 오답: 짝수의 합 일부를 계산한 값으로, continue 뒤 실제 합산 대상과 다르다.
- ③ 오답: 1부터 10까지의 짝수 합이며 조건이 건너뛰는 값들이다.
- ④ 정답: 홀수만 남아
1+3+5+7+9=25가 된다.
10. Java 기본 문법 오류와 실행 결과를 점검하는 순서로 가장 타당한 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
- ① 오답: 컴파일 단계의 이름·자료형 문제를 무시하면 실행 결과 추적까지 갈 수 없다.
- ② 정답: 문법 성립, 저장 규칙, 계산 가능성과 실행 위치를 의존 순서대로 확인한다.
- ③ 오답: 무분별한 참조형·캐스트 사용과 제어 장치 제거는 새로운 오류를 만든다.
- ④ 오답: 계산 순서뿐 아니라 범위와 분기가 실제 결과를 함께 결정한다.
참고 자료와 작성 기준
이 글은 해당 차시 강의자료를 바탕으로 학습 목적에 맞게 재구성한 비공식 학습자료입니다. 코드 실행 추적, 자료형 비교와 문제 해설은 처음 배우는 학습자가 판단 과정을 재현할 수 있도록 구성하고 검토했습니다.
- 작성·편집: 올에이클래스 학습연구팀
- 주요 근거: 한국방송통신대학교 컴퓨터과학과, 「Java프로그래밍」 2강 ‘Java 기본 문법(1)’ 강의자료(PDF 생성 정보: 2024년)
- 편집 원칙: 올에이클래스 편집 정책
- 최종 내용 검토: 2026-09-01
댓글
댓글 쓰기