[Java Basic] 변수와 타입

buckshot·2025년 5월 24일

JAVA

목록 보기
10/18

변수

변수는 값을 저장할 수 있는 메모리의 특정 번지에 붙이에 붙이는 이름이다. 프로그램은 변수를 통해 메모리의 특정 번지에 값을 저장하고 읽을 수 있다.

프로그래밍 언어에 따라 다르지만, 자바의 변수는 다양한 타입의 값을 저장할 수 없다. 각 타입에 정해진 타입의 값만 저장할 수 있으며, 하나의 변수에는 단일의 값만 저장할 수 있다.

변수 선언

변수를 선언에 있어 먼저 변수의 타입을 선언하고 뒤에 변수명을 붙인다.

// 타입  변수명;
int num;
double value;

추가적으로 하나의 특정 타입으로 여러 변수 선언 시 콤마(,)를 이용하여 한꺼번에 선언할 수 있다.

// 같은 타입의 여러 변수 선언 방법
int x, y, z;

변수 작명

변수 이름은 자바 언어에서 정한 규칙을 따라야 한다.

작성 규칙
첫 번째 글자는 문자이거나 ‘$’, ‘_’이어야 하고 숫자로 시작할 수 없다.필수가능 : price, $price, …
불가능 : 1v, @Speed, &value
영어 대소문자를 구분한다.필수firstname과 fristName은 다른 변수
척 문자는 영어 소문자로 시작하되, 다른 언어가 붙을 경우 첫 문자를 대문자로 한다.관례maxSpeed, firstName, …
문자 길이에 대한 제한은 없다,
자바 예약어는 사용할 수 없다필수

예약어란 이미 해당 프로그래밍 언어에서 의미를 갖고 사용되고 있는 단어로, 변수 이름으로 사용할 수 없다.

예약어로 변수 이름을 선언하고 컴파일 에러가 발생한다.

값 저장

변수에 값을 저장할 때는 대입 연산자 ( = )를 사용한다. 등호( = )는 대부분 ‘같다’라는 의미지만, 자바 언어에서는 같은 의미로 사용되지 않는다.

자바에서 = 와 == 차이점

= -> 변수에 값을 저장할 때

== -> 변수가 특정 값이나 변수와 같은지 비교할 때

int score; // 변수 선언
score = 90; // 값 저장
//     <-
// 변수에 정수를 저장

자바에서 변수에 값이 저장되지 않으면 변수가 생성되지 않는다. 여기서 선언과 생성은 다른 의미이다.

  • 변수 선언 : 변수의 이름과 타입을 지정
  • 변수 생성 : 메모리에 해당 변수 공간에 실제로 할당
    변수에 최초로 값이 저장될 때 변수가 생성되는데 이것을 변수 초기화라고 한다. 그리고 이때 사용된 값은 초기값이라고 한다.

위 코드 블럭을 보면 변수를 선언하고 다음 줄에서 값을 저장하는 형태가 보인다. 변수 선언과 값을 저장할 때 무조건 두 줄을 사용해야 하는 것은 아니다. 초기값을 선언과 동시에 제공하는 방법을 이용하면 된다.

int score = 90;

저장된 값이 없는 변수는 생성되지 않는 이유는..

자바는 JVM(Java Virtual Machine) 위에서 실행됩니다. 컴파일러(javac)나 JIT 컴파일러(Just-In-Time 컴파일러)는 사용되지 않는 변수나 의미 없는 코드를 최적화 과정에서 제거할 수 있다.

그렇기 떄문에 변수를 사용할 때 변수 초기화를 하고 사용해야 된다.

변수 사용 범위

자바의 모든 변수는 중괄호 블록 내에서 선언되고 사용된다. 메서드 블록 내에서 선언된 변수는 로컬 변수라고 칭한다.

로컬 변수는 메서드 블록 내부에서만 사용이 되고, 메서드 실행이 끝나면 해당 메모리는 자동으로 없어진다.

public class VariableExample {								// ⎤
	public static void main(String[] args) {	// ⎤	  	   ⎟	
		int value = 10;							// ⎟			클래스 블록
		int sum = value + 20;					// 	메서드 블록   ⎟
		System.out.print(sum);					// ⎟           ⎟
	}											// ⎦		   ⎟
}															// ⎦

