학습할 것
- 변수란?
- 부동 소수점
- BigInteger와 BigDecimal
- Wrapper 클래스프리미티브 타입
- 레퍼런스 타입
- 변수 선언 및 초기화하는 방법
- 변수의 스코프와 라이프타임
- 접미사(L, D, F)
- 리터럴
- 타입 변환, 캐스팅 그리고 타입 프로모션
- 1차 및 2차 배열 선언하기
- 타입 추론, var
1. 변수
- 자료형: 우리가 사용할 내용의 그릇
- 변수명: 그 그릇의 이름
- 변수 핸들링: 어떤 내용을 사용하기 위해 그릇에 담고 그 그릇을 다루는 일
- 변수명은 사용 목적을 내포해야합니다.
2. 프리미티브 타입
- 비객체 타입
Type | Name | Byte | 유효 저장 범위 | 기본 값 |
논리형 | boolean | 1bit | 0(false) ~ 1(true) | false |
문자형 | char | 2bytes | 0 ~ 2^(16)-1 | '\u0000' |
정수형 | byte | 1byte | -2^(7) ~ 2^(7)-1 | 0 |
short | 2bytes | -2^(15) ~ 2^(15)-1 | 0 | |
(signed) int | 4bytes | -2^(31) ~ 2^(31)-1 | 0 | |
unsigned int | 0 ~ 2^(32)-1 | |||
(signed) long | 8bytes | -2^{63} ~ 2^{63}-1 | 0L | |
unsigned long | 0 ~ 2^(64)-1 | |||
실수형 | float | 4bytes | single-precision 32-bit | 0.0f |
double | 8bytes | double-precision 64-bit | 0.0d |
부동 소수점
부동 소수점은 실수형에서 실수 값을 메모리에 저장하는 방법입니다. 이때 컴퓨터는 메모리에 2진수로 저장을 하므로 1을 기준으로 아래와 같이 각 자리의 합으로 표현합니다.

부동 소수점을 사용하는 대표적인 방법으로는 IEEE 754가 있습니다.
부동 소수점 종류
- single precision
- double precision
- extended precision

부동 소수점 특징
- 특정 값을 정확하게 나타낼 수 없습니다. (Ex. 0.3)
- double precision이 single precision보다 더 많이 표현할 수 있는 만큼 정확도가 높습니다.
특징 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Example {
public static void main(String[] args) {
float f = 0.0f;
double d = 0.0;
for(int i=0; i<100; i++) {
f += 0.01;
d += 0.01;
}
System.out.println("float : "+f);
System.out.println("double : "+d);
}
}
|

0.01은 부동 소수점 표현 방식으로 정확하게 표현할 수 없어서 똑같은 값을 연속으로 더했을 때 1이 아닌 오차가 발생한 것을 볼 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Example {
public static void main(String[] args) {
float f = 0.0f;
double d = 0.0;
for(int i=0; i<100; i++) {
f += 0.0625;
d += 0.0625;
}
System.out.println("float : "+f);
System.out.println("double : "+d);
}
}
|

0.0625는 정확하게 표현 가능하므로 연속으로 더해도 정확하게 나왔습니다.
BigInteger & BigDecimal
- 객체이며, 각 값들은 문자열처럼 불변합니다.
- 오퍼레이터를 사용하지 않고 각 클래스 메서드를 사용하여 연산합니다.
- 연산 결과로 BigInteger와 BigDemcial을 반환하며 불변이므로 새로운 인스턴스를 반환합니다.
- 정수와 실수의 범위를 벗어난 값을 다루고 싶을 때 사용
- 부동 소수점의 경우 오차를 가지고 있는데 BigDemical을 사용하면 오차 없이 사용 가능합니다.
사용 예제
1
2
3
4
5
6
7
8
9
10
11
|
import java.math.BigInteger;
public class Example {
public static void main(String[] args) {
BigInteger a;
a = new BigInteger("123");
a.add(new BigInteger("111"));
System.out.println(a);
a = a.add(a);
System.out.println(a);
}
}
|

불변이므로 새로운 인스턴스 값을 반환해 주어야만 새로운 값으로 변경됩니다.
Wrapper 클래스
- 기본형의 변수를 객체로 사용해야 할 때 사용하는 클래스
- 여러 속성 존재
- 값을 변경하고 싶으면 새로운 인스턴스를 만들어야 합니다.
기본타입 | 변환 | Wrapper 클래스 |
boolean | Boxing => <= UnBoxing |
Boolean |
char | Character | |
byte | Byte | |
short | Short | |
int | Integer | |
long | Long | |
float | Float | |
double | Double | |
void | Void |
Boxing과 UnBoxing 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 |
public class Example {
public static void main(String[] args) {
Integer intAuto = 1234; //Auto Boxing
Integer intBox1 = new Integer(4); //Boxing
Integer intBox2 = Integer.valueOf(1234); //Boxing
intBox1 = (Integer)1234; //Boxing
int unBox1 = intBox1.intValue(); //UnBoxing
int unBoxAuto = intBox2; //UnBoxing
System.out.println(intBox1+intBox2);
System.out.println(intBox1+unBox1);
System.out.println(intBox1 == intBox2);
System.out.println(intBox1.equals(intBox2));
System.out.println(intBox2 == unBox1); }
}
|

