Java의 정석: CHAPTER 02 변수(Variable)

mucha·2023년 4월 15일

Java의 정석

목록 보기
2/6
post-thumbnail

CHAPTER 02 변수(Variable)

1. 변수와 상수


1.1 변수란?

단 하나의 값을 저장할 수 있는 메모리 공간.

1.2 변수의 선언과 초기화

int age; //age라는 이름의 변수를 선언

변수타입: 변수에 저장될 값이 어떤 타입인지를 지정하는 것.
변수이름: 변수에 붙인 이름. 같은 이름의 변수가 여러 개 존재해서는 안됨.

변수의 초기화
변수를 선언한 이후부터는 변수를 사용할 수 있으나, 그 전에 반드시 변수를 초기화 해야 함.
메모리는 여러 프로그램이 공유하는 자원이므로 전에 다른 프로그램에 의해 저장된 알 수 없는 값이 남아있을 수 있기 때문

int age = 25; // 변수 age를 선언하고 25로 초기화한다.
class VarEx1 {
	public static void main(String[] args) {
		int year = 0;
		int age  = 14;
		 
		System.out.println(year);
		System.out.println(age);

		year = age + 2000;  // 변수 age의 값에 2000을 더해서 변수 year에 저장
		age  = age + 1;     // 변수 age에 저장된 값을 1증가시킨다.

		System.out.println(year);
		System.out.println(age);
	}
}

두 변수의 값 교환하기

class VarEx2 {
	public static void main(String[] args) {
		int x = 10;
		int y = 20;
		int tmp = 0;
	
		System.out.println("x:"+ x + " y:" + y);
		
		tmp = x; // x값을 저장하기 위한 임시 저장소 tmp
		x = y;
		y = tmp; 

		System.out.println("x:"+ x + " y:" + y);
	}
}

1.3 변수의 명명규칙

식별자: 변수의 이름처럼 프로그래밍에서 사용하는 모든 이름. 같은 영역 내에서 서로 구분 가능 해야 함.

식별자 만들 때 규칙
1. 대소문자가 구분되며 길이에 제한이 없음.
2. 예약어를 사용해서는 안된다.
예약어: 프로그래밍 언어의 구문에 사용되는 단어.
3. 숫자로 시작해서는 안된다.
4. 특수문자는 ‘_’와 ‘$’만 사용 가능.

권장되는 규칙
1. 클래스 이름의 첫글자는 항상 대문자
변수와 메서드의 이름의 첫 글자는 항상 소문자
2. 여러 단어로 이루어진 이름은 단어의 첫 글자를 대문자
lastIndexOf, StringBuffer
3. 상수의 이름은 모두 대문자. 여러 단어로 이루어진 경우 ‘_’로 구분.
PI, MAX_NUMBER

2. 변수의 타입


기본형과 참조형

  • 기본형(primitive type)
    • 실제 값 저장
    • 논리형(boolean), 문자형(char), 정수형(byte, short, int, long), 실수형(float, double)
  • 참조형
    • 어떤 값이 저장되어 있는 주소를 값으로 가짐
    • 객체의 주소를 저장. 8개의 기본형을 제외한 나머지 타입

2.1 기본형(primitive type)

기본형의 종류와 크기

1 byte2 byte3 byte8 byte
논리형boolean
문자형char
정수형byteshortintlong
실수형floatdouble

2.2 상수와 리터럴(constant & literal)

상수(constant): 값을 저장할 수 있는 공간. 변수와 달리 한 번 값을 저장하면 다른 값으로 변경 불가.
final int MAX_SPEED =10;
상수는 선언과 동시에 초기화해야함.

리터럴
값 자체를 의미

상수가 필요한 이유
리터럴에 의미있는 이름을 붙여 코드의 이해와 수정을 쉽게 만듦.

리터럴의 타입과 접미사

종류리터럴접미사
눈리형false, true없음
정수형123, 0b0101, 077, 0xFF, 100LL
실수형3.14, 3.0e8, 1.4ff, d
문자형“A”, “1”, “\n”없음
문자열“ABC”, “123”, “abc”, “true”없음

타입의 불일치

int i = "A" // OK. "A"의 유니코드인 65가 저장 됨
long l = 123 // OK int보다 long의 범위가 더 큼
double d = 3.14f // OK float보다 double의 범위가 더 큼

int i = Ox1234568; // Error. int타입의 범위를 넘는 값 저장
float f = 3.14; // Error. float 타입보다 double 타입의 범위가 넓음

