이 글의 내용은 자바의 정석 을 기반으로 합니다.
이 카테고리는 마인크래프트 플러그인 개발에 포커스를 둡니다.
Java의 정석 | 남궁성 - 교보문고 (kyobobook.co.kr)
Java의 정석 | 남궁성 - 교보문고
Java의 정석 | 자바의 기초부터 실전활용까지 모두 담다!자바의 기초부터 객제지향개념을 넘어 실전활용까지 수록한『Java의 정석』. 저자의 오랜 실무경험과 강의한 내용으로 구성되어 자바를
product.kyobobook.co.kr
변수란 ?
단 하나의 값을 저장할 수 있는 메모리 공간
변수의 선언
// 변수의 선언방법
int age; // age 라는 이름의 변수를 선언
// 변수타입 변수이름; 으로 구성
변수타입 은 변수에 저장될 값이 어떤 타입 인지를 지정하는 것
지정하고자 하는 값의 종류에 맞게 변수의 타입을 선택해서 적어주면 된다.
변수이름 은 변수에 붙인 이름이다.
변수는 값을 저장할 수 있는 메모리 공간 이므로 변수의 이름은 메모리 공간에 이름을 붙여주는 것이다.
그래야 그 이름을 이용해서 저장공간에 값을 저장하고, 저장된 값을 읽어오기도 할 수 있는 것이다.
위의 문장은 변수 age 를 선언한다.
이 변수는 나이 를 저장하기 위한 것이고 나이는 정수(integer) 이므로 변수의 타입을 int 로 지정하였다.
변수의 초기화
변수를 선언한 이후부터는 변수를 사용할 수 있으나, 변수를 초기화 해야 한다.
메모리는 여러 프로그램이 공유하는 자원이므로 전에 다른 프로그램에 의해 저장된 알 수 없는 값 이 남아있을 수 있기 때문이다.
변수에 값을 저장할 때는 대입연산자 = 를 이용한다.
오른쪽의 값을 왼쪽 변수 에 저장하라는 뜻이다.
// 변수의 초기화
int age = 25; // 변수 age 를 선언하고 25로 초기화 된다.
변수의 초기화란, 변수를 사용하기 전에 처음으로 값을 저장하는 것
// 두 변수를 교체하는 로직
class Swap {
public static void main(String[] args) {
int x = 10;
int y = 20;
int temp = 0;
System.out.println("x : " + x + "y : " + y);
temp = x;
x = y;
y = temp;
System.out.println("x : " + x + "y : " + y);
}
}
변수의 명명규칙
대소문자가 구분되며 길이에 제한이 없다.
예약어를 사용해서는 안 된다.
숫자로 시작해서는 안 된다.
특수문자는 '_'와 '$' 만을 허용한다.
변수의 이름은 짧을수록 좋지만, 약간 길더라도 용도를 알기 쉽게 의미있는 이름 으로 하는 것이 바람직하다.
변수의 타입
우리가 자주 사용하는 값의 종류는 크게 문자 와 숫자로 나눌 수 있으며
숫자는 다시 정수 와 실수 로 나눌 수 있다.
이러한 값의 종류에 따라 값이 저장될 공간의 크기 와 저장형식을 정의한 것이 자료형이다.
자료형은 크게 기본형 과 참조형 두 가지로 나눌 수 있다.
기본형 변수는 실제 값을 저장하는 반면
참조형 변수는 어떤 값이 저장되어 있는 주소를 값으로 갖는다.
기본형(primitive type)
- 논리형(boolean)
- 문자형(char)
- 정수형(byte, short, int, long)
- 실수형(float, double)
참조형(reference type)
- 객체의 주소를 저장한다. 8개의 기본형을 제외한 나머지 타입
참조형 변수를 선언할 때는 변수의 타입으로 클래스의 이름을 사용하므로
클래스의 이름이 참조변수의 타입이 된다.
그래서 새로운 클래스를 작성한다는 것은 새로운 참조형을 추가하는 셈이다.
// 참조 변수 선언
// Date 객체를 생성해서, 그 주소를 today 에 저장
Date today = new Date();
객체를 생성하는 연산자 new 의 결과는 생성된 객체의 주소이다.
이 주소가 대입연산자에 의해서 참조변수 today 에 저장되는 것이다.
이제 참조변수 today 를 통해서 생성된 객체를 사용할 수 있게 된다.
참조형 변수는 null 또는 객체의 주소를 값으로 갖는다.
null 은 어떤 객체의 주소도 저장되어 있지 않음을 뜻한다.
상수와 리터럴(constant & literal)
상수는 변수와 마찬가지로 값을 저장할 수 있는 공간이지만
변수와 달리 한 번 값을 저장하면 다른 값으로 변경할 수 없다.
상수를 선언하는 방법은 변수와 동일하며, 단지 변수의 타입 앞에 키워드 final 을 붙여주기만 하면 된다.
// 상수 선언 및 초기화
final int MAX_SPEED = 10; // 상수 MAX_SPEED 를 선언 및 초기화
상수는 반드시 선언과 동시에 초기화해야 하며, 그 후 부터는 상수의 값을 변경하는 것을 허용하지 않는다.
상수의 일므은 모두 대문자로 하는 것이 암묵적인 관례이며, 여러 단어로 이루어져있는 경우 '_' 로 구분된다.
// 상수 선언 및 초기화 오류 케이스
final int MAX_SPEED; // 에러. 상수는 선언과 동시에 초기화해야함
final int MAX_VALUE = 100; // OK. 선언과 동시에 초기화했음
MAX_VALUE = 200; // 에러. 상수의 값은 변경될 수 없음
리터럴(literal)
원래 12, 123, 3.14, 'A' 와 같은 값들을 상수 라고 하는데
프로그래밍에서는 상수를 값을 한 번 저장하면 변경할 수 없는 저장공간 으로 정의하였기 때문에
이와 구분하기 위해 기존의 상수를 다른 이름으로 불러야만 했다.
그래서 상수 대신 리터럴 이라는 용어를 사용한다.
리터럴은 단지 우리가 기존에 알고 있던 상수 의 다른 이름일 뿐이다.
// 리터럴
int year = 2014;
// 타입 변수 = 리터럴;
final int MAX_VALUE = 100;
//타입 상수 = 리터럴;
타입의 불일치
리터럴의 타입은 저장도리 변수의 타입과 일치하는 것이 보통이지만
타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용된다.
// 타입의 불일치
int i = 'A'; // OK. 문자 'A' 의 유니코드인 65가 변수 i 에 저장된다.
long l = 123; // OK. int 보다 long 타입이 더 범위가 넓다.
double d = 3.14f; // OK. float 보다 double 타입이 더 범위가 넓다.
int i = 0x123456789; // 에러. int 타입의 범위를 넘는 값을 저장
float f = 3.14; // 에러. float 타입보다 double 타입의 범위가 넓다.
// 3.14 는 3.14d 에서 접미사가 생력된 것으로 double 타입이다.
문자 리터럴과 문자열 리터럴
'A' 와 같이 작은따옴표로 문자 하나를 감싼 것은 문자 리터럴 이라고 한다.
두 문자 이상은 큰 따옴표로 감싸야 하며 문자열 리터럴 이라고 한다.
문자열은 문자의 연속된 나열을 의미하며 영어로 string 이라고 한다.
// 문자 리터럴과 문자열 리터럴
char ch ='J'; // char ch ='Java'; 이렇게 할 수 없다.
String name = "Java"; // 변수 name 에 문자열 리터럴 "Java" 를 저장
char 타입의 변수는 단 하나의 문자만 저장할 수 있으므로
여러 문자를 저장하기 위해서는 String 타입을 사용해야 한다.
문자열 리터럴은 "" 안에 아무런 문자도 넣지 않는 것을 허용하며, 이를 빈 문자열 이라고 한다.
그러나 문자 리터럴은 반드시 '' 안에 하나의 문자가 있어야 한다.
String 은 클래스이므로 아래와 같인 객체를 생성하는 연산자 new 를 사용해야 하지만
특별히 위와 같은 표현도 허용된다.
// String 선언 및 초기화
String name = "Java"; // 변수 name 에 문자열 리터럴 "Java" 를 저장
String name = new String("Java"); // String 객체를 생성
덧셈 연산자는 피연산자가 모두 숫자일 때는 두 수를 더하지만
피연산자 중 어느 한 쪽이 String 이면 나머지 한 쪽을 먼저 String 으로 변환한 다음 두 String 을 결합한다.
// 덧셈 연산자를 활용한 문자열 결합
문자열 + any type -> 문자열 + 문자열 -> 문자열
any type + 문자열 -> 문자열 + 문자열 -> 문자열
기본형(primitive type)
논리형 - boolean
논리형에는 boolean 한가지 밖에 없다.
boolean 형 변수에는 true 와 false 중 하나를 저장할 수 있으면 기본값은 false 이다.
boolean 형은 true 나 false 두 가지의 값만을 표현하면 되므로 1 bit 만으로도 충분하지만
자바에서는 데이터를 다루는 최소단위가 byte 이기 때문에, boolean 의 크기가 1 byte 이다.
// 논리형 - boolean
boolean power = true;
boolean checked = false;
문자형 - char
문자형에는 char 한 가지 자료형밖에 없다.
문자를 저장하기 위한 변수를 선언할 때 사용되며
char 타입의 변수는 단 하나의 문자만을 저장할 수 있다.
// 문자형 - char
char ch = 'A'; // 문자 'A' 를 char 타입의 변수 ch 에 저장.
위의 문장은 변수에 문자가 저장되는 것 같지만
사실은 문자가 아닌 문자의 유니코드(정수)가 저장된다.
컴퓨터는 숫자밖에 모르기 때문에 모든 데이터를 숫자로 변환하여 저장하는 것이다.
문자 'A' 의 유니코드는 65 이므로, 변수 ch 에는 65가 저장된다.
그래서 문자 리터럴 대신 문자의 유니코드를 직접 저장할 수도 있다.
문자 'A' 의 유니코드는 10진수로 65 이며, 아래의 두 문장은 동일한 결과를 얻는다.
// 문자 리터럴의 상수값
char ch = 'A'; // 문자 'A' 를 char 타입의 변수 ch 에 저장
char ch = 65; // 문자의 코드를 직접 변수 ch 에 저장
// 어떤 문자의 유니코드를 알고 싶다면
int code = (int)ch; // ch 에 저장된 값을 int 타입으로 변환하여 저장한다.
어떤 타입을 다른 타입으로 변환하는 것을 형변환(casting) 이라고 한다.
정수형 - byte, short, int, long
정수형에는 모두 4 개의 자료형이 있으며
각 자료형이 저장할 수 있는 값의 범위가 서로 다르다.
크기순으로 나열하면 다음과 같다. 단위는 byte 이다.
// 정수형의 자료형 크기 순 나열
byte(1) < short(2) < int(4) < long(8)
실수형 - float, double
실수형은 실수를 저장하기 위한 타입으로 float 와 double 두 가지가 있다.
실수형은 소수점수도 표현해야 하므로 얼마나 큰 값을 표현할 수 있는 가 뿐만 아니라 얼마나 0에 가깝게 표현할 수 있는가 도 중요하다.
정수형과 달리 실수형은 오차가 발생할 수 있다는 단점이 있다.
실수형에는 표헌할 수 있는 값의 범위 뿐만 아니라 정밀도(precision) 도 중요한 요소이다.
float 타입은 정밀도가 7 자리인데, 7자리의 10진수를 오차없이 저장할 수 있다 는 뜻이다.
만일 7자리 이상의 정밀도가 필요하다면, 변수의 타입을 double 로 해야한다.
double 타입은 float 타입보다 정밀도가 약 2배인 10진수로 15자리의 정밀도를 가지므로
float 타입보다 훨씬 더 정밀하게 값을 표현할 수 있다.
// float 의 정밀도
9.12345678901234567890 // 원래 값
9.12345695495605500000 // 저장된 값
// 정밀도가 7 자리이므로 원래의 값에서 7자리의 값만 오차없이 저장된 것이다.
// 9.123456 까지 일치
형변환이란 ?
프로그램을 작성하다 보면 같은 타입뿐만 아니라 서로 다른 타입간의 연산을 수행해야 하는 경우도 있다.
이럴 때는 연산을 수행하기 전에 타입을 일치시켜야 하는데, 변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형변환 이라고 한다.
// 형변환 방법
(타입)피연산자
double d = 85.4;
int score = (int)d; // double 타입의 변수 d 를 int 타입으로 형변환
// 형변환의 결과인 85 를 변수 score 에 저장
기본형(primitive type) 에서 boolean 을 제외한 나머지 타입들은 서로 형변환이 가능하다.
기본형과 참조형간의 형변환은 불가능하다.
값 손실(loss of data)
크기가 큰 타입에서 작은 타입으로의 변환은 크기의 차이만큼 값이 잘려나가게 된다.
그래서 경우에 따라 값 손실이 발생할 수 있다.
반대로 작은 타입에서 큰 타입으로의 변환은 저장공간의 부족으로 잘려나가는 일이 없으므로
값 손실이 발생하지 않는다.
// 실수형 형변환
double d = 1.0e100; // float 의 최대값보다 큰 값을 d 에 저장 ( 1.0 * 10^100 )
float f = (float)d; // d 의 값을 float 로 형변환해서 f 에 저장. f는 무한대가 된다.
double d = 1.0e-50; // float 의 최소값보다 작은 값을 d 에 저장 ( 1.0 * 10^-50 )
flaot f = (float)d; // f 의 값은 0 이 된다.
실수형을 정수형으로 변환
실수형을 정수형으로 변환하면 실수형의 소수점이하 값은 버려진다.
정수형의 표헌방식으로 소수점 이하의 값을 표현할 수 없기 때문이다.
// 실수형을 정수형으로 변환
double d = 1.666;
int i = (int)d;
// 1.666 -> 1
자동 형변환
서로 다른 타입간의 대입이나 연산을 할 때 형변환으로 타입을 일치시키는 것이 원칙이다.
하지만, 경우에 따라 편의상의 이유로 형변환을 생략할 수 있다.
그렇다고 해서 형변환이 이루어지지 않는 것은 아니고 컴파일러가 생략된 형변환을 자동으로 추가한다.
// 자동 형변환
float f= 1234; // 형변환의 생략. float f = (float)1234; 와 같음.
그러나 다음과 같이 변수가 저장할 수 있는 값의 범위보다 더 큰 값을 저장하려는 경우에 형변환을 생략하면 에러가 발생한다.
// 자동 형변환 생략 에러
byte b = 1000; // 에러. byte 의 범위 (-128 ~ 127) 를 넘는 값을 저장.
그러나 명시적으로 형변환을 해줬을 경우, 형변환이 프로그래머의 실수가 아닌 의도적인 것으로 간주하고
컴파일러는 에러를 발생시키지 않는다.
// 명시적 형변환은 에러를 일으키지 않음
char ch = (char)1000; // 명시젹 형변환. 에러가 발생하지 않는다.
자동 형변환의 규칙
형변환을 하는 이유는 서로 다른 두 타입을 일치시키기 위해 이다.
형변환을 생략하면 컴파일러가 알아서 자동적으로 형변환을 한다고 했다.
그러면 컴파일러는 어떤 판단 기준으로 타입을 일치시킬까 ?
표현 범위가 좁은 타입에서 넓은 타입으로 형변환하는 경우에는 값 손실이 없으므로
두 타입 중에서 표현범위가 더 넓은 쪽으로 형변환된다.
COBOL and Java Data Types - IBM Documentation
COBOL and Java Data Types
The following table shows the COBOL data type that corresponds to each Java™ primitive type. Table 1. Comparison of COBOL and Java Data Types Java Primitive Type Description Java Data Range COBOL Data Type COBOL Data Range boolean unsigned 8 bits 0 (fals
www.ibm.com
'자바의 정석' 카테고리의 다른 글
6. 자바의 정석 6장 - 객체지향 프로그래밍 I (0) | 2024.08.26 |
---|---|
5. 자바의 정석 5장 - 배열(array) (0) | 2024.08.24 |
4. 자바의 정석 4장 - 조건문과 반복문 (0) | 2024.08.24 |
3. 자바의 정석 3장 - 연산자(Operator) (0) | 2024.08.20 |
1. 자바의 정석 1장 - 자바를 시작하기 전에 (0) | 2024.08.19 |