두 개의 Integer인스턴스인 intBox1과 intBox2의 값을 비교하기 위해서는 ==연산자를 사용하면 안 됩니다. ==연산자는 인스턴스의 주소를 비교하므로 false가 나옵니다. 따라서 두 값을 비교하기 위해서는 .equals()를 사용해야 하며 다른 연산 오퍼레이터와 인스턴스와 변수의 ==연산의 경우는 자동으로 오토박싱과 언박싱을 해주기 때문에 가능합니다.
3. 레퍼런스 타입
- java.lang.Object를 상속받습니다.
- 객체의 주소를 저장합니다.
- New라는 연산자를 통하여 타입 선언
- 참조 변수 : Stack, 참조 값 : Heap
4. 변수 선언 및 초기화 방법
변수 및 상수 선언
- 클래스 변수 : 클래스 자체 변수, 여러 인스턴스들이 공유하는 변수
- 인스턴스 변수 : 클래스가 공통으로 가지고 있는 변수이지만 독립적으로 값을 가진다.
- 지역 변수 : 블록 내에서만 활용 가능한 변수 일시적인 계산을 위해서 사용
- 상수 : 한 번 지정하면 값이 변경 불가능하며
- 클래스 영역의 Constant pool에 저장됩니다.
- 선언과 동시에 초기화해주어야 합니다.
변수 스코프와 라이프 타임
변수의 종류 | 선언위치 | 생성시기 | 메모리 영역 | 초기화 |
클래스 변수 | 클래스 영역 | 클래스가 메모리에 올라갈 때 | 메서드 영역 | 자동 |
인스턴스 변수 | 클래스 영역 | 인스턴스 생성 시 | 힙 영역 | 자동 |
지역 변수 | 블록 내부 | 블록 내부에서 선언될 때 | 스택 영역 | 필요 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
public class Example {
/*
* 클래스 변수 선언
*/
static int iClassVar;
static Integer intClassVar;
static String sClassVar;
static {
System.out.println("클래스 변수 초기화 블록");
}
/*
* 인스턴스 변수 선언
*/
int iInstanceVar;
Integer intInstanceVar;
String sInstanceVar;
int example;
{
this.example = 5;
System.out.println(this.example+"인스턴스 변수 초기화 블록");
}
Example(int example){
System.out.println(this.example+"생성자 호출");
this.example = example;
}
public static void main(String[] args) {
System.out.println("int클래스 변수: "+Example.iClassVar);
System.out.println("Integer클래스 변수: "+Example.intClassVar);
System.out.println("String 클래스 변수: "+Example.sClassVar);
Example ex = new Example(10);
System.out.println("int인스턴스 변수: "+ex.iInstanceVar);
System.out.println("Integer인스턴스 변수: "+ex.intInstanceVar);
System.out.println("String 인스턴스 변수: "+ex.sInstanceVar);
System.out.println("example: "+ex.example);
/*
* 지역 변수 선언
*/
int i = 1;
Integer In = null;
System.out.println(i);
System.out.println(In);
}
}
|

리터럴
변하지 않는 값이다. const는 변수에 대하여 값을 변경할 수 없게 만든 것이지만 리터럴은 고유한 값이라 생각하면 될 거 같습니다.
String 객체와 리터럴
1
2
|
String s = new String("HI");
String s1 = "HI";
|
String은 문자열을 저장하는 변수입니다. s와 s1 둘 다 HI라는 문자열을 저장했는데 저장하는 방식은 다릅니다.
s의 경우 String 객체를 생성했기에 사용 가능하다 하지만 s1은 constant string pool에서 "HI" literal을 참조하고 있다고만 생각했는데 만약 이때 상수값만 가져오게 된다면 string class의 메서드를 사용하지 못하는 게 아닌가?라는 생각이 들었습니다. 하지만 두 경우 모두 string class의 메서드를 사용할 수 있으므로
s1은 "HI"라는 리터럴을 Constant pool에서 바로 참조하는 것이 아니라 "HI"리터럴을 참조하고 있는 string class object가 Constant pool에 존재하고 이 값을 가져오는 것이 아닌가 라는 생각을 하게 되었습니다.
(접미사 L F D)
자바에서 정수형과 실수형, 각각의 기본 자료형은 Integer와 Double입니다.
1
2
|
int iMax = 2100000000;
System.out.println(iMax);
|
위 코드는 정상적으로 실행이 됩니다. 하지만
1
2
|
int iMax = 21000000000;
System.out.println(iMax);
|
해당 코드는 컴파일 에러가 발생합니다. int의 최대 범위는 21억까지이므로 210억을 넣어서 컴파일 에러가 발생하는 것입니다.
문제는 long자료형 일 때인데
1
2
|
long lMax = 21000000000;
System.out.println(lMax);
|
cs |
long은 8byte로 210억을 넣었을 때 컴파일이 되어야 하지만 컴파일 오류가 뜹니다.

