Chapter 2 :)  변수

1. 변하는 것(변수)과 변하지 않는 것(상수)

저장공간의 선언

  • Java 프로그램에서 값을 다루기 위해서는 값을 저장해둘 저장공간의 선언이 필요
  • 선언할때는 저장공간에 담을 값의 타입과 이름을 명시하여 선언
    • 값의 타입 : 저장공간의 종류
    • 값의 이름 : 저장공간의 이름

 

값의 저장

  • 초기화 : 선언과 동시에 값을 저장
  • 덮어쓰기 : 선언 이후에 값을 저장
// 초기화
int num1 = 10;
// 덮어쓰기
num = 100;

 

변수

  • 변하는 저장공간
  • Java 프로그램에서 저장하는 대부분의 값들은 변하는 것. 즉, 변수임
  • 하나의 값을 저장할 수 있는 저장공간
  • “저장공간”이라고 표현한 이유는 “변하는 것”이라는 의미에 맞게 저장하고 있는 값이 달라질 수 있음
  • 저장공간에 이름(변수명)을 붙여서 필요한 값을 저장해둠
  • 저장되는 값의 형태에 따라서 여러가지 모습을 지니게 됨
int number = 10; // 1. 변수로 선언 및 초기화
number = 11; // 2. 변수의 값을 바꾼다. (덮어쓰기)

 

상수

  • 변하지 않는 저장공간
  • Java 프로그램에서는 변하지 않을 값을 변하지 않는 저장공가네 저장해둠
  • “변하지 않는 저장공간”이라고 표현한 이유는 저장효율을 위해 “변하지 않을 값”을 따로 저장하는 공간이 있기 때문
  • 저장되는 값의 형태에 따라서 여러가지 모습을 지니게 됨
final int number = 10; // 1. 상수로 선언 (데이터 타입 앞에 final을 붙이면 됨)
number = 11; // e2. 변수의 값을 바꾸려고하면 에러가 납니다!

2. 저장공간의 종류 (변수 타입)

기본형 변수

  1. 논리형 변수 : boolean
    • True / False 값만 저장
    boolean flag = true; // 1. 논리형 변수 boolean 으로 선언 및 True 값으로 초기화
    flag = false; // 2. False 값으로도 저장할 수 있습니다.
    
  2. 문자형 변수 : char
    • ‘A’, ‘1’과 같은 문자 하나만 저장
    char alphabet = 'A'; // 문자 하나를 저장합니다.
    
  3. 정수형 변수 : byte, short, int, long
    • 0, 1, 99와 같은 정수형 숫자값을 저장
    • 정수형 변수 표현 범위 ⇒ 각 변수 표현 범위를 넘는 숫자를 넣게되면 오버플로우 발생
      • byte(1) : -128 ~ 127 범위의 숫자만 저장 가능
      • short(2) : -32,768 ~ 32,767 범위의 숫자만 저장 가능
      • int(4) : -21억 ~ 21억 범위의 숫자만 저장 가능
      • long(8) : 9백경 정도의 매우 큰수를 저장 가능
    byte byteNumber = 127;
    short shortNumber = 32767;
    int intNumber = 2147483647;
    long longNumber = 2147483647L;
    
    🤓 정수형 리터럴 구분값 (리터럴 = 데이터값) 
    -> int 와 long 의 데이터값(리터럴)을 구분하기 위한 구분자로 long으로 담을 숫자뒤에 L을 붙임.
    이런식으로 데이터값(리터럴) 뒤에 붙이는 구분값을 “접미사”라고 부름
  4. 실수형 변수 : float, double
    • 0.123, 0.9999와 같은 소수점 실수값을 저장
    • 실수형 변수의 표현 범위 ⇒ 실수는 표현범위가 매우 넓어서 정수형 변수에서 담지 못할 수 있음
      • float(4) : 3.4 * -10^38 ~ 3.4 * 10^38(long 보다 큼)범위의 숫자 저장이 가능
      • double(8) : 1.7 * -10^308 ~ 1.7 * 10^308(long 보다 큼)범위의 숫자 저장이 가능
    float floatNumber = 0.123f;
    double doubleNumber = 0.123123123;
    
    🤓 실수형 리터럴 구분값(리터럴 = 데이터값)
    -> float 와 double 의 데이터값(리터럴)을 구분하기 위한 구분자로 float으로 담을 숫자뒤에 f 를 붙임
    
    🤓 float 는 4byte 만쓰는데 어떻게 long 보다 더 넓은 범위를 표현가능한가요?
    -> float 라는 단어의 뜻은 “부동” 이라는 의미를 가지고 있으며
    소수점이 움직인다는 의미의 “부동 소수점 방식”으로 숫자를 저장합니다.
    - 부동 소수점 방식 : 가수와 지수를 구분해서 저장하고 이값들을 곱한 값을 저장(표현)하는 방식 입니다.
    ✋ float 가 long 보다 더 넓은 범위를 표현하기 때문에 자동 형변환이 안됨
     