문자 리터럴과 문자열 리터럴

char ch = 'J';
String name = "JAVA";

String str = "";
char ch = ""; //Error ''안에 반드시 하나의 문자가 필요함
char ch = " ";

String name = new String("Java");

String name = "ja" + "va";
String str = name + 8.0;
class StringEx {
	public static void main(String[] args) {
		String name = "Ja" + "va";
		String str  = name + 8.0;

		System.out.println(name);
		System.out.println(str);
		System.out.println(7 + " ");
		System.out.println(" " + 7);
		System.out.println(7 + "");
		System.out.println("" + 7);
		System.out.println("" + "");
		System.out.println(7 + 7 + "");
		System.out.println("" + 7 + 7);
	}
}

2.3 형식화된 출력 - printf()

printf(): 지시자를 통해 변수의 값을 여러 가지 형식으로 변환하여 출력.
지시자: 값을 어떻게 출력할 것인지를 지정해주는 역할.

System.out.printf("age:%d", age);
System.out.printf("age:%d", 14);
System.out.printf("age:14");

만약 출력하려는 값이 2개 이상이라면 지시자도 2개 이상 사용

System.out.printf("age: %d, year: %d", age, year);

줄바꿈은 %n을 사용한다

자주 사용하는 printf()의 지시자

지시자설명
%bboolean
%ddecimal
%ooctal
%x, %Xhexa-decimal
%ffloating-point
%e, %Eexponent
%ccharacter
%sstring

간격 맞게 프린트하는법

System.out.printf("finger = [%5d]", finger); //  finger = [   10]
System.out.printf("finger = [%-5d]", finger); // finger = [10   ]
System.out.printf("finger = [%05d]", finger); // finger = [00010]

2.4 화면에서 입력받기 - Scanner

import java.util.*;    // Scanner를 사용하기 위해 추가

class ScannerEx { 
	public static void main(String[] args) { 
		Scanner scanner = new Scanner(System.in);

		System.out.print("두자리 정수를 하나 입력해주세요.>");

		String input = scanner.nextLine();
		int num = Integer.parseInt(input); // 입력받은 문자열을 숫자로 변환

		System.out.println("입력내용 :"+input);
		System.out.printf("num=%d%n", num);
	} 
}

3. 진법


3.1 10진법과 2진법

컴퓨터는 2진 체계로 설계.
2진법을 알지 못하면 컴퓨터의 동작원리나 데이터 처리방식을 온전히 이해할 수 없음.

3.2 비트(bit)와 바이트(byte)

비트: 한 자리의 2진수. 컴퓨터가 값을 저장할 수 있는 최소단위
바이트: 1비트 8개를 묶음. 데이터의 기본 단위.
워드: CPU가 한 번에 처리할 수 있는 데이터의 크기. CPU의 성능에 따라 크기는 달라짐.

n비트로 표현할 수 있는 10진수

  • 값의 개수: 2n2^n
  • 값의 범위: 0 ~ 2n12^n - 1

3.3 8진법과 16진법

8진수는 2진수 3자리를, 16진수는 2진수 4자리를 각각 한자리로 표현할 수 있기 때문에 자리수가 짧아져서 알아보기 쉽고 서로 간의 변환방법 또한 매우 간단.

2진수를 8진수, 16진수로 변환
2진수를 뒤에서부터 3, 4자리씩 끊어서 그에 해당하는 8진수 혹은 16진수로 바꾸면 된다.

3.4 정수의 진법 변환

10진수를 n진수로 변환
해당 진수로 나누고 나머지 값을 옆에 적는 과정을 몫이 해당 진수보다 작아질때까지 반복한다.
마지막 나머지부터 첫번째 나머지까지 순서대로 적는다.

n진수를 10진수로 변환
각 자리의 수에 해당 단위의 값을 곱해서 모두 더하면 됨.

3.5 실수의 진법 변환

10진 소수를 2진 소수점수로 변환하는 법
1. 10진 소수에 2를 곱한다.
0.625 X 2 = 1.25
2. 위의 결과에서 소수부만 가져다가 다시 2를 곱한다.
0.25 X 2 = 0.5
3. 1과 2의 과정을 소수부가 0이 될 때까지 반복한다.
0.5 X 2 = 1.0
4. 결과에 정수부만을 위에서 아래로 순서대로 적고 ‘0.’을 붙인다.
0.101

