2022.05.31 - [JAVA] - [Snack Java] 3. 자바의 문자열 클래스: 심화(StringTokenizer, StringBuilder, StringBuffer)
[Snack Java] 3. 자바의 문자열 클래스: 심화(StringTokenizer, StringBuilder, StringBuffer)
2022.05.31 - [JAVA] - [Snack Java] 1. 자바의 타입(Type of JAVA) 2022.05.31 - [JAVA] - [Snack Java] 2. 자바의 문자열 클래스(String Class) 문자열을 다루기 위해 만들어진 클래스를 알아봤으니 조금 더 심..
yunjuniverse.tistory.com
앞선 글에서도 조금씩 등장했던 변수(variable)와 상수(constant), 리터럴(literal), 형변환(type casting)에 대해 자세히 알아보자
1. 변수(Variable)
변수(變數, variable)의 뜻을 풀이해보자
한자로 변수(變數)는 변하는 수를 나타내며, 영문명인 variable은 vary(다르게 하다, 변화를 주다) -able(할수 있는)의 합성어로 '변화를 줄 수 있는 것'을 말한다. 즉, 컴퓨터 과학에서 변수는 변할 수 있는 수이자 데이터를 말한다.
그런데 이 변하는 수, 데이터를 그대로 쓸 수가 없다. 9, 10, 20, 14 등 다양한 형태로 변하는 데이터를 가리킬 수 없기 때문이다. 따라서 이 변수를 담을 그릇이자 이름표를 할당해주어야 한다.
String name = "Yunjuniverse";
위 예제가 데이터에 변수를 할당하는 방법이다.
1. (String)변수의 데이터의 타입 선언: 변수 또한 데이터이다. 따라서 변수를 담을 공간(메모리 크기)을 미리 지정해주어야 한다. 자바에서 변수를 선언할 때는 메모리의 크기를 알려주기 위해 데이터 타입을 먼저 선언해준다. 위 예제에서는 String 참조타입을 선언해주었다.
2. (name) 변수의 이름 선언: 이제 변수를 담을 이름을 선언해준다. 이를 통해 사용자는 변하는 데이터를 가리킬 수 있다. 자바에서 변수의 이름을 선언할 땐
1) 숫자로 시작하지 않는다. 1name-> (X)
2) 예약어를 쓰지 않는다. class -> (X)
3) 소문자로 시작한다. Name -> (X)
4) 명사형으로 이름을 짓는다. make -> (X)
5) 카멜케이스를 이용해 띄어쓰기를 구분한다. cocaCola
이외의 다른 규칙들은 이전에 쓴 글을 참조하자. (식별자 부분 참고)
2022.05.30 - [JAVA] - 객체지향을 위한 자바 언어의 구조와 원칙
객체지향을 위한 자바 언어의 구조와 원칙
객체지향에 대해 모르신다면 본 글을 읽으시기전에 꼭 이전 발행 글을 읽으시길 권장합니다. 2022.05.16 - [컴퓨터 사이언스] - 객체지향 프로그래밍, 그 철학에 관하여 - 1 기초 개념, 탄생 배경 객
yunjuniverse.tistory.com
3. (=) 할당자로 데이터 할당: 할당 연산자를 이용해 데이터를 변수에 할당한다.
4. ("Yunjuniverse") 데이터 선언: 변수에 할당할 데이터를 선언한다. 여기에서는 String의 형식인 쌍따옴표로 둘러싼 데이터를 선언했다.
5.(;) 세미콜론으로 문장 끝 선언: 자바에서는 하나의 선언문이 완료되면 세미콜론으로 마지막을 알려준다.
변수는 변할 수 있는 데이터를 담을 하나의 그릇이기 때문에 아래와 같이 굳이 먼저 데이터를 선언해주지 않아도 된다.
변수를 선언한다는 것은 메모리 상에 값을 저장할 공간을 확보하고 이름을 붙이는 것이다. 따라서 변수를 선언하면 컴퓨터에 공간이 얼만큼 필요한지 알려준다.
Sting name;
2. 상수(Constant)
상수(常數, constant)는 변하지 않는 수를 말한다. 즉 프로그램 내에서 절대 변하지 않는 수로 고정된 값을 정할 때 사용한다. 오타로 인한 에러 방지, 값 보존, 데이터 재사용에 의의가 있다.
final String NAME_CONSTANT = "Yunjuniverse"
앞선 변수와의 선언 차이는 데이터 타입 선언 전에 상수를 선언해주는 final이라는 키워드를 사용하는 것이다. 여기에 이름을 정하는 규칙도 달라지는데, 상수는 전체를 대문자로 적어주며 언더스코어로 띄어쓰기를 구분한다(스네이크 케이스).
2. 리터럴(Literal)
리터럴(literal)은 사전적 의미로 '문자 그대로'를 의미한다. 프로그래밍에서 리터럴은 문자가 가리키는 값 그 자체를 의미한다. 즉, 변수에 할당할 수 있는 상수 값이다.
'변수'에 할당할 수 있는 '상수'라니....... 이게 이제 말이 어려워지는데, 쉽게 말해 리터럴은 '변수에 선언해준 데이터'를 의미한다. boolean, int, double, char, String 등 변수에 선언해준 다양한 타입의 데이터가 모두 리터럴이다.
예를 들어 보면
int a = 100;
int b = 100;
위 코드에서 a와 b는 모두 100이라는 정수형 리터럴을 보유하고 있다.
이전에 원시타입인 데이터를 선언하면 주솟값이 아닌 값 자체를 저장한다고 했다. 리터럴은 이 규칙과 연관이 있다. 만약 100이라는 값을 2번에 나누어 저장한다면? 데이터 낭비가 너무 심해질 것이다. 그래서 자바는 100을 상수 풀에 넣어두고 두 변수가 모두 하나의 값을 가리키도록 한다. 정수로 선언된 100이라는 데이터는 자바의 메모리 저장공간 중 Heap 메모리 영역의 constant pool이라는 상수 데이터 저장 공간에 저장된다
다시말해 자바에서는 코드 상에서 적은 정수형 리터럴(100)을 평가해서 변수 내의 값을 도출한다. 이를 통해 100이라는 값을 여러번 생성하는 것이 아니라 한번만 생성하고 돌려 쓰는 것이다.
리터럴은 정수형 리터럴(int, byte, short, long), 실수형 리터럴(float, double), 논리형 리터럴(boolean), 문자형 리터럴(char)과 스트링 리터럴(String)이 있다. 그런데 스트링은 또 참조타입이라고 하지 않았나?
스트링은 참조타입에서도 조금 특이한 놈이라서 리터럴을 사용할 수 있도록 메모리 저장 영역을 따로 string constant pool로 두었다. 그래서
String str1 = "Yunjuniverse";
String str2 = "Yunjuniverse";
System.out.println(str1 == str2); // 결과값: true;
이렇게 주솟값을 비교하는 == 할당자로 비교해도 동일하다는 결과를 볼 수 있다.
자세한 내용은 아래를 참고하자
https://www.geeksforgeeks.org/literals-in-java/
Literals in Java - GeeksforGeeks
A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.
www.geeksforgeeks.org
4. 형 변환(Type Casting)
자바에서 변수를 선언할 땐 타입을 명시해준다. 데이터가 들어갈 메모리 공간을 알려주고 데이터간 연산을 하기 위함이다. 자바에서는 각 타입을 변환할 수 있다.
자동 타입 변환
1. 바이트 크기가 작은 타입에서 큰 타입으로 변환
2. 덜 정밀한 타입에서 더 정밀한 타입으로 변환
이 두 가지 경우엔 다른 변환 작업이 필요하지 않다.
그 이유는 첫 째, 메모리 크기가 작은 타입의 경우에서 큰 타입으로 변환할 때는 메모리 크기를 더 할당해주기만 하면 된다.
둘째로 덜 정밀한 타입에서 정밀한 타입으로 변환하는 것은 계산상에 문제를 일으키지 않는다. 2라는 값을 2.0이라고 변환해주는 것은 문제가 없지만 2.5를 정수만 표현 가능한 int타입으로 변환한다면? 상당한 문제를 일으킬 수 있다.
'데이터의 크기','덜 정밀 -> 더 정밀'이라는 규칙을 고려하여 자동 형변환이 가능한 순서를 정리하면
byte(1) -> short(2)/char(2) -> int(4) -> long(8) -> float(4) -> double(8) 순이다.
float은 4byte이지만 int나 long보다 뒤에 있는데, float이 표현 할 수 있는 값이 훨씬 정밀하기 때문이다.
수동 타입 변환
1. 바이트 크기가 큰 타입에서 작은 타입으로 변환
2. 더 정밀한 타입에서 덜 정밀한 타입으로 변환
이 경우에는 자동 형변환이 되지 않는다. 각 경우마다 어떻게 형 변환을 할 수 있는지 알아보자
* 수동 형 변환 방법 정리
정수 <-> 실수: 타입 캐스팅( ) 연산자 사용
1. 실수(double, float)에서 정수(int, byte, short, long) : 타입 캐스팅 연산자 ( ) 사용, 소수점 뒷 자리는 버려진다.
double d = 111.22222222222;
float f = 3303.9929f;
int test1;
int test2;
test1 = (int)d; // 출력: 111
test2 = (int)f; // 출력: 3303
2. 더 큰 정수형에서 더 작은 정수형으로 변환: 타입 캐스팅 연산자 ( ) 사용. 최대, 최소값을 넘으면 숫자를 순환한다. 예를 들어 127이 최대 표현량인 byte 타입으로 128 크기의 데이터를 형 변환 한다면 -128로 순환하여 출력한다.
int i = 128;
byte b = (byte)i;
//int 타입으로 선언된 변수 i를 더 작은 단위인 byte로 변환
System.out.println(b); //출력값: -128
3. 더 큰 실수형(double)에서 더 작은 실수형(float)으로 변환: 타입 캐스팅 연산자 ( ) 사용. 표현할 수 있는 범위를 넘은 소수점의 뒷자리는 반올림한다.
double d = 111.2222279235299;
float x = (float)d;
System.out.println(x); // 출력값: 111.22223
문자열(string) <-> 숫자(integer, float)
4. 문자열(string)에서 숫자로 변환: 각 원시타입의 클래스에 속한 valueOf() 메소드 사용. 단 크기가 벗어나면 오류를 발생시킬 수 있다. 예를 들어 "12345"를 byte 타입으로 바꿀 경우에는 범위 오류가 나타난다.
String str1 = "123";
int int1 = Integer.valueOf(str1);
float float1 = Float.valueOf(str1);
double double1 = Double.valueOf(str1);
byte byte1 = Byte.valueOf(str1);
System.out.println(int1); // 출력값: 123
System.out.println(float1); // 출력값: 123.0
System.out.println(double1); // 출력값: 123.0
System.out.println(byte1); // 출력값: 123
4. 숫자에서 문자열(String)로 변환: String 클래스의 valueOf() 메소드 사용
boolean boolean1 = true;
byte byte1 = 123;
short short1 =1234;
int int1 = 12341234;
long long1 =12341223023704L;
float float1 = 1234.1234f;
double double1 = 1234.12341234;
String booleanToString = String.valueOf(boolean1);
String byteToString = String.valueOf(byte1);
String shortToString = String.valueOf(short1);
String intToString = String.valueOf(int1);
String longToString = String.valueOf(long1);
String floatToString = String.valueOf(float1);
String doubleToString = String.valueOf(double1);
System.out.println(booleanToString); // 출력값: true
System.out.println(byteToString); // 출력값: 123
System.out.println(shortToString); // 출력값: 1234
System.out.println(intToString); // 출력값: 12341234
System.out.println(longToString); // 출력값: 12341223023704
System.out.println(floatToString); // 출력값: 1234.1234
System.out.println(doubleToString); // 출력값: 1234.12341234
문자(char) <-> 숫자(integer, float): 타입 캐스팅 연산자 ( ) 사용.
5. 문자(char)에서 숫자로 변환: 타입 캐스팅 연산자 사용
이 과정에서 중요한건 문자형 리터럴에서 적힌 값이 숫자로 바뀌는 과정이다. 문자열을 스트링 클래스의 valueOf 메소드를 이용할 때는 "0"이 0으로 잘 변경되어 나왔지만 타입캐스팅 연산자를 사용하는 경우에는 주의해야할 점이 있다.
자바에서 문자는 아스키(ASCII)코드의 형태로 구분한다. 문자 리터럴 0의 경우 48라는 값으로 아스키에서 지정을 해놓았기 때문에 문자 0을 정수로 변환 시 48이라는 값이 도출된다. 그래서 만약 원하는 숫자값으로 명확하게 변환을 하고 싶을 때는 '0'을 빼주거나 숫자 48을 빼주어야 원하는 결과가 도출된다.
char c = '9';
int i1 = (int)(c);
int i2 = (int)(c)-48;
int i3 = (int)(c-'0');
System.out.println(i1); //출력값: 57
System.out.println(i2); //출력값: 9
System.out.println(i3); //출력값: 9
6. 숫자에서 문자(char)로 변환: 타입 캐스팅 연산자 사용
숫자에서 문자형으로 바꾸기 위해서는 어떤 점을 유의해야 할까? 위에서 말했듯이 문자 리터럴은 숫자를 아스키 코드를 기준으로 인식한다. 따라서 9라는 정수 값을 문자형으로 바꾸면 아스키코드 9번에 해당하는 "TAB"이라는 녀석을 표현하려고 할 것이다. 그러나 한 개의 문자를 표현하는 char는 이 아스키코드 9번을 표현하지 못하는 불상사가 생긴다. (컴파일에서는 오류가 나지 않는 매우 귀찮은 오류...)
그래서 만약 원하는 숫자값으로 명확하게 변환을 하고 싶을 때는 '0'을 더해주어야 한다.
int i = 9;
char c = (char)(i+'0');
System.out.println(c); //출력값: 9
문자(char) <-> 문자열(String)
7. 문자(char)에서 문자열로 변환: 한 자리 숫자의 경우 String 클래스의 charAt(index) 메서드를 사용한다. 만약 숫자가 여러자릿수라면 자릿수마다 문자가 있는 것이기 때문에 문자의 집합(배열)을 사용한다. (아직 배열을 모르는 분을 위해 설명하고자 집합이라는 표현을 사용) 배열의 경우에는 String 클래스의 toCharArray() 메소드를 이용해 바꾸어 준다.
String str1 = "9";
String str2 = "12345";
char ch1 = str1.charAt(0);
char[] ch2 = str2.toCharArray();
System.out.println(ch1); // 출력값: 9
System.out.println(ch2); // 출력값: 12345
8. 문자열(String)에서 문자(char)로 변환: String 클래스의 valueOf() 메소드를 활용하면 된다. 앞서 말한 문자열 배열(char[]) 또한 valueOf()로 바꿀 수 있다.
char ch1 = '9';
char[] ch2 = {'Y','u', 'n'};
String s1 = String.valueOf(ch1);
String s2 = String.valueOf(ch2);
System.out.println(ch1); // 출력값: 9
System.out.println(ch2); // 출력값: Yun
'JAVA' 카테고리의 다른 글
[Snack Java] 6. 자바의 콘솔 출력(Console Output) (0) | 2022.06.04 |
---|---|
[Snack Java] 5. 자바의 연산자(Operators) (0) | 2022.06.02 |
[Snack Java] 3. 자바의 문자열 클래스: 심화(StringTokenizer, StringBuilder, StringBuffer) (0) | 2022.05.31 |
[Snack Java] 2. 자바의 문자열 클래스(String Class) (0) | 2022.05.31 |
[Snack Java] 1. 자바의 타입(Type of JAVA) (0) | 2022.05.31 |