위 코드를 보면 변수가 선언된 위치에서 가장 가까운 블록을 찾아보면 main과 동일한 줄에서 사용된 중괄호가 가장 가깝다. 그러면 해당 변수는 main 블록 내부에서만 사용이 가능하다.

	public static void main(String[] args) {	// ①
		int v1 = 10;
		if(...) {	// ②
			int v2;
			v2 = 5;
			int v3 = v1 + v2;
		}	
//		int v4 = v1 + v2;
	}	

그러면 위 상황에서 변수 사용 가능 범위를 확인하자. ( 중괄호를 번호로 칭하겠다)

(조건문 if에 대한 설명이 아니다. 저런게 있구나 하고 변수 선언 위치에 신경을 쓰자…)

  • v1변수는 블록 ①과 ② 내부에서 사용 가능
    • 블록 ②는 블록 ① 내부에 선언되었기 때문에 활동 범위에 포함
  • v2변수는 ② 중괄호 내부에서만 사용 가능
    • v2는 블록 ② 내부에서 선언되었기 때문에 블록 ①에서 사용 불가능

그러면 변수 v3와 v4에 대해서 적합한 코드인지 확인을 하자.

  • v3 : 변수 v1, v2는 적절한 활동 범위 내에서 사용했기 때문에 적합하다.
  • v4 : 변수 v1는 적절한 활동 범위 내에서 사용 했지만, v2는 정해진 활동 범위를 벗어났기 때문에 불가능

이 처럼 변수는 중괄호 내부에서만 선언과 사용이 가능하다. 그렇기 때문에 사용 범위를 유의하여 선언한다.


기본 타입

자바는 정수, 실수, 논리값을 저장할 수 있는 기본 타입 을 제공한다. 제공되는 기본 타입 8개에 대하여 간단하게 확인하자.

구분분류타입
기본 타입정수 타입byte, char, short, int, long
기본 타입실수 타입float, double
기본 타입논리 타입boolean

기본 타입

정수 타입

타입메모리 크기허용 범위허용 범위
byte1 byte ~ 8 bit27(271)-2^7 \sim (2^7 -1)128127-128 \sim 127
short2 byte ~ 16 bit215(2151)-2^15 \sim (2^15 -1)32,76832,767-32,768 \sim 32,767
char2 byte ~ 16 bit0(2161)0 \sim (2^16 -1)0655350 \sim 65535(유니코드)
int4 byte ~ 32 bit231(2311)-2^31 \sim (2^31 -1)2,147,483,6482,147,483,647-2,147,483,648 \sim 2,147,483,647
long8 byte~ 64 bit263(2631)-2^63 \sim (2^63 -1)

각 타입이 저장할 수 있는 값의 범위는 아래의 식이다. 여기서 n에 메모리 bit수를 넣으면 허용 범위가 된다.

2n1(2n11)-2^{n-1} \sim (2^{n-1} -1)

리터럴

프로그래머에 의하여 직접 입력된 값을 리터럴(Literal)이라고 부른다. 입력된 리터럴 중에서 자바가 정수로 인식하는 경우는 아래와 같다.

  • 2 진수 : 0b 또는 0B로 시작하고 0과 1로 구성된다.
    • 0b1011>1×23+0×22+1×21+1×20>120b1011 -> 1\times2^3 + 0\times2^2 + 1\times2^1 +1\times2^0 -> 12
  • 8 진수 : 0으로 시작하고 0 ~ 7로 구성된다.
    • 013>1×81+3×80>11013 -> 1\times8^1 + 3\times8^0 -> 11
  • 10 진수 : 소수점 없이 0 ~ 9로 구성된다.
    • 1212
  • 16 진수 : 0x 또는 0X로 시작하고 0 ~ 9 숫자와 ABCDEF(대소문자 상관 x)로 구성된다.
    • 0xB3>11×161+3×160>1790xB3 -> 11\times16^1 + 3\times16^0 -> 179

정수 타입 변수에 허용된 범위를 초과하는 값을 저장할려고 시도하는 경우 컴파일 에러가 발생되는 점을 유의하며 사용 해야 한다.

long x = 30000000000; // 컴파일 에러 발생!
long x = 30000000000L;

long타입의 변수에 정수를 저장할 때 int 범위에 포함되는 값을 저장하면 정수만 입력하면 쉽게 값을 저장할 수 있다. 하지만 int 범위를 초과하는 정수를 저장할 때 컴파일러에게 “이 정수는 long 타입의 범위에 해당 합니다.”라는 식으로 리터럴 뒤에 L이나 l을 붙여줘야 한다. (하지만 나는 간단한 실수를 몇 번 한다.)

  • char 타입
    하나의 문자를 작은 따옴표(‘)로 감싼 것을 문자 리터럴이라고 한다. 이는 유니코드(Unicod)로 변환되어 저장된다.
    여기서 유니코드는 서계 각국 문자를 2byte로 표현할 수 있는 숫자 (0 ~ 65535)로 매핑한 국제 표준 규약이다.
    자바는 이러한 유니코드를 저장할 수 있도록 2byte 크기인 char타입을 제공한다.