위와 같은 오류가 뜨게 되는데 이를 해결해주기 위해
L을 붙여주어 21000000000L로 변경해 주시면 됩니다.
왜 그럴까?
자바에서 어떤 수를 변수에 저장하기 전에 메모리에 저장하는데 기본적으로 정수형은 int형으로 계산이 됩니다.
타입 변환, 캐스팅 그리고 타입 프로모션
- 캐스팅 : 강제
- 프로모션 : 자동
형 변환
변환할 변수나 리터럴 앞에 (타입)을 붙여 변환합니다. 범위가 작은 byte에서 범위가 큰 byte로의 형 변환은 문제가 되지 않지만 반대로 범위가 큰 쪽에서 범위가 작은 쪽으로의 변환 시 데이터의 손실로 문제가 발생할 수 있습니다.
- 큰 byte에서 작은 byte로의 변환 : 데이터 손실로 강제 형 변환 필요
- 작은 byte에서 큰 byte로의 변환 : 자동으로 형 변환 가능
1
2
3
4
5
6
7
8
9
10
11
|
public class Example {
public static void main(String[] args) {
int i = 10;
long l = 20; // 타입 프로모션
double d = 22.12;
i = (int)d; // 타입 캐스팅
d = l; // 타입 프로모션
System.out.println(i);
System.out.println(d);
}
}
|

상속 관계에서의 형 변환(자세한 건 추후에)
- UpCast : SubCalss -> SuperClass
- 부모 클래스를 통해 서브클래스를 가져와서 사용 가능
- DownCast : SuperClass -> SubClass
- 가지고 있지 않는 특성이 있기에 강제 형 변환이 필요
- UpCast로 잃어버린 자신의 특성을 DownCast로 되찾을 수 있다.
1차 및 2차 배열 선언하기
배열은 같은 자료형을 여러 개 선언했을 때 하나의 변수로 묶어서 처리하기 위해 있습니다.
- 1차원 배열 : 여러 개의 변수가 하나의 묶음
- 2차원 배열 : 묶음이 여러 개로 묶음
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Example {
public static void main(String[] args) {
int[] arr1 = new int[5]; //선언 방법1
int arr2[]; //선언 방법2
arr2 = new int[6];
arr2[1] = 4;
for(int i=0; i < arr1.length; i++) {
arr1[i] = i+1;
System.out.println(i+": "+arr1[i]+"\t"+arr2[i]);
}
arr2[6] = 1; //ArrayIndexOutOfBoundsException
}
}
|

허용된 인덱스를 벗어난 접근 시 런타임 에러(ArrayIndexOutOfBoundsException)가 발생합니다.
추가적으로 선언과 동시에 초기화도 가능합니다 (int[] arr = {1,2,3,4};)

타입 추론, var
- 자바 컴파일러에서 타입을 추론하는 변수 (동적 변수)
- var의 대표적인 사용으로 Foreach가 있습니다. (다른 용도는 추후에 포스트 하겠습니다.)
foreach
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Example {
public static void main(String[] args) {
int[] arr = {1,23,4,5,6,6,7,8};
for(int index: arr) {
System.out.print(index+", ");
}
System.out.println();
for(var index: arr) {
System.out.print(index+", ");
}
}
}
|

arr에 대하여 어떠한 값을 받아오게 되었을 때 특정하기 힘들 때가 있습니다. 이때 자료형 대신 var로 런타임에 추정하게 할 수 있습니다.
'JAVA > 자바스터디' 카테고리의 다른 글
[자바스터디] 4. 선택문, 반복문 (0) | 2022.01.06 |
---|---|
[자바스터디] 3. 연산자 (0) | 2022.01.03 |
[자바스터디] 1.1 컴파일과 실행하는 법 (0) | 2021.12.27 |
[자바스터디] 1. JAVA와 JVM (0) | 2021.12.27 |
[Live Study] 자바 스터디 목차 (0) | 2021.11.07 |