변수(Variable)
데이터를 저장하는 공간(메모리)
변수 생성 규칙
- 대소문자가 구분되며 길이에 제한이 없음
- 숫자로 시작 불가
- 특수문자는 _ 와 $ 만 허용
변수 선언
class Variable1_1 {
boolean flag;
char grade;
byte val;
short sval;
int num;
long price;
float tax;
double score;
}
변수의 종류
지역 변수(Local Variable)
- 메서드나 블록 내부에서 선언되는 변수, 반드시 초기화해야 함.
- 메모리 저장 위치 : Stack
- 생명 주기 : 메서드 종료 시 제거
인스턴스 변수(Instance Variable)
- 클래스 내부에서 선언, 객체가 생성될 때 할당됨. 객체마다 별도 존재, 서로 다른 값을 가질 수 있음.
- 메모리 저장 위치 : Heap
- 생명 주기 : 객체가 제거될 때까지 유지
클래스 변수(Class Variable, Static Variable)
- 모든 객체가 공유하는 변수, 한 번만 메모리에 저장 됨.
- 메모리 저장 위치 : Method Area
- 생명 주기 : 프로그램 종료 시까지 유지
매개변수(Parameter)
- 메서드가 호출될 때 전달되는 값을 저장하는 변수. 메서드가 실행되는 동안만 사용.
- 메모리 저장 위치 : Stack
- 생명 주기 : 메서드 실행 중에만 존재
class Car {
// 클래스 변수 (static 변수) - 모든 객체가 공유
static int totalCars = 0;
// 인스턴스 변수 - 객체마다 개별적으로 존재
String brand;
int speed;
// 생성자 (매개변수 사용)
public Car(String brand, int speed) {
this.brand = brand; // 인스턴스 변수 초기화
this.speed = speed; // 인스턴스 변수 초기화
totalCars++; // 클래스 변수 증가 (모든 객체가 공유)
}
// 메서드 (매개변수 사용)
public void accelerate(int increase) {
// 지역 변수 - 메서드 내부에서만 사용
int newSpeed = speed + increase;
speed = newSpeed; // 인스턴스 변수 업데이트
System.out.println(brand + " 속도 증가: " + speed + "km/h");
}
// 클래스 변수 사용 예제
public static void showTotalCars() {
System.out.println("총 차량 수: " + totalCars);
}
}
public class VariableExample {
public static void main(String[] args) {
// 지역 변수 - main 메서드 내부에서만 사용됨
int initialSpeed = 50;
// 객체 생성 (매개변수 전달)
Car car1 = new Car("Tesla", initialSpeed);
Car car2 = new Car("BMW", 60);
// 메서드 호출 (매개변수 전달)
car1.accelerate(20);
car2.accelerate(30);
// 클래스 변수 출력 (객체 없이 사용 가능)
Car.showTotalCars();
}
}
✔ 지역 변수: initialSpeed, newSpeed
✔ 인스턴스 변수: brand, speed
✔ 클래스 변수: totalCars
✔ 매개변수: brand, speed, increase
상수(Constant)
한 번 값을 저장하면 변경할 수 없는 변수.
프로그램 실핼 중 값이 변하지 않아야 할 경우 사용 됨.
final 키워드를 사용해서 선언
public class ConstantExample {
public static void main(String[] args) {
final double PI = 3.14159; // 상수 선언
System.out.println("원주율: " + PI);
// PI = 3.14; // ❌ 오류 발생! (상수는 값 변경 불가능)
}
}
리터럴(Literal)
상수나 변수에 들어가는 값 자체를 의미.
- 정수 리터럴 : int, long
- 실수 리터럴 : double, float
- 문자 리터럴 : char, ''(작은 따옴표)
- 문자열 리터럴 : String, ""(큰 따옴표)
- 논리 리터럴 : boolean
- null 리터럴 : 객체가 아무것도 가리키지 않을 때 사용
public class LiteralExample {
public static void main(String[] args) {
int number = 10; // 정수 리터럴 (10)
double pi = 3.14; // 실수 리터럴 (3.14)
char letter = 'A'; // 문자 리터럴 ('A')
String word = "Java"; // 문자열 리터럴 ("Java")
boolean isJavaFun = true; // 논리 리터럴 (true)
System.out.println(number);
System.out.println(pi);
System.out.println(letter);
System.out.println(word);
System.out.println(isJavaFun);
}
}
✔ "Java"는 문자열 리터럴
✔ 'A'는 문자 리터럴
✔ 10, 3.14, true 같은 값들은 모두 리터럴!
기본형 데이터 타입
논리형
- boolean(1 byte), range(true, false), default value(false)
문자형
- char(2 byte), range(0 ~ 65,535), default value('\u0000')
정수형
- byte(1 byte), range(-128 ~ 127), default value(0)
- short(2 byte), range(-32,768 ~ 32,767), default value(0)
- int(4 byte), range(-2,147,483,648 ~ 2,147,483,647), default value(0)
- long(8 byte), range(-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807), default value(0L)
실수형
- float(4 byte), range(-3.4 × 10^38 ~ 3.4 × 10^38), default value(0.0F)
- double(8 byte), range(-1.8 x 10^308 ~ 1.8 x 10^308), default value(0.0)
1bit = 0, 1 -> 2개
2bit = 00, 10, 01, 11 -> 4개
8bit = 2^8 : 256개
1byte = 8bit
부호없는 정수의 범위 : 0 ~ 2^n - 1
부호있는 정수의 범위 : -2^(n-1) ~ 2^(n-1) - 1
✔ 첫 번째 비트(최상위 비트, Most Significant Bit)를 부호(Sign)로 사용.
✔ 0이면 양수, 1이면 음수를 나타냄.
✔ 나머지 (n-1)개의 비트로 숫자를 표현.
📌 즉, 전체 n비트 중에서 1비트는 부호를 저장하므로, 숫자를 저장하는 공간이 n-1비트로 줄어듦.
실수형 표현 범위
float(4byte) = 32bit
S : 부호(양수, 음수), 1bit
E : 지수, 8bit
M : 가수(소수점 이하), 23bit
정규화 (Normalization)
✔ 부동소수점 표현에서, 가수를 항상 특정한 형태로 유지하는 것
✔ 컴퓨터가 소수를 저장하는 방식을 표준화해서, 저장 공간을 최적화하는 과정
✔ IEEE 754 표준에 따라 가수(M)는 항상 1.xxx... 형태로 저장됨.
✔ 즉, 소수점 왼쪽이 항상 1이 되도록 변환하는 것
🔹 예제: 10진수를 2진수 부동소수점으로 변환
(1) 10진수 10.625를 2진수로 변환
1. 정수 부분 변환: 10 → 1010₂
2. 소수 부분 변환: 0.625 → 0.101₂
3. 전체 2진수 표현: 1010.101₂
(2) 정규화 (Normalization)
✔ 정규화하면 소수점 왼쪽을 1로 맞춰야 함.
✔ 1010.101₂ → 1.010101 × 2³
✔ 즉, M = 1.010101, E = 3
📌 똑같은 4byte여도 float가 int보다 더 큰 범위가 저장 가능한 이유
int는 1비트는 부호, 31비트는 숫자만 저장 가능함
float는 1비트는 부호, 8비트는 지수, 23비트는 가수로 구성되어 있는데, 위의 부동소수점 표현으로 더 큰 범위가 저장 가능하기 때문
✔ 지수를 사용해서 값의 크기를 조절할 수 있음.
✔ 즉, 10진수에서 1.5 × 10³, 1.5 × 10⁶처럼, float도 M × 2^E 형태로 수를 표현 가능
메모리에는 값이 2진수로 변환하여 저장 됨.
문자를 표현하기 위해서 문자와 숫자를 매칭하는 아스키 코드를 만들었음. (ex : A -> 65 -> 1000001(2))
*문자코드는 음수 표현이 필요없기 때문에 char범위에는 부호가 없음.
아스키코드(ASCII)
✔ 영어 알파벳, 숫자, 특수문자를 표현하는 문자 인코딩 표준
✔ 7비트(0~127)의 숫자로 문자 표현 (총 128개 문자 가능)
✔ 주로 영어 및 기본적인 기호만 포함됨.
유니코드(Unicode)
✔ 전 세계 모든 문자를 표현하기 위한 국제 표준 문자 인코딩
✔ ASCII로는 영어만 표현 가능하지만, 한글, 일본어, 중국어 등 모든 언어를 포함함.
✔ 각 문자를 고유한 코드(숫자)로 매핑하여 저장함.
✔ 유니코드 문자 표현 방식에는 여러 가지가 있지만, 가장 많이 사용하는 방식이 UTF-8
UTF-8
✔ 유니코드를 효율적으로 저장하기 위한 가변 길이 인코딩 방식
✔ 1~4바이트로 문자 표현 (가변 길이)
✔ 영어(ASCII 문자)는 1바이트, 한글/중국어/일본어는 3바이트 이상 사용
✔ 웹, 운영체제, 데이터베이스 등에서 가장 많이 사용하는 인코딩 방식

