21.04.26(월)~4.27(화)
※ 몰랐던 내용 위주로 정리 ※
2장. 자바 프로그래밍을 위한 변수와 데이터형
01. 변수
p.48
프로그래밍 언어 : 특성에 따라 변수를 선언하는 방식이 구분됨
1. 정적 타입 지정 언어(Statically typed language) : 자바
-> 모든 변수를 반드시 정해진 데이터형으로 선언
2. 동적 타입 지정 언어(Dinamic typed language)
-> 프로그램을 실행할 때 적절한 데이터형이 적용되며 스크립트 언어들이 주로 이 방식 채택
변수 == 메모리 영역에 데이터를 저장할 공간(변수가 저장되는 공간 : JVM의 스택 영역)
p.49
개발자 : 데이터를 가공해서 변수를 다루는 사람
변수명(Variable name) 명명규칙(Naming convention)
- 대소문자 구분(서로 다르게 인식)
- 이름 길이 제한 없음
- 미리 정해진 예약어 사용 불가능
- 숫자로 시작할 수 없음
- 특수문자 : '_'과 '$'만 허용
권장 명명 규칙 : for 통일성, 유지 보수, 협업을 위한 규칙 준수
- 변수와 메소드 이름의 첫 글자는 소문자로 선언
- 여러 단어일 때 첫 번째 단어의 첫 글자는 소문자로선언하고 다음 단어의 첫 글자는 대문자로 선언
ex) int caffeLatte = 1;
- 상수(애플리케이션 안에서 변하지 않게 고정된 데이터) -> 모든 글자를 대문자로 선언
ex) final int COFFEE_DEFAULT_SIZE = 1;
- 반드시 사용 목적을 내포
02. 데이터형의 종류와 사용법
데이터형의 종류
1. 기본형(primitive type) : 자바에서 기본적으로 제공하는 데이터형
- Numeric Type(숫자형)
-> Integral Type(정수형) : byte, short, int, long, char
-> Floating-Point Type(부동소수형) : float, double
- boolean Type :
- returnAddress(주소 반환형)
2. 참조형(reference type) : 보통은 클래스를 의미
- reference : 문자열/날짜..
-> class type
-> interface type
-> array type
정수를 담기 위한 정수형
정수 : 부호가 있는 자연수 (양의 정수 / 0 / 음의 정수
자바 : C 혹은 C++과 다르게 unsigned 타입을 제공하지 않음
-> 즉, 숫자형은 무조건 부호를 갖고 있다.
정수형
- signed : 부호가 있는
- unsigned : 부호가 없는
따라서 자바에서
int num;
은
signed int num;
과 같다 -> signed는 생략 가능
반대로 부호가 없는 자료형을 선언하려면 unsigned를 작성 해주어야 함
signed int num; == int num;
(-2,417,483,648 ~ 2,417,483,647)
unsigned int num;
(0 ~ 4,294,967,297)
★ byte, short, int, long 정수형과 Byte, Short, Integer, Long 참조형은 전혀 다른 데이터형!
-- Wrapper 클래스 : Byte, Short, Integer, Long형 ..
- 기본형의 변수를 객체로 사용해야 할 때 사용하는 클래스
- 데이터는 유지시키고 객체로 사용하기 위해 기본형을 감싸는 역할을 함
-> 이 클래스들은 각 데이터형에 대한 최댓값(MIN_VALUE), 최솟값(MAX_VALUE) 속성을 갖고 있음
정수형의 크기와 표현 범위
데이터형 | 크기 | 기본값 | 표현 범위 |
byte | 8bit = 1byte | 0 | -128 ~ 127 |
short | 16bit = 2byte | -32,768 ~ 32,767 | |
int | 32bit = 4byte | -2,147,483,648 ~ 2,147,483,647 | |
long | 64bit = 8byte | -9,223,372,036,854,775,808 ~ 9,223,372,854,775,807 |
<byte 변수형의 구조>
부호 bit |-----------------------------Value bits----------------------------------|
0|1 | 0|1 | 0|1 | 0|1 | 0|1 | 0|1 | 0|1 | 0|1 |
8bit -> 한 칸은 1bit -> 저장 가능한 데이터 2^8(=256)개
- 첫 번째 bit는 부호(음수, 양수) 정보 저장, 나머지 7개의 bit에 정수 데이터 저장
--> 부호를 제외한 숫자를 표현할 수 있는 영역 : 2^7(=128)
--> 부호와 함께 숫자를 표현할 수 있는 범위 : 음수 -128 ~ -1, 양수 0 ~ 127
- 양수의 최대 절댓값(127)이 항상 음수의 최소 절댓값(128)보다 1이 작은 이유 : 0을 포함하기 때문
Overlflow : 컴퓨터 연산 과정에서 한 단어가 표시될 수 있는 최대 정수보다 큰 수가 입력되어 과잉 유출이 되는 것
- 이미 할당한 공간이 모두 채워져 있는 상태에 추가 데이터 입력이 발생한 것을 의미
package Session1.com.gilbut.chapter2;
// p.053 각 정수형마다 표현 가능한 최솟값과 최댓값
public class NumberRange {
public static void main(String[] args) {
System.out.println("byte range : " + Byte.MIN_VALUE + " ~ " + Byte.MAX_VALUE); // 최솟값, 최댓값을 의미하는 상수
System.out.println("short range : " + Short.MIN_VALUE + " ~ " + Short.MAX_VALUE);
System.out.println("int range : " + Integer.MIN_VALUE + " ~ " + Integer.MAX_VALUE);
System.out.println("long range : " + Long.MIN_VALUE + " ~ " + Long.MAX_VALUE);
byte vlu = 0;
// 0부터 300 미만까지 루프 돌림
for(int i = 0; i < 300; i++) {
System.out.println(vlu++);
} // 0~127 까지 출력된 후 오버플로우 발생 -> 나머지는 -128 -127 ... 0 1 2 ... 43까지 출력함
}
}
byte range : -128 ~ 127
short range : -32768 ~ 32767
int range : -2147483648 ~ 2147483647
long range : -9223372036854775808 ~ 9223372036854775807
0 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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 -128 -127 -126 -125 -124 -123 -122 -121 -120 -119 -118 -117 -116 -115 -114 -113 -112 -111 -110 -109 -108 -107 -106 -105 -104 -103 -102 -101 -100 -99 -98 -97 -96 -95 -94 -93 -92 -91 -90 -89 -88 -87 -86 -85 -84 -83 -82 -81 -80 -79 -78 -77 -76 -75 -74 -73 -72 -71 -70 -69 -68 -67 -66 -65 -64 -63 -62 -61 -60 -59 -58 -57 -56 -55 -54 -53 -52 -51 -50 -49 -48 -47 -46 -45 -44 -43 -42 -41 -40 -39 -38 -37 -36 -35 -34 -33 -32 -31 -30 -29 -28 -27 -26 -25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 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
byte 데이터형 : 네트워크 통신에서 발생하는 데이터값 혹은 시스템의 파일(file)에서 받아들이는 테이터값을 표현하기 위해 주로 사용
명시적 선언을 위한 정수 리터럴
byte value1 = 120;
short value2 = 250;
int value3 = 300;
long value4 = 25000L; // 리터럴(literal)
// 또는
long value4 = 25000l; // 리터럴(literal)
// 또는
long value4 = 25000;
25000이란 변수값은 int형도 저장 가능, long도 저장 가능
-> 확실하게 구분하기 위해 25000이란 값을 리터럴 L과 함께 사용 : long형 데이터라고 선언한 것
정수형 리터럴 중 접미사 L이 붙으면 long 변수형을 나타니며, L이 없는 경우 int 변수형을 의미
정수형 리터럴은 진수법(10, 16, 8, 2진수)에 따라서 표기 방법이 바뀜
진수법 | 접두어 | 표기 숫자 |
10진법 | - | 0 1 2 3 4 5 6 7 8 9 |
16진법 | 0x 또는 0X | 0 1 2 3 4 5 6 7 8 9 A B C D E F |
8진법 | 0 | 0 1 2 3 4 5 6 7 |
2진법 | 0b 또는 0B | 0 1 |
- 0X, 0B와 같이 대문자 이용하기 (0은 모두 숫자 0임)
package Session1.com.gilbut.chapter2;
// p.056 정수 12를 각 진수법에 따라서 표현하고 콘솔 화면에 출력
public class ScaleExample {
public static void main(String[] args) {
int decimal = 12; // 10진수
int hexadecimal = 0XC; // 16진수
int octet = 014; // 8진수
int binary = 0B1100; // 2진수
System.out.println(decimal);
System.out.println(hexadecimal);
System.out.println(octet);
System.out.println(binary);
}
}
12
12
12
12
System.out.println();
-> 기본적으로 정수를 1-진법으로 변환하여 출력해줌
03 char형이 곧 문자형
char형(Character types, 문자형)
-> 앞에서는 정수형의 일부라고 표현했음..
-> 유니코드 : 세상의 모든 문자를 표현하는 문자 세트(Character set), 16bit로 구성되어 65,536개의 문자 표현 가능
-> Char형 : 유니코드를 표현(16bit == 4byte)
-> 유니코드의 코드는 정수, 유니코드에 맵핑된 것은 문자 : 즉, char형은 유니코드를 의미
선언 방법
char firstChar = 'A';
char firstChar = '\u0041';
// 유니코드 사용 시 '\u'를 사용 : 유니코드임을 명시적으로 보여주어야 함
char형 리터럴 문자 표현 : 홑따옴표(''), 유니코드 사용 시 '\u'
cf) 문자열 리터럴 : 쌍따옴표("")
자바 특수문자(escape sequence)
특수 문자 | 특수 자 표기법 | 유니코드 |
backspace(백스페이스) | \b | \u0008 |
tab | \t | \t0009 |
line feed(개행문자) = LF - 커서를 다음 행으로 옮기는 기능 |
\n | \u000a |
carriage return(복귀문자) = CR - 커서를 행의 가장 왼쪽에 위치시키는 역할 |
\r | \u000d |
double quote(쌍따옴표) | \" | \u0022 |
single quote(홑따옴표) | \' | \u0027 |
backslash(역슬래시) | \\ | \u005c |
04 부동 소수형 이해하기
float -> 32bit = 4byte -> 십진법으로 6~7개의 유효 숫자 표현
- 목적 : single precision -> 단순 정확도를 위한 것
double -> 64bit = 8byte -> 십진법으로 15개의 유효 숫자 표현
- 목적 : double precision -> 두 배의 정확도를 위한 것
double형이 float 형보다 표현 범위가 넓어 더 정환가게 데이터 표현 가능
But, float형을 사용하면 보다 빠른 연산 결과 를 얻을 수 있음
보통 int를 제외한 나머지 변수형들은 매우 높은 값까지 저장 가능 -> int의 유효 범위 정도만 알면 됨
부동 소수형 리터럴
변수형 | 리터럴 | 예 |
float형 | 점미사 F 또는 f | float price = 2.99F |
double형 | 접미사 D 또는 d | double pi = 3.1415926535897932384D; |
10진수의 밑수 | E 또는 e | double tax = 0.0299E1; |
-> long형의 리터럴과 마찬가지로 코드의 가독성을 높이기 위해 접미사는 대문자로 표기하는 것을 추천
package Session1.com.gilbut.chapter2;
// p.060
public class FloatPointNumber {
public static void main(String[] args) {
char TAB_CHAR = '\t';
float price = 2.99f;
double pi = 3.1415926535897d;
double tax = 0.299e1;
System.out.println("Variable price" + TAB_CHAR + ": " + price);
System.out.println("Variable pi" + TAB_CHAR + ": " + pi);
System.out.println("Variable tax" + TAB_CHAR + ": " + tax);
float maxFloatValue = Float.MAX_VALUE;
float minFloatValue = Float.MIN_VALUE;
System.out.println("Overflow" + TAB_CHAR + ": " + maxFloatValue * 10);
System.out.println("Underflow" + TAB_CHAR + ": " + minFloatValue / 100);
}
}
Variable price : 2.99
Variable pi : 3.1415926535897
Variable tax : 2.99
Overflow : Infinity
Underflow : 0.0
float형이 표현할 수 있는 최댓값 초과(Overflow) : Infinity
float형이 표현할 수 있는 최솟값을 초과(Underflow) : 0.0
05 불리언형과 참조형 변수
Boolean : true or false 값을 가지는 데이터형(0, 1의 정수 직접 저장X, 리터럴 사용해 저장)
- 1bit의 데이터 크기 -> 오직 두 가지 값만 가질 수 있음 -> 흑백 노릴를 사용하는 로직에서 많이 사용
참조형 변수(Reference type)
참조 변수형 == 클래스 -> 이 클래스가 인스턴스화 되어 생성된 객체 : 참조형 변수
- String, Date 클래스
(기본형을 제외하면 대부분이 클래스)
보통 참조형 : 첫 글자가 대문자(String, Long) -> 모든 클래스의 첫 글자는 대문자로 시작
기본형 : 첫 글자가 소문자(long, int)
package Session1.com.gilbut.chapter2;
import java.util.Calendar;
import java.util.Date;
// p.062 참조형 변수 예제
public class ReferenceExample {
public static void main(String[] args) {
// 참조 변수형 -> 클래스
String lastName = "Kim";
String firstName = new String("Benjamin");
Date endDate = new Date();
Date nowDate = Calendar.getInstance().getTime();
System.out.println("My full name is " + firstName + " " + lastName);
System.out.println(endDate);
System.out.println(nowDate);
}
}
My full name is Benjamin Kim
Tue Apr 27 06:28:27 KST 2021
Tue Apr 27 06:28:27 KST 2021
06 형 변환(Type casting)
변수형을 다른 변수형으로 바꾸는 작업
- 형 변환 연산자 사용 ex (float)
- 주의 : 값 손실, 형 변환 에러
- boolean형(숫자형X, 논리형) 제외하면 모두 형 변환 가능
- 메모리 크기가 더 큰 형으로 변환할 경우 : 묵시적 형 변환 -> 형 변환 연산자를 사용하지 않아도 자동 형 변환
- 반대의 경우 명시적 형 변환 -> 형 변환 연산자 표현
- 보통 기본형 변수 사이 또는 참조형 변수 사이에서만 사용
-> 드물게 참조형 변수에 담긴 데이터를 기본형 형수에 저장하거나 기본형 변수에 담긴 데이터를 참조형 변수에 저장할 수 있음 -> 참조형 변수의 valueOf() 메소드와 같은 형 변환 메소드를 사용해 처리
07 JVM에 저장된 데이터 위치 확인
- Runtime Data Area에 데이터가 저장되고 사용이 끝난 데이터는 소멸된다
- 변수 선언 -> JVM의 메모리 영역인 Heap에 저장
- Heap : 참조형이 저장됨
- Stack : 기본형이 저장됨
package Session1.com.gilbut.chapter2;
// p.066
public class VariableHashcode {
public static void main(String[] args) {
long varLong1 = 32L;
long varLong2 = 32L;
int varInt1 = 32;
System.out.println("varLong1 : " + System.identityHashCode(varLong1));
System.out.println("varLong2 : " + System.identityHashCode(varLong2));
System.out.println("varInt1 : " + System.identityHashCode(varInt1));
int varInt2 = (int) varLong2;
long varLong3 = (long) varInt1;
System.out.println("varInt2 : " + System.identityHashCode(varInt2));
System.out.println("varLong3 : " + System.identityHashCode(varLong3));
String str1 = String.valueOf(varLong1);
String str2 = String.valueOf(varInt1);
String str3 = String.valueOf(varLong1);
System.out.println("str1 : " + System.identityHashCode(str1));
System.out.println("str2 : " + System.identityHashCode(str2));
System.out.println("str3 : " + System.identityHashCode(str3));
/* System.identifyHashCode() 메소드 : JVM 메모리 영역에 저장된 변수의 위치를 반환 -> 해시 코드(Hash Code) : JVM 메모리의 주소명(실제 주소X) */
}
}
varLong1 : 1130478920
varLong2 : 1130478920
varInt1 : 1982791261
varInt2 : 1982791261
varLong3 : 1130478920
str1 : 1562557367
str2 : 1101288798
str3 : 942731712
해시 코드가 같다 -> 두 변수는 JVM 메모리의 같은 주소에 있는 데이터를 참조하고 있다
- String은 저장된 값이 동일해도 해시 코드는 서로 다름
-> String.valueOf() 메소드를 사용해 매번 새로운 데이터를 생성하기 때문
해시 코드를 알아낸다고 해도 우리는 변숫값의 정확한 메모리 주소는 알 수 없음
- 자바에서 생성한 데이터 : JVM Runtime Data 영역에 저장 -> 우리는 그 메모리의 고유 관리번호인 해시 코드만 알 수 있음
- 해시 코드값 : 항상 바뀜, 코드를 다시 실행하면 값이 바뀌어 있을 것 -> JVM이 초기화되면 해시 코드의 값도 바뀜
--> JVM 메모리 영역(힙 영역) 어느 곳이든 데이터가 생길 수 있으며, 그 위치는 개발자가 직접 정할 수 없기 때문
[null 키워드로 메모리를 효율적으로 관리]
기본형 변수 - 변수값을 설정하지 X면 그 변수형에 따라 기본값이 존재
ex) int형 : 0, boolean형 : false
참조형 변수 - 기본값이 존재하지 않음
-> 값이 없는 상태로 변수 이름만 가지고 있음 -> null 값을 갖고 있다
지금까지 살펴본 예제 : 모든 변수에 값을 넣어 사용 -> 메모리에 데이터를 새롭게 생성했다 -> 메모리 사용량 증가
애플리케이션의 성능을 높이기 위해 항상 힙 영역의 메모리 관리에 신경 쓰면서 코딩해야 함
힙 영역에 데이터를 생성하지 않고 변수를 선언하기 위한 방법
String param = null;
-> param이라는 변수 : JVM 메모리에서 참조하는 변수값이 없음
-> 값이 없는 변수라도 param이라는 변수명은 초기화됨 -> param이라는 변수명 사용 가능
-> null로 선언 후 필요에 따라 새로운 문자열 데이터를 넣을 수도 있고, 사용하지 않고 프로그램을 끝낼 수도 있음
* 주의
null != 공백(blank, " ")
package Session1.com.gilbut.chapter2;
// p.069 null과 blank
public class VariableHashcode2 {
public static void main(String[] args) {
String varStr1 = "";
String varStr2 = null; // 변수 이름만 생성하기 위해 null 값을 대입하는 경우
System.out.println("varStr1 : " + System.identityHashCode(varStr1)); // 405662939
System.out.println("varStr3 : " + System.identityHashCode(varStr2)); // 0
}
}
varStr1 : 405662939
varStr3 : 0
null 키워드의 특수성 -> null 키워드로 선언한 변수의 해시 코드는 항상 0
blank("", 빈값)는 문자로 JVM에서 하나의 메모리를 참조하고 있음
===> blank 문자와 null 키워드는 서로 같지 않으며 자바를 다를 때 항상 구분해서 사용!!
Java의 메모리 : Stack과 Heap ??
2021.04.27 - [프로그래밍/자바(JAVA)] - [메모리 구조] 자바의 메모리 구조
'프로그래밍 > 자바(JAVA)' 카테고리의 다른 글
[패스트캠퍼스 서포터즈 4기] 한번에 끝내는 Java Spring 인강 - 웹 개발 마스터 (0) | 2021.08.15 |
---|---|
[자바를 다루는 기술 Vol.2] Session3 자바에서 사용하는 연산자 & 연산 (2) | 2021.04.27 |
[자바 미니 프로젝트] 참고 사이트 (0) | 2021.02.05 |
[복습] 4일차 복습 - 22일차2 ~ 23일차 복습(클래스, 객체) 진행 중 (0) | 2021.01.16 |
[복습] 3일차 복습 - 자바 기본(21일차 배열, 난수) (0) | 2021.01.15 |