2진 소수점수를 10진 소수점수로 변환하는 방법
0.101 = 1 X 0.5 + 0 X 0.25 + 1 X 0.125 = 0.625

3.6 음수의 2진 표현 - 2의 보수법

#2진수부호있는 10진수
100000
200011
300102
400113
501004
601015
701106
801117
91000-8
101001-7
111010-6
121011-5
131100-4
141101-3
151110-2
161111-1

2의 보수법
n의 보수: 더했을 때 n이 되는 수

음수를 2진수로 표현하기
10진 음의 정수를 2진수로 변환하려면 10진 음의 정수의 절대값을 2진수로 변환한다.
그 다음에 2진수의 2의 보수를 구하면 됨.

음수의 2진 표현을 구하는 방법
1. 음수의 절대값을 2진수로 변환한다.
-5의 절대값인 5를 2진수로 변환한다. (0101)
2. 1에서 구한 2진수의 1을 0으로 0을 1로 바꾼다.
0101 → 1010
3. 2의 결과에 1을 더한다.
1010에 1을 더하면 1011이 되고 이것이 -5의 2진 표현이다.

4. 기본형


4.1 논리형 - boolean

default: false
크기: 1바이트
TRUE와 true는 다름. true와 false만 가능.

4.2 문자형 - char

변수에 ‘문자’가 저장되는 것 같지만, 사실은 문자가 아닌 ‘문자의 유니코드’가 저장됨.

특수 문자 다루기
char tab = '\t';

특수 문자문자 리터럴
tab\f
backspace\b
form feed\f
new line\n
carriage return\r
역슬래쉬\
작은 따옴표\’
큰 따옴표\”
유니코드 문자\u유니코드

char타입의 표현방식
char ch = “A”;
short s = 65;
두 개의 2진수는 같음. 하지만 출력해보면 결과가 다름.
변수의 타입이 정수형이면 변수에 저장된 값을 10진수로 해석하여 출력하고, 문자형이면 저장된 숫자에 해당하는 유니코드 문자를 출력하기 때문.

인코딩과 디코딩
문자 인코딩: 문자를 코드로 변환하는 것.
문자 디코딩: 코드를 문자로 변환하는 것.

4.3 정수형 - byte, short, int, long

byte(1) → short(2) → int(4) → long(8)

정수형의 오버플로우
오버플로우: 연산과정에서 해당 타입이 표현할 수 있는 값의 범위를 넘어서는 것.
에러가 발생하는 것은 아님.

부호있는 정수의 오버플로우
부호있는 정수는 부호비트가 0에서 1이 될 때 오버플로우 발생.

4.4 실수형 - float, double

실수형의 범위와 정밀도
float, double 두 가지가 있으며 각 타입의 변수에 저장할 수 있는 값의 범위는 아래와 같다.

타입저장 가능한 값의 범위정밀도크기(bit)크기(byte)
float1.4 10^-45 ~ 3.4 10^387자리324
double4.9 10^-324 ~ 1.8 10^30815자리648

연산속도의 향상이나 메모리를 절약하려면 float, 더 큰 값의 범위라던가 더 높은 정밀도를 필요로 한다면 double.

실수형의 저장방식
실수형은 값을 부동소수점수의 형태로 저장.
float: 1(S) + 8(E) + 23(M) = 32 (4 byte)
double = 1 + 11 + 52 = 64 (8 byte)

기호의미설명
S부호(Sign bit)0이면 양수, 1이면 음수
E지수(Exponent)부호있는 정수
지수의 범위는 -127 ~ 128(float), -1023 ~ 1024(double)
M가수(Mantissa)실제값을 저장하는 부분.
10진수로 7자리(float), 15자리(double)의 정밀도로 저장 가능

부동소수점의 오차
실수 중에는 무한 소수가 존재하므로, 정수와 달리 실수를 저장할 때 오차 발생 가능.

// float 타입의 값이 실제로 어떻게 저장되는지 확인
class FloatToBinEx {
	public static void main(String args[]) {
		float f = -9.1234567f;
		int i = Float.floatToIntBits(f);

		System.out.printf("%f%n", f);
		System.out.printf("%X%n", i); // 16진수로 출력
	} // main의 끝
}

5. 형변환


5.1 형변환(캐스팅, casting)이란?

형변환: 변수 또는 상수의 타입을 다른 타입으로 변환하는 것.

5.2 형변환 방법

(타입)피연산자

double d = 85.4;
int score = (int) d; // int score = 85;