정수형 오버플로우(Integer Overflow)
✔ 변수가 저장할 수 있는 최대값을 초과할 때 발생하는 오류
✔ 컴퓨터는 메모리 크기가 제한되어 있기 때문에, 특정 자료형이 표현할 수 있는 숫자 범위를 넘으면 값이 예상과 다르게 변함.
✔ 최대값을 초과하면 최소값으로, 최소값을 초과하면 최대값으로 순환됨 (순환 구조, Wrap Around).
public class OverflowExample {
public static void main(String[] args) {
int maxInt = Integer.MAX_VALUE; // 2,147,483,647 (int의 최대값)
System.out.println("최대값: " + maxInt);
int overflow = maxInt + 1; // 최대값 + 1
System.out.println("오버플로우 발생: " + overflow); // -2,147,483,648 (int 최소값)
}
}
실행 결과
최대값: 2147483647
오버플로우 발생: -2147483648
✔ int의 최대값(2,147,483,647)에서 1을 더하면 최소값(-2,147,483,648)으로 변함!
✔ 이런 현상을 정수형 오버플로우(Integer Overflow)라고 함
해설
✔ 컴퓨터는 숫자를 이진수(0과 1)로 저장
✔ int는 4바이트(32비트)이며, 범위는 -2^31 ~ 2^31 - 1
✔ 최대값(0111...1111)에서 +1을 하면 부호 비트가 반전되면서 최소값(1000...0000)이 됨.
BigInteger
✔ Java에서 매우 큰 정수를 저장하고 연산할 수 있도록 제공하는 클래스
✔ 기본 정수형(int, long)은 크기 제한이 있지만, BigInteger는 이론적으로 무한한 크기의 정수를 저장 가능
✔ 메모리가 허용하는 한 크기 제한 없이 사용할 수 있음.
✔ java.math.BigInteger 패키지에 포함되어 있음.
public class BigIntegerExample {
public static void main(String[] args) {
long maxLong = Long.MAX_VALUE; // 9,223,372,036,854,775,807
System.out.println("long 최대값: " + maxLong);
// long 범위를 초과하는 값 (에러 발생)
// long bigNumber = 9223372036854775808L; // ❌ 오류 발생
// BigInteger 사용
BigInteger bigNumber = new BigInteger("9223372036854775808");
System.out.println("BigInteger 값: " + bigNumber);
}
}
BigInteger의 주요 특징
✔ 정수 크기 제한이 없음.
✔ +, -, *, / 같은 연산자를 직접 사용할 수 없고, 메서드를 사용해야 함.
✔ 값을 직접 대입(=)할 수 없고, new BigInteger("값")으로 생성해야 함.
타입간 변환방법
숫자 → 문자 (int → char)
public class ConvertExample {
public static void main(String[] args) {
int num = 65; // ASCII에서 65는 'A'
char ch = (char) num;
System.out.println("숫자 → 문자: " + ch); // 'A'
}
}
숫자 → 문자: A
문자 → 숫자 (char → int)
public class ConvertExample {
public static void main(String[] args) {
char ch = 'A';
int num = (int) ch;
System.out.println("문자 → 숫자: " + num); // 65
}
}
문자 → 숫자: 65
유니코드(ASCII) 이용한 변환
- 숫자 + '0' = 문자
- 문자 - '0' = 숫자
class Variable3_2 {
public static void main(String[] args) {
int num = 5;
char ch = '5';
// 숫자 -> 문자
System.out.println("num = " + num);
// '0' 이 48이기 때문에 결과값을 char 타입으로 변환 필요
System.out.println("num + '0' = " + (char)(num + '0'));
// 문자 -> 숫자
System.out.println("ch = " + ch);
System.out.print("ch - '0' = ");
System.out.println(ch - '0');
// '5' 에서 숫자 5로 변환되었기 때문에 결과값 6
System.out.print("ch - '0' + 1 = ");
System.out.println(ch - '0' + 1);
}
}
숫자 → 문자열 (int → String)
public class ConvertExample {
public static void main(String[] args) {
int num = 123;
String str1 = String.valueOf(num);
String str2 = Integer.toString(num);
System.out.println("숫자 → 문자열: " + str1); // "123"
System.out.println("숫자 → 문자열: " + str2); // "123"
}
}
숫자 → 문자열: 123
숫자 → 문자열: 123
문자 → 문자열 (char → String)
public class ConvertExample {
public static void main(String[] args) {
char ch = 'A';
String str1 = Character.toString(ch);
String str2 = String.valueOf(ch);
System.out.println("문자 → 문자열: " + str1); // "A"
System.out.println("문자 → 문자열: " + str2); // "A"
}
}
문자 → 문자열: A
문자 → 문자열: A
문자열 연결(Concatenation) 연산을 이용한 변환
- 숫자 + "" = 문자열
- 문자 + "" = 문자열
class Variable3_3 {
public static void main(String[] args) {
int num = 5;
char ch = '5';
// 숫자 -> 문자열
System.out.println("num + \"\" = " + num + "");
// num 이 "5" 로 변환되었기 때문에 "5" + "5" 로 결과값은 "55"
System.out.println("num + \"\" + \"5\" = " + num + "" + "5");
// 문자 -> 문자열
System.out.println("ch + \"\" = " + ch + "");
// ch 이 '5' 에서 "5" 로 변환되었기 때문에 "5" + "8" 로 결과값은 "58"
System.out.println("ch + \"\" + \"8\" = " + ch + "" + "8");
}
}
문자열 → 숫자 (String → int, double 등)
public class ConvertExample {
public static void main(String[] args) {
String str = "123";
int num = Integer.parseInt(str);
double dnum = Double.parseDouble("3.14");
System.out.println("문자열 → 정수: " + num); // 123
System.out.println("문자열 → 실수: " + dnum); // 3.14
}
}
문자열 → 정수: 123
문자열 → 실수: 3.14
문자열 → 문자 (String → char)
public class ConvertExample {
public static void main(String[] args) {
String str = "Hello";
char ch = str.charAt(0); // 첫 번째 문자 가져오기
System.out.println("문자열 → 문자: " + ch); // 'H'
}
}
문자열 → 문자: H
참조형 타입(Reference Type)
기본 데이터타입을 제외한 나머지 타입 (ex : String, System).
참조형 변수는 null 또는 메모리 주소를 저장
타입에 관계없이 변수의 크기는 항상 4byte(JVM이 64bit일 경우 8byte)
- 4바이트(32비트)는 총 2^32 = 4,294,967,296 개의 서로 다른 값을 표현 가능
- 즉, 40억 개(약 2^32)의 메모리 주소를 표현할 수 있음
✔ 각 메모리 주소는 1바이트를 가리킴.
✔ 1개의 메모리 주소가 1바이트(8비트) 크기의 데이터에 해당
✔ 즉, 40억 개의 주소를 저장할 수 있다는 것은 40억 바이트(4GB)의 메모리를 다룰 수 있다는 것을 의미
64비트 JVM
✔ 2^64 바이트 = 16엑사바이트(EB)
✔ 이론적으로 16EB(엑사바이트)까지 메모리 접근 가능
예제
class Variable3_5 {
public static void main(String[] args) {
// Date import 필요!
Date date; // 참조형 변수 date 를 선언
date = new Date(); // date 에 객체의 주소를 저장 , new 는 객체를 생성하는 명령어
System.out.println(date); // Wed Jan 11 20:54:45 KST 2023
}
}
* Date는 날짜와 시간을 저장하고 조작하는 참조형 클래스
* 기본형(int, double 등)과 다르게, 객체를 생성해야 사용할 수 있음.
* java.util.Date 클래스는 날짜와 시간을 다루는 클래스로, java.util 패키지에 포함되어 있음.
'코딩 > Java' 카테고리의 다른 글
Java 6 : Map, Hash, HashTable (1) | 2025.02.07 |
---|---|
Java 5 : 객체지향(OOP : Object-Oriented-Programming), 추상화, 인터페이스 (0) | 2025.02.06 |
Java 4 : 조건문, 반목문, 배열 (0) | 2025.02.05 |
Java 3 : 연산자 (0) | 2025.02.05 |
Java 1 : Java와 JVM 개념, Java 환경 셋팅하기 (0) | 2025.02.03 |