프로그래밍 언어에서 변수란 데이터를 저장하는데 사용된다. 다양한 이름으로 불리는데 객체 / 인스턴스 / 인수/ 인자 등등 상황에 맞게 변경되어 불리지만 의미 어떻게 쓰이나 똑같다. 데이터를 저장하는 곳
각 변수는 특정 유형의 데이터를 저장하도록 선언되며 특정 유형은 변수를 선언시 결정된다.
변수는 크게 기본형과 참조형으로 분류되어 있으며 형에따라 변수의 성격이 달라진다.
_
, $
만 가능하다.기본형은 char, int, long, float, double, boolean으로 각각 "문자형", "정수형", "실수형",논리형"으로 구분된다.
null
값을 할당 할수 없다.public class Main
public static void main(String [] args){
char c = 'a';
int i = 1;
long l = 1;
double d = 0.1;
boolean b = true;
}
}
정수형의 오버/언더플로우
정수형 타입을 사용할때는 데이터의 최소/최대 크기를 고려해야한다.
타입의 크기를 초과하면 오버플로가 발생해 전혀 다른 값이 저장될 위험이 있다.int maxIntValue = 2147483648; //int 최대값 int minIntValue = -2147483648; //int 최소 값
참조형 타입은 위 기본형을 제외한 나머지를 뜻하며, 기본적으로 제공하는 클래스, 배열, 열거 등 모두 참조형이다.
객체의 값을 저장하는 것이 아닌 객체의 주소를 저장한다.
int a = 1; //값 그자체
Age age = new Age();
age = x001 //주소가 할당되어있음
char
와 int
만 이름이 변경된다.char -> Character
int -> Integer
long -> Long
double -> Double
float -> Float
boolean -> Boolean
Java에선 문자열을 위한 String class를 별도로 지원한다.
String class의 내부 요소를 보면 String은 결국 char[]로 이루어져 있고, 참조 자료형으로 분류한다.
여기서 참조형과 기본형의 차이는 원시타입(기본형) 데이터는 stack영역에 저장되면 참조타입(참조형)은 heap영역에 저장되고 주소만 stack영역에 저장된다.
즉, 기본형 => stack, 참조형 => heap -> stack이라고 보면 된다.
Intellij에서 가져온 String 클래스에 대한 설명이다.
String인스턴스는 한번 생성되면 그 값을 읽기만 가능하고, 변경불가이다.
이를 불변 객체(Immutable object)라고한다.
+
연산자로 문자열을 결합하는 것은 기존의 문자열이 변경되는 것이 아니라 새로운 문자열로 생성되는 것이다.
형변환이란 값이 기존 타입을 다른 타입으로 변환하는것이다.
형변환은 메모리에 할당 받은 바이트의 크기가 상대적으로 작은 타입에서 큰 타입으로 형 변환은 생략이 가능하지만 그 반대로 큰 타입에서 작은 타입으로의 형 변환은 데이터의 손실이 발생한다.
예를 들어 500ml의 우유를 1L의 통으로 옮기면 손실이 없지만 1L의 우유를 500ml의 컵으로 옮기면 500ml라는 손실율이 발생하는 것과 같다.
형변환은 bool타입을 제외한 기본형 타입은 서로 형변환이 가능하다.
int -> char = (char)65 -> 'A'
char -> int = (int)'A' -> 65
double -> int = (int)1.4 -> 1
int -> double = (double) -> 1.0
자바의 형변환은 크게 두가지로 분류된다.
개발자가 지정하지 않아도 자동으로 변환이 동작하는 자동(묵시적)형변환,
개발자가 명시해야만 변환이 동작하는 강제(명시적) 형변환으로 분류한다.
이때 위에서 얘기한 바이트의 크기로 형변환의 종류가 결정된다.
int는 4byte long은 8byte이기 때문에 위 처럼 변환이 이루어진다.
자동형 변환은 묵시적 / 암시적 변환이라고 불리기도 한다. 동작의 원리는 프로그램 실행 중 컴파일러에 의해 자동적으로 타입 변화가 일어나는 것을 말한다.
작은 타입에서 큰타입으로 변환이 될떄 발생하는 것이고, 값이 보존된 채로 변환이 이루어지는것이 가장 큰 특징이다.
public class Main{
public static void main(String [] args){
int intValue = 10;
long longValue = 0;
double doubleValue = 0;
longValue = intValue; // int -> long 자동형변환
doubleValue = intValue; // int -> double 자동 형변환
doubleValue = 20L; // Long -> double 자동 형변환
}
}
바이트 크기는 int < long < double
순이다.
//동작순서
intValue = 10;
doubleValue = intValue; //값 대입
doubleValue = (double)intValue; //형변환 시작
doubleValue = (double)10; //변수의 값 읽기
doubleValue = 10.0; //변환
강제 형변환은 명시적 형변환이라고도 하며, 개발자가 타입 캐스트연산자 (type)value
를 사용하여 강제로 변환을 수행하는 것을 말한다.
큰 타입에서 작은 타입으로 변환은 자동으로 이루어 지지않기때문에 개발자가 직접 변환을 해야하고, 값이 보존되지않고 전혀 다른 값으로 변환될 가능성이 있다는 것이 특징이다.
public class Main{
public static void main(String [] args){
double doubleValue = 10.5;
int intValue = 0;
long longValue = 0;
//intValue = doubleValue; 컴파일 오류
intValue = (int)doubleValue; //double -> int 강제형변환
System.out.println("intValue = " + intValue); // 10 손실 값 0.5;
longValue = (long)doubleValue; //double -> long
System.out.println("longValue = " + longValue); //10 손실 값 0.5;
}
}
다시한번 정리하자면, 강제형변환은 말 그대로 강제적인 동직이기 때문에 데이터의 손실이 일어나며 정확한 연산 수행이 불가능하다. 따라서 예상하지 못한 결과값이 출력될 수 있다.
자바의 연산을 진행시 이뤄지는 형변환은 2가지이다.
1. 같은 타입끼리의 계산은 같은타입의 결과를 낸다. (당연한 소리...)
2. 서로 다른 타입의 계산은 큰 타입으로 자동형 변환이 진행된다.
int + long = long + long 으로변환
int + double = double + double 으로 변환