char var1 = 'A'; // 유니코드 65
char var2 = 65; // A
char var3 = 0x0041; // A

유니코드는 정수이므로 char도 정수 타입에 속한다. 그래서 작은 따옴표로 감싼 문자가 아니라 10진수 또는 16진수 형태로 유니코드를 저장할 수 있다.

문자 리터럴을 int 타입에 저장하면 어떻게 될까?

작은 따옴표를 감싼 문자 리터럴은 유니코드로 변환되기 때문에 int타입 변수에도 저장할 수 있다.

int x = 'A'; // 유니코드로 변환되어 자장
// x 출력 -> 65 

실수 타입

실수 타입에는 floatdouble 이 존재한다.

타입메모리 사용 크기허용 범위정밀도(소수점 이하 자리)
float4 byte ~ 32 bit(1.4×1045)(3.4×1038)(1.4\times10^{-45})\sim(3.4\times10^{38})7자리
double8 byte ~ 64 bit(4.9×10324)(1.8×10308)(4.9\times10^{-324})\sim(1.8\times10^{308})15자리

자바는 실수 리터럴을 기본적으로 double타입으로 해석하기 때문에 double타입 변수에 저장을 해야 한다. 실수 리터럴을 float타입으로 저장하고 싶다면 “f / F”를 리터럴 뒤에 붙여야 한다.

논리 타입

참과 거짓을 의미하는 논리 리터럴로 treu / false를 사용한다.

boolean a = true;
boolean b = false;

논리 타입 리터럴은 다음과 같이 1 byte크기의 boolean타입 변수에 저장할 수 있다.

boolean타입 변수는 주로 두 가지 상태 값에 따라 조건문과 제어문의 실행 흐름을 변경하는 데 사용된다.

String 타입

char타입은 작은 따옴표를 감싼 문자를 변수에 저장되어 유니코드로 저장되지만, 큰 따옴표로 감싼 문자는 또는 여러 개의 문자들은 유니코드로 변환되지 않는다.

자바에서 큰 따옴표로 감싼 문자들을 문자열이라고 칭한다. 문자열을 변수에 저장하고 싶을 경우에는 String 타입을 사용해야 한다.

String str = "hello";

타입 변환

동일 타입의 두 변수가 있을 경우 한쪽 변수의 값을 다른 변수에 복사하여 저장할 수 있다. 하지만 변수의 타입이 다를 경우는 타입 변환이 필요하다.

자동 타입 변환

자동 타입 변환은 자동으로 타입 변환이 일어나는 것을 의미한다. 자동 타입 변환은 값의 허용 범위가 작은 타입이 허용 범위가 큰 타입으로 저장될 때 발생한다.

byte byteValue = 10;
int intValue = byteValue; // 자동 타입 변환

기본 타입에서의 허용 범위 크기 순서는 byte < short < int < long < double 같다.

자동 타입 변환 예외

char타입 보다 허용 범위가 작은 byte타입은 char타입으로 변환될 수 없다. 그 이유는 char타입의 허용 범위는 음수를 포함하지 않는데, byte타입은 음수를 포함하기 때문이다.

강제 타입 변환

허용 범위가 큰 타입은 보다 작은 타입으로 변환될 수 없다. 마치 큰 물통의 물을 작은 물통에 모두 넣을 수 없는 것과 동일하다. 하지만 작은 물통에 나눠서 한 부분만 작은 물통에 담는 것 처럼 허용 범위 큰 타입을 허용 범위가 작은 타입으로 강제적으로 나눠서 저장하는 것을 강제 타입 변환이라고 한다.
(실수 타입에서 정수 타입으로 변환 시 소수점 이하 부분은 버려지게 된다.)

연산 중 자동 타입 변환

산술 연산식에서 피연산자로 사용되는 변수의 타입에 따라 자동으로 타입이 변환되어 연산을 수행한다.

정수 산술 연산int보다 작은 타입(byte, short, char)이 자동으로 int로 변환되고, 실수 산술 연산에서는 floatdouble이 함께 연산되면 자동으로 double로 변환됩니다.

