[자바프로그래밍] 02. 변수·자료형·연산자
프로그램의 기본 재료인 변수와 자료형, 그리고 그것들을 다루는 연산자를 자바 기준으로 정리했다. C와 비슷한 부분이 많지만, 자바만의 규칙(기본형 8가지, boolean 엄격함, Scanner 입력 등)이 분명히 있어 그 차이에 집중했다.
1. 기본 구조와 식별자
자바의 모든 코드는 클래스 안에 들어가고, 실행은 main() 메서드에서 시작한다.
public class Hello {
public static void main(String[] args) {
int i = 20;
System.out.println("Hello");
System.out.println(i); // 20
}
}
이름(식별자)을 짓는 규칙은 C와 비슷하다. 문자·숫자·_·$를 쓰되 숫자로 시작할 수 없고, 예약어는 못 쓰며, 대소문자를 구별한다. 자바에는 강한 이름 관례가 있다.
- 클래스 이름: 대문자로 시작 (
HelloWorld) - 변수·메서드: 소문자로 시작 (
myAge,getAge()) - 상수: 모두 대문자 (
final static double PI)
C에서는 한 함수만 있어도 됐는데, 자바는 무조건 클래스 안에 코드를 넣어야 한다는 게 처음엔 번거로웠다. 모든 게 객체 지향 위에 서 있다는 신호로 받아들였다.
2. 자료형
자바의 기본형(basic type)은 byte·short·int·long·float·double·boolean·char 8가지로, 크기가 정해져 있고 OS·CPU에 따라 변하지 않는다. 그 외 String·배열·클래스 등은 값이 저장된 주소를 다루는 참조형(reference type)이다.
C와 다른 점이 자료형 크기가 플랫폼과 무관하게 고정이라는 것이다(플랫폼 독립성의 일환). 또 boolean이 정수와 완전히 분리되어 있다.
boolean t = true;
boolean c = 1; // 오류! 자바는 1/0을 참/거짓으로 쓰지 못한다
C에서 0/1을 참거짓으로 쓰던 것과 달리, 자바는 true/false만 허용한다. 이 엄격함이 if (x = 5) 같은 실수를 원천 차단한다. C에서 자주 걸리던 함정을 언어가 막아준다는 게 인상적이었다.
상수는 final로 선언해 값을 못 바꾸게 한다. 정수 리터럴은 기본 int, 실수 리터럴은 기본 double로 처리되며, 문자열은 +로 연결된다("JDK" + 1.8 → "JDK1.8").
3. 형변환
| 종류 | 설명 |
|---|---|
| 자동(확대) 형변환 | 작은 타입 → 큰 타입, 손실 없음 (byte→int→long→double 방향) |
| 명시적(축소) 형변환 | 캐스트 연산자 (타입)으로 강제, 손실 가능 |
double d = 1.9;
int n = (int)d; // 1 (소수점 손실)
System.out.println(10 / 4); // 2 (정수 나눗셈)
System.out.println(10.0 / 4); // 2.5 (한쪽이 실수)
(int)2.9 + 1.8 // → 2 + 1.8 = 3.8 (2.9만 변환)
(int)(2.9 + 1.8) // → (int)4.7 = 4 (합을 변환)
(int)2.9 + (int)1.8 // → 2 + 1 = 3 (각각 변환)
괄호의 위치가 계산 순서와 결과를 바꾼다. 형변환은 "무엇을 언제 변환하는가"를 정확히 봐야 한다.
정수 나눗셈 함정은 C·C++에 이어 자바에서도 똑같이 만났다. 언어가 바뀌어도 "타입이 연산 결과를 좌우한다"는 원칙은 그대로였다.
4. Scanner로 키보드 입력받기
자바는 입력에 Scanner를 쓴다. java.util.Scanner를 import해야 한다.
import java.util.Scanner;
Scanner scan = new Scanner(System.in);
int age = scan.nextInt(); // 정수
double w = scan.nextDouble(); // 실수
String name = scan.next(); // 한 단어
String line = scan.nextLine(); // 한 줄(공백 포함)
scan.close();
타입마다 메서드가 다른 게 특징이다. nextInt는 정수를, nextDouble은 실수를 읽는다. C의 scanf가 %d/%lf 형식 지정자로 구분했다면, 자바는 메서드 이름으로 구분하는 셈이다.
5. 연산자
연산자는 C와 거의 같다. 산술(+ - * / %), 비교(> >= == !=), 논리(&& || !), 증감(++ --), 삼항(조건 ? a : b) 모두 동일하게 동작한다.
int a, b = 4;
a = b++; // 대입 후 증가 → a=4, b=5
a = ++b; // 증가 후 대입 → a=6, b=6
int big = (x > y) ? x : y; // 삼항: 큰 값
수학에서 쓰는 연속 비교는 프로그래밍 언어에선 안 된다. "20대"를 표현하려면 논리 연산자로 두 조건을 묶어 (age >= 20) && (age < 30) 으로 써야 한다.
오늘 느낀 점
- 연산자·형변환이 C와 거의 같아 적응이 빨랐다. 대신 boolean 엄격함, 자료형 고정 크기 같은 자바만의 차이가 "왜 이렇게 만들었나"를 생각하게 했다.
- boolean에 정수를 못 넣게 막는 엄격함이 C에서 자주 겪던 실수를 원천 차단한다는 점에서, 언어 설계가 안전을 어떻게 챙기는지 보였다.
- 정수 나눗셈 함정을 또 만나며, 개념은 언어를 가리지 않는다는 걸 다시 확인했다. C에서 익힌 게 그대로 자산이 됐다.
한 걸음 더
- 자바의 기본형(int 등)과 참조형(String 등)은 다루는 방식이 근본적으로 다르다. 기본형은 값 자체를, 참조형은 객체의 주소를 담는다. 그래서 문자열 비교에
==를 쓰면 내용이 아니라 주소를 비교해 엉뚱한 결과가 날 수 있고, 내용 비교는.equals()를 써야 한다. 이건 객체를 본격적으로 배울 때 다시 만나는 핵심 주제다. - 정수 리터럴이 기본 int라는 점은 큰 수에서 함정이 된다.
long변수에 21억을 넘는 값을 직접 쓰면 int 범위 초과로 오류가 나므로,100000000000L처럼 끝에L을 붙여 long 리터럴임을 알려야 한다. Scanner에서nextInt()다음에nextLine()을 쓰면 빈 줄이 읽히는 유명한 함정이 있다.nextInt()가 숫자만 읽고 줄바꿈을 남겨둬서, 다음nextLine()이 그 남은 줄바꿈을 먼저 읽어버리기 때문이다. 입력 메서드를 섞어 쓸 때 자주 겪는 문제라 알아두면 좋다.