형변환 연산자는 그저 피연산자의 값을 읽어서 지정된 타입으로 형변환하고 그 결과를 반환 → 피연산자인 변수 d의 값은 형변환 후에도 아무런 변화가 없음.
기본형에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능.

변환수식결과
int → char(char)65“A”
char → int(int)”A”65
float → int(int)1.6f1
int → float(float)1010.0f

5.3 정수형 간의 형변환

큰 타입에서 작은 타입으로의 변환에서, 경우에 따라 ‘값 손실’이 일어날 수 있다.

class CastingEx2 {
	public static void main(String[] args) {
		int  i = 10;
		byte b = (byte)i;
		System.out.printf("[int -> byte] i=%d -> b=%d%n", i, b);
		
		i = 300;
		b = (byte)i;
		System.out.printf("[int -> byte] i=%d -> b=%d%n", i, b); 

		b = 10;
		i = (int)b;
		System.out.printf("[byte -> int] b=%d -> i=%d%n", b, i); 

		b = -2;
		i = (int)b;
		System.out.printf("[byte -> int] b=%d -> i=%d%n", b, i); 

		System.out.println("i="+Integer.toBinaryString(i)); 
	}
}

/* [int -> byte] i=10 -> b=10
[int -> byte] i=300 -> b=44
[byte -> int] b=10 -> i=10
[byte -> int] b=-2 -> i=-2
i=11111111111111111111111111111110 */

5.4 실수형 간의 형변환

작은 타입에서 큰 타입으로 변환하는 경우, 빈 공간을 0으로 채운다.
float 타입의 범위를 넘는 값을 float으로 형변환하는 경우 +- 무한대 또는 +-0을 결과로 얻는다.

class CastingEx3 {
	public static void main(String[] args) {
		float f   = 9.1234567f;
		double d  = 9.1234567;
		double d2 = (double)f;

		System.out.printf("f =%20.18f\n", f);
		System.out.printf("d =%20.18f\n", d);
		System.out.printf("d2=%20.18f\n", d2);
	}
}
/* f =9.123456954956055000
d =9.123456700000000000
d2=9.123456954956055000 */

5.5 정수형과 실수형간의 형변환

정수형을 실수형으로 변환
정수를 2진수로 변환한 다음 정규화를 거쳐 실수의 저장형식으로 저장.
실수형의 정밀도 제한으로 인한 오차가 발생 가능.
10진수로 8자리 이상의 값을 실수형으로 변환할 때는 float가 아닌 double로 형변환해야 오차가 발생하지 않음.

실수형을 정수형으로 변환
실수형의 소수점 이하 값은 버려짐.
실수의 소수점을 버리고 남은 정수가 정수형의 저장범위를 넘는 경우에는 정수의 오버플로우가 발생한 결과를 얻음.

class CastingEx4 {
	public static void main(String[] args) {
		int   i  = 91234567;  // 8자리의 10진수
		float f  = (float)i;  // int를 float로 형변환
		int   i2 = (int)f;	  // float를 다시 int로 형변환

		double d = (double)i; // int를 double로 형변환
		int   i3 = (int)d;    // double을 다시 int로 형변환

		float f2 = 1.666f;
		int   i4 = (int)f2;

		System.out.printf("i=%d\n", i);
		System.out.printf("f=%f i2=%d\n", f, i2);
		System.out.printf("d=%f i3=%d\n", d, i3);
		System.out.printf("(int)%f=%d\n", f2, i4);
	}
}
/* i=91234567
f=91234568.000000 i2=91234568
d=91234567.000000 i3=91234567
(int)1.666000=1 */

5.6 자동 형변환

서로 다른 타입간의 대입이나 연산을 할 때, 형변환으로 타입을 일치시키는 것이 원칙.
경우에 따라 편의상의 이유로 형변환 생략 가능.
컴파일러가 생략된 형변환을 자동적으로 추가.
서로 다른 두 타입간의 덧셈에서는 두 타입 중 표현 범위가 더 넓은 타입으로 형변환하여 타입을 일치시킨 다음 연산 수행.
산술변환: 연산과정에서 자동적으로 발생하는 형변환.

자동 형변환의 규칙
기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환.
기본형의 자동 형변환이 가능한 방향

  • byte → short → int → long → float → double
  • char → int
  • 화살표방향으로의 변환은 형변환 연산자를 사용하지 않아도 자동 형변환.

0개의 댓글