byte a = 10;
byte b = 20;
int result1 = a + b;      // byte + byte → int로 자동 변환

float x = 3.14f;
double y = 2.0;
double result2 = x + y;   // float + double → double로 자동 변환

정수 산술 연산에서 int보다 작은 타입의 연산에서는 int로 변환된다고 했다. 그러면 int보다 허용 범위가 큰 long의 경우에는 어떻게 될까??

long타입의 경우에는 int타입의 변수가 long타입으로 변환되어 연산이 진행된다.

int a = 1000;
long b = 2000L;

long result = a + b; // a가 long으로 변환되어 long + long → 결과는 long

추가적으로 정수 타입과 실수 타입 끼리의 산술 연산에 있어서 어떻게 타입이 변환될까?

int타입과 double타입을 연산해도 비슷과 과정을 거친다.
먼저 int타입을 갖는 피연산자가 double타입으로 변환되어 진행한다.

만약 꼭 int타입으로 연산을 해야 한다면 double타입을 int타입으로 강제 변환을 해야 한다.

+ 연산에서 문자열이 있을 경우

+연산자에는 두 가지 기능을 갖고 있다. 피연산자 모두 숫자일 걍우에는 덧셈 연산을 수행한다. 하지만 피연산자 중 문자열이 하나라도 존재 할 경우에는 문자열로 자동 변환된다.

숫자 + 숫자 -> 덧셈 연산 -> 숫자
"문자열" + 숫자 -> "문자열" + "숫자" -> 결합 연산 -> "문자열숫자"

연산식에서 +연산자가 연이어 나오면 앞에서 부터 순차적으로 +연산을 수행하게 된다. 여기서 +연산자가 덧셈 연산이라면 덧셈 결과를 가지고 다음 연산을 진행하게 되고, 만약 먼저 결합 연산이 수행되면 이후 진행되는 +연산은 모두 결합 연산으로 수행하게 된다.

3 + 2 + "3" -> 5 + "3" -> "53"
"3" + 2 + 3 -> "32" + 3 -> "323"

문자열 -> 기본 타입으로 강제 변환

변환 타입사용 예
String -> byteByte.parseByte( “문자열“ );
String -> shortShort.parseShort( “문자열” );
String -> intInteger.parseInt( “문자열” );
String ->longLong.parseLong( “문자열” );
String -> floatFloat.parseFloat( “문자열” );
String -> doubleDouble.parseDouble( “문자열” );
String -> booleanBoolean.parseBoolean( “문자열” );

문자열을 기본 타입으로 변환 과정에서 변환될 값이 해당 타입에 허용되는 범위에 적합하지 않을 경우에는 예외가 발생하게 된다는 점을 유의 해야 한다.


변수와 시스템 입출력

출력

지금까지 출력을 System.out.println( 리터럴 );과 같은 방식으로 출력을 했다.

출력에 있어서 사용되는 메서드는 총 3가지가 있다.

메서드의미
println( 내용 );내용을 출력하고 행을 바꾼다.
print( 내용 );내용만 출력 한다.
printf( “형식문자열”, 값1, 값2 , … );문자열 형식대로 출력 한다.

println()print( )같은 경우 출력하고 싶은 내용을 괄호에 명시하면 해당 내용이 쉽게 출력되는 것을 확인할 수 있다. 하지만 printf( )메서드는 다른 방법으로 출력된다.

printf( )메서드는 형식화된 문자열을 이용하여 출력을 제어할 수 있다.

printf("형식문자열", 값1, 값2, ...)
			
형식문자열 -> %[argument_index] [flags] [width] [.precision] conversion
				값의 순번		   -, +  전체 자릿수  소수 자릿수     변환 문자
			⌞__________________생략 가능__________________⌟

형식 문자에서 %와 conversion은 생략이 불가능한 필수로 기입을 해줘야 한다. 그 외 나머지 항목은 생략을 하여도 문제 없다.

conversion에는 제공되는 값의 타입에 따라 d(정수), f(실수), s(문자열)를 입력한다. 그리고 값이 2개 이상일 경우 값의 순번을 지정해줘야 한다.

System.out.printf("이름 : %s", "홍길동"); // 이름 : 홍길동
System.out.printf("나이 : %d", 25);		// 나이 : 25

System.out.printf("이름 : %1$s, 나이 : %2$d", "홍길동", 25);
// 이름 : 홍길동, 나이 : 25
profile
let's go insane

0개의 댓글