일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Method
- HTML
- Database
- java
- String
- 프로그래밍
- SQL
- jsp
- 서블릿
- function
- JavaScript
- web
- Python
- 메소드
- 문자열
- oracle
- frontend
- 자바
- 자바스크립트
- 함수
- 파이썬
- It
- PL/SQL
- 코딩
- Servlet
- 데이터베이스
- 오라클
- Programming
- 프론트엔드
- 웹
- Today
- Total
Untitled_Blue
[JAVA] 데이터 타입 - 기본형, 참조형 본문
안녕하세요. 두 번째 자바 글입니다.
이번에는 데이터 타입 자료형에 대한 설명입니다.
- 자료형이란?
자료형을 알기 전에 변수에 대한 설명부터 먼저 하겠다. 변수를 쉽게 어느 하나의 저장 공간이라고 생각하면 될 것이다. 여기서 "메모리 공간을 만들면서 동시에 이름을 부여하는 이름"을 변수라고 한다.
그리고 변수에 어떤 종류의 데이터를 저장할 것인가를 지정해야 한다. 어떤 데이터는 숫자를 저장할 것이고 그 안에서도 필요한 용량 내지 공간이 제각각 다를 것이며 저장하는 목적 또한 다양할 것이다. 이를 확실히 지정해둘 필요가 있다.
여기서 필요한 것이 자료형이며 자료형은 "저장하고자 하는 각각의 데이터에 맞는 종류와 용량을 규격화해둔 일종의 타입"을 의미한다. 이 말은 곧 자료형에 따라 저장가능한 데이터의 종류가 다르다는 의미이다.
- 자료형과 변수 사용법
int age = 20;
String name = "홍길동";
double cpa = 4.5;
상단 소스코드처럼 변수를 선언하기 전 반드시 자료형을 작성해야 한다. 앞서 변수는 하나의 공간을 선언하는 것이라고 언급했다. 우리가 마치 살면서 거주할 공간을 마련하는 것에 비유할 수 있다. 그러나, 아무리 본인이 살고 싶은 아파트가 있어도 해당 세대에 공실이 없으면 살 수 없지 않은가? 이러한 상황이 있으니까 우리는 집을 구할 때도 공실이 있는 매물을 계약해서 입주한다. 자료형과 변수 관계도 이와 다를 것이 없다고 생각한다. 먼저 변수라는 공간을 선언하기 전에 메모리에 어느 정도의 공간을 확보해야 한다. 그리고 해당 공간에 변수를 선언함으로서 '이 공간은 나의 장소다.'라고 자리를 잡는 것이다. 그렇기 때문에 변수 앞에 반드시 자료형을 선언해야 한다.
추가로 소스코드에서 나이를 저장하기 위해 int라는 자료형을 선언해서 20이라는 값을 저장했다. 나이를 표현하기 위해 정수형을 선언하였고, 이름을 저장하기 위해 String이라는 문자열을 선언했다. 이렇듯 사용하고자 하는 목적과 값의 종류에 따라 선언해야 하는 자료형은 제각각이다.
- 자료형의 종류
자료형은 크게 기본 자료형과 참조 자료형으로 분류할 수 있다. 간단하게 각 자료형에 대한 설명을 한다면 먼저 기본 자료형은 크게 자바 기준으로 8가지가 있다. 8가지는 정수형인 byte, short, int, long이 있고 실수형인 double, float 논리형인 boolean과 문자형인 char가 있다. 이 외 나머지 배열, String 문자열 등 객체를 저장하는 자료형은 모두 참조 자료형이다.
이 둘의 차이가 존재하는데 가장 큰 이유는 '실제 데이터 값의 저장 위치'가 다르다는 점이다.
물론 기본 자료형과 참조 자료형을 기반으로 하는 변수의 공간은 모두 스택 메모리에 생성된다. 그러나 저장되는 값이 어떤 것인가에서 차이가 난다. 먼저 기본 자료형은 스택 메모리에 변수의 공간에 해당 실제 값을 함께 저장하는 반면 참조 자료형은 실제 값을 힙 메모리에 저장하고 스택 메모리에는 변수의 공간과 함께 실제 값이 들어있는 힙 메모리의 주소값이 저장되어있다. 참조 자료형은 말 그대로 'Reference' 사전적 의미처럼 가리키는 방식으로 주소값이 가리키는 값을 참조한다.
(이에 대한 자세한 설명은 이전 포스트 '자바의 기본 구조'에 언급되어있다. 참고하는 것을 추천한다.)
해당 포스트 링크 : https://untitedblue.tistory.com/3
[JAVA] JAVA의 기본 구조
안녕하세요. 자바 첫 포스팅입니다. 다소 부족하더라도 양해 부탁드립니다. - 자바 소스 코드의 실행 과정 먼저 이클립스를 기준으로 소스 코드를 입력하고 컴파일 버튼을 클릭하면 컴파일러에
untitedblue.tistory.com
- 기본 자료형의 종류와 저장 가능한 범위
자료형 | 자료형의 크기 | 표현 가능한 범위 | |
논리형 | boolean | 1 Byte | true, false |
정수형 | byte | 1 Byte | -128 ~ 127 |
short | 2 Byte | -32,768 ~ 32,767 | |
int | 4 Byte | -2,147,483,648 ~ 2,147,483,649 |
|
long | 8 Byte | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,809 |
|
실수형 | float | 4 Byte | ±(1.40 x 10 ^ -45 ~ 3.40 x 10 ^ 38) |
double | 8 Byte | ±(4.94 x 10 ^ -324 ~ 1.79 x 10 ^ 308) |
|
문자형 | char | 2 Byte | Unicode 문자 |
상단의 표에서 알 수 있듯이 자료형의 크기가 클수록 표현 가능한 범위 또한 증가한다. 이 때 정수형과 실수형에서 바이트 수가 같지만 사용하는 목적 내지 표현 가능한 종류가 다르다는 점을 확인할 수 있다. 이에 대한 해답은 표현 가능한 범위에서 확인할 수 있는데 실수형은 자료형과 다르게 소수점도 같이 표현해야 되기 때문에 부동 소수점을 사용했기 때문이다.
+ 부동 소수점 : 실수를 컴퓨터상에서 근사하여 표현할 때 소수점의 위치를 고정하지 않고 그 위치를 나타내는 수를 따로 적는 것 (출처 : 위키피디아)
package classes;
public class Main {
public static void main(String[] args) {
int a = 30;
//int a2 = 30.5; // Compile Error
byte b = 127;
//byte b2 = 128; // Compile Error
double c = 30.5;
float d = 560.7f; // double과 다르게 float는 숫자 뒤에 f를 붙여야 한다.
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
[ 상단 소스코드에 대한 실행 결과 화면 ]
해당 코드에서 자료형에 따라 표현 가능한 범위가 명확하게 정해져 있다는 점을 확인할 수 있다.
또한 실수형 중에서도 float의 경우에는 숫자 뒤에 'f'라는 문자를 반드시 붙여야 된다.
왜냐하면 보통 실수형은 기본적으로 double를 기준으로 인식하고 있기 때문이다.
byte 형식의 b2에 128을 대입했는데 오류가 발생했다. 이는 byte라는 자료형의 표현 가능한 범위를 초과했기 때문이다.
b2를 정상적으로 사용하기 위해서는 byte보다 큰 범위의 자료형으로 바꿔야 한다.
다음으로 int 형식의 a2의 경우에는 30.5를 대입했는데 오류가 발생했다. int는 명백한 정수를 수용하기 위한 자료형이기 때문에 실수형을 받을 수 없다. 또한 자바에서는 30.5라는 자료형을 double로 인식하기 때문인 점도 존재한다.
이를 해결하기 위해서는 해당 코드를 int a2 = (double)30.5; 또는 double a2 = 30.5;로 변경해야 한다.
여담으로 앞으로 코딩하면서 자료형에 대한 형변환을 마주하게 될텐데 간략하게 설명하면 작은 자료형에서 큰 자료형으로 변환할 때는 상관없으나 큰 자료형의 데이터를 작은 자료형의 변수에 대입할 경우에는 대입받을 변수의 공간의 한계로 인해 오류가 발생한다. 이를 해결하기 위해서 반드시 ()를 통해 값 좌측에 변환하고자 하는 자료형을 명시해야 한다.
그렇기 때문에 개인적으로 표를 모두 외우는 것이 아니라 바이트 수가 작은 것부터 큰 것으로의 방향으로 자료형의 순서를 숙지해두는 것을 추천한다.
- 참조 자료형
참조 자료형은 크게 배열, 열거, 클래스 인터페이스로서 4가지가 있다. 이들은 존재하지 않는 값(어떠한 것도 입력하지 않는 기본값)을 Null로 표현되고 있는 것이 특징이다. (참고로 기본 자료형은 각각 0, true, 0.0 등으로 기본 값이 정해져 있다.)
현재 글에서는 String을 우선적으로 핵심 내용 위주로 설명할 것이며 나머지 객체, 배열 등은 차차 설명해나갈 것이다.
참조 자료형 중에서도 대표적으로 가장 자주 쓰이게 될 String이라는 문자열 클래스가 있다. 이는 하나하나의 문자를 여러 개로 구성되는 방식으로서 한 글자 이상의 문자를 표현하기 위한 자료형이다.
상단의 그림과 같이 String 문자열은 말그대로 char 형식의 문자형을 배열 형식으로 구성된 참조 자료형이다.
또한 불변형의 성격을 가진 객체이다.
package classes;
public class Main {
public static void main(String[] args) {
String value = "Hello";
String value02 = "Hello";
System.out.println(value.hashCode());
System.out.println(value.hashCode());
value = "Tistory";
String value03 = "Hello";
System.out.println(value.hashCode());
System.out.println(value03.hashCode());
}
}
다음은 소스코드에 대한 실행 결과이다.
이를 통해 각 문자열에 대한 해시코드를 확인할 수 있으며 다른 값을 대입하면 다른 해시코드가 표시되는 것을 확인할 수 있다. 또한 다른 ,String 변수에 이전에 사용했던 값을 사용하면 같은 해시코드가 표시되는 것도 확인할 수 있다.
상단 이미지와 같이 기존 문자열에서 또 다른 문자열로 바꾸는 과정에서 최초로 생성했던 String 객체가 바뀌는 것이 아닌 바뀐 문자열에 대한 새로운 String 객체를 생성함으로써 해당 객체에 대한 주소값을 참조하는 것이다. Heap 영역에는 기본에 생성했던 객체가 사라지는 것이 아니라는 점 때문에 다른 String 객체가 기존에 생성했던 객체에 대한 주소값을 사용할 수도 있다. (상단 String에 대한 hashCode() 사용한 코드 참고)
+ String이 불변형 상수인 이유 : '캐싱', '보안성', '안전성'
* 캐싱 : 이는 곧 메모리 절약으로 이어진다. String은 자바에서 많이 사용되는 자료형 중 하나이다. 그만큼 웹을 기준으로 같은 문자열을 수도 없이 불러와야할 것이다. 그럴 때마다 일일이 새로 생성하고 삭제하기에는 메모리 공간을 많이 차지하고 시간이 상대적으로 오래 소요된다. 이러한 점 때문에 String을 객체와 주소값을 사용해서 객체가 메모리 주소값을 참조하는 방식을 사용해서 다른 변수 또는 객체들이 문자열을 공유하는 방식을 사용한다.
* 보안성 : 불변성을 다루는 있는 만큼 또한 참조 자료형이 많이 쓰인다는 점이 있는 만큼 외부로 인해 데이터가 쉽게 변경된다면 보안성과 안정성에 치명적인 위험이 있기 때문에 불변형을 사용해서 해당 객체의 정보를 변경할 수 없게 되어있다.
* 안전성 : 멀티 스레드 환경에서 하나의 객체를 참조하는 상황에서도 안정적으로 작동된다는 의미이다. 동기화가 되지 않기 때문에 더 안전하게 사용할 수 있다. 여기서 자바에서 얘기하는 동기화는 "여러 스레드가 하나의 자원을 사용하는 상황에서 해당 스레드를 제외하고 나머지 스레드의 접근을 제한하는 과정"을 의미한다. 이렇게 되면 막상 필요한 곳에서 해당 객체를 참조 못하는 상황이 발생할 수 있다.
+ String 선언하는 방법 (new 연산자, 리터럴 방식)
package classes;
public class Main {
public static void main(String[] args) {
String value = "Hello";
String value02 = new String("Hello");
System.out.println(value == value02);
System.out.println(value.equals(value02));
}
}
Heap 영역에서 재사용의 확률이 높은 문자열들은 String Pool에 저장된다. Literal 방식의 String 객체에 한해 언제든 참조하는 방식으로 다시 사용하기 위해 String Pool이라는 곳에 별도로 저장해둔다. 그렇기 때문에 value과 value02 모두 같은 값을 참조하면서 참조에 대한 주소값이 동일할 수 있다.
반면, new 연산자를 통한 문자열은 애초에 new를 사용해서 새로 선언한 것이기 때문에 String Pool이 아닌 Heap 영역에 별도로 저장된다. 아무리 같은 Hello 여도 저장되어 있는 영역이 다르기 때문에 같은 주소값이 아니다.
해당 부분은 String 관련 메서드를 주제로 하는 글에서 다룰 예정이다. 여기서 new와 Literal의 논리값을 비교할 예정이다.
'Programming Language > JAVA' 카테고리의 다른 글
[JAVA] String 메소드 1 - charAt(), length(), isEmpty(), concat(), contain(), trim(), toCharArray() (0) | 2023.05.06 |
---|---|
[JAVA] 배열 (0) | 2023.05.03 |
[JAVA]제어문 (0) | 2023.04.27 |
[JAVA] 연산자 (1) | 2023.04.25 |
[JAVA] JAVA의 기본 구조 (1) | 2023.04.17 |