참조형 변수

  1. 문자열 변수 : String
    • “텍스트”, ”apple”과 같은 문장을 저장
    String message = "Hello World"; // 문자열을 저장
    
  2. 그 외 : Object, Array, List …
    • 객체, 배열, 리스트와 같은 단일 저장공간에 담을 수 없는 값을 저장
    List<int> alphabet = [0,1,2,3]; // 기본형 변수 여러개를 저장
    
    int[] a = {1, 2, 3};
    System.out.println(Arrays.toString(a));
    
    // 출력
    // [1, 2, 3]
    

 

래퍼 클래스 변수

  • 기본형 변수를 클래스로 한번 랩핑(감싸는) 변수
  • 기본형 변수 타입명에서 첫글자를 대문자로 바꾸어서 래퍼 클래스를 정의

  • 박싱 vs 언박싱
    • 박싱 : 기본 타입에서 래퍼 클래스 변수로 변수를 감싸는 것
    • 언박싱 : 래퍼 클래스 변수를 기본 타입 변수로 가져오는 것
    // 박싱 VS 언박싱
    
    // 박싱
    // Integer 래퍼 클래스 num 에 21 의 값을 저장
    int number = 21;
    Integer num = number;
    
    // 언박싱
    int n = num.intValue(); // 래퍼 클래스들은 inValue() 같은 언박싱 메서드들을 제공해줌
    
  • 래퍼 클래스를 사용하는 이유
    • 클래스로 변수를 관리하면서 객체지향의 많은 지능을 사용할 수 있기 때문

 

숫자와 문자

  • 숫자(int)를 문자(char)로 매핑해서 표현
  • 숫자 -> 문자
// 숫자 -> 문자
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		int asciiNumber = sc.nextInt();
		char ch = (char)asciiNumber; // 문자로 형변환을 해주면 숫자에 맞는 문자로 표현됨

		System.out.println(ch);
	}
}

// 입력
97

// 출력
a
  • 문자 -> 숫자
// 문자 -> 숫자
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
        
		// 첫번째 글자만 받아오기위해 charAt(0) 메서드를 사용
		char letter = sc.nextLine().charAt(0);

		// 숫자로 형변환을 해주면 저장되어있던 아스키 숫자값으로 표현됩니다.
		int asciiNumber = (int)letter;

		System.out.println(asciiNumber);
	}
}

// 입력
a

// 출력
97

 

문자와 문자열

  • 선언 관점에서 차이점
    • 문자 (char)
      • 문자 한개만 저장하며 따옴표를 사용하여 값을 지정
    • 문자열 (String)
      • 문자 여러개를 문장형태로 저장하며 쌍따옴표를 사용하여 범위를 지정
  • 저장 관점에서 차이점
    • 문자 (char)
      • 문자 뒤에 \0(널문자)가 없음
      • 1byte만 쓰기 때문에 끝을 알아서 데이터만 저장하면 됨
    • 문자열 (String)
      • 문장의 끝에 \0(널문자)가 함께 저장이 됨
      • 몇 개의 byte를 쓸지 모르기 때문에 끝을 표시해야 함

 

참조형

  • 참조형 변수 = 주소형 변수
    • 다른 기본형 변수가 실제 값을 저장하는 저장공간이라면, 참조형 변수는 실제 값이 아닌 원본값의 주소값을 저장함
    • 기본형 변수 : 원본값이 Stack영역에 있음
    • 참조형 변수 : 원본값이 Heap 영역에 있음
      • Stack 영역에는 따로 저장 해둔 원본값의 Heap 영역 주소를 저장저장 관점에서 차이점
🤓 Stack 영역 vs Heap 영역

- Stack의 경우에는 정적으로 할당된 메모리 영역
    - 그래서, 크기가 몇 byte 인지 정해져 있는 기본형 변수를 저장
    - 추가로, 크기가 정해져 있는 참조형 변수의 주소 값도 저장
- Heap의 경우에는 동적으로 할당된 메모리 영역
    - 그래서, 크기가 계속 늘어날 수 있는 참조형 변수의 원본을 저장

 

입력 & 출력

  • 입력
Scanner sc = new Scanner(System.in); // Scanner 객체를 new 명령어로 생성
String input = sc.next();  // sc(Scanner)의 .next(); 를 실행하면 input 변수에 입력한 글자를 받을 수 있습니다.
  • 출력
Scanner sc = new Scanner(System.in);
String input = sc.next();  

System.out.println("입력값 : " + input);  // 입력한 글자를 출력합니다.

// 실행 결과
{입력}
입력값 : {입력}

// 인텔리제이에서 sout를 입력하면 출력 코드가 작성됨

 

3. 변수 타입 바꾸기 (형변환)

형변환에 대한 이해

  • 형변환은 주로 기본형 변수인 정수 <-> 실수 <-> 문자 들 사이에서 일어남

 

정수형, 실수형 간 발생하는 형변환

  • 정수 <-> 실수 간에 변환할 때는 ({원하는 타입}) 명령을 통해 변환 가능 (캐스팅)
// (Int)캐스팅 방식으로 실수를 정수로 치환하는 방법
// 이때 실수형의 소수점아래자리는 버려짐

double doubleNumber = 10.101010;
float floatNumber = 10.1010

int intNumber;
intNumber = (int)doubleNumber; // double -> int 형변환
intNumber = (int)floatNumber; // float -> int 형변환
//(Double,Float) 캐스팅으로 정수형을 실수형으로 변환하는 방법

int intNumber = 10;

double doubleNumber = (double)intNumber; // int -> double 형변환
float floatNumber = (float)intNumber;  // int -> float 형변환

 

자동 형변환

  • 프로그램 실행 도중에 값을 저장하거나 계산할 때 자동으로 타입변환이 일어남
  • 작은 크기의 타입에서 큰 크기의 타입으로 저장될 때 큰 크기로 형변환이 발생

🤓 변수 타입별 크기 순서

byte(1) -> short(2) -> int(4) -> long(8) -> float(4) -> double(8)

byte byteNumber = 10;
int intNumber = byteNumber;    // byte -> int 형변환
System.out.println(intNumber); // 10

char charAlphabet = 'A';
intNumber = charAlphabet;   // char -> int 형변환
System.out.println(intNumber); // A의 유니코드 : 65

intNumber = 100;
long longNumber = intNumber; // int -> long 형변환
System.out.println(longNumber); // 100

intNumber = 200;
double doubleNumber = intNumber; // int -> double 형변환
System.out.println(doubleNumber); // 200.0  (소수점이 추가된 실수출력)
  • 작은 크기의 타입이 큰 크기의 타입과 계산될 때 자동으로 큰 크기의 타입으로 형변환이 발생
int intNumber = 10;
double doubleNumber = 5.5;
double result = intNumber + doubleNumber; // result 에 15.5 저장됨 (int -> double)

intNumber = 10;
int iResult = intNumber / 4; // iResult 에 2 저장됨 (int형 연산 -> 소수점 버려짐)

intNumber = 10;
double dResult = intNumber / 4.0; // dResult 에 2.5 저장됨 (double형 연산 -> 소수점 저장)

 

🤓 자동 형변환 vs 강제 형변환

  • 작은 타입 > 큰 타입 형변환시 (자동 형변환)
    • 더 큰 표현범위를 가진 타입으로 변환되는것이라 값의 손실이 없음
    • 값의 손실없이 변환이 가능하기 때문에 컴파일러가 자동으로 형변환을 해줌
  • 큰 타입 > 작은 타입 형변환시 (강제 형변환 = 캐스팅)
    • 더 작은 표현범위를 가진 타입으로 변환된는것이라 값의 손실이 생김
    • 값의 손실이 생기기 때문에 자동으로 형변환을 해주지 않고 개발자가 선택하여 형변환을 함

BELATED ARTICLES

more