변수

Jaca·2021년 8월 10일
0

변수란?

값을 저장할 수 있는 메모리상의 공간.
하나의 변수에 단 하나의 값만 저장할 수 있으므로, 새로운 값을 저장하면 기존의 값은 사라진다.

변수의 선언과 초기화

변수의 선언은 '변수타입'과 '변수이름'으로 이루어진다.

int age //변수이름
//변수타입

변수타입

변수에 저장될 값이 어떤 타입인지 지정하는 것.
저장하고자하는 값의 종류에 맞게 타입을 선택.

변수이름

말 그대로 변수에 붙힌 이름.
변수는 '값을 저장할 수 있는 메모리 공간'이므로 변수의 이름은 메모리 공간에 이름을 붙히는 것이다.
같은 이름의 변수가 중복되면 안됨

변수의 초기화

메모리는 여러 프로그램이 공유하는 자원이므로 전에 다른 프로그램에 의해 저장된 '알 수 없는 값'이 남아 있을 수 있다.
변수의 종류에 따라 변수의 초기화를 생략할 수 도있지만, 변수는 사용되기 전에 적절한 값으로 초기화 하는 것이 좋다.

변수의 명명규칙

'변수 이름'처럼 프로그래밍에서 사용하는 모든 이름을 '식별자(identifier)'라고 하며, 식별자는 같은 영역 내에서 서로 구분(식별) 될 수 있어야한다.
그리고 식별자를 만들 때는 몇가지 규칙이 있다.

1. 대소문자가 구분되며 길이 제한이 없다.
2. 예약어를 사용해서는 안 된다. (대소문자를 구분하므로 true는 안되지만 True는 가능)
3. 숫자로 시작해서는 안된다.
4. 특수문자는 '_'와 '$'만 허용한다.

이 외에도 자바 개발자 끼리의 가독성을 높이기 위한 약속들이 존재한다.

1. 클래스 이름의 첫 글자는 항상 대문자로 한다.
2. 여러 단어로 이루어진 이름은 단어의 첫 글자를 대문자로 한다.
3. 상수의 이름은 모두 대문자로 한다. 여러 단어일 경우 '_'로 구분한다.

변수의 타입

우리가 주로 사용하는 값의 종류는 크게 '문자'와 '숫자'로 나눌 수 있다.

  • 값 :
    • 문자
    • 숫자
      • 정수 : (byte, short, int, long)
      • 실수 : (float, double)

기본형과 참조형

자료형은 크게 기본형과 참조형으로 나눌 수 있다.

기본형 : 실제 값(data)을 저장

  • boolean, char, byte, short, int, long, float, double

참조형 : 어떤 값이 저장되어 있는 주소값을 저장

  • 8개의 기본형을 제외한 나머지 타입

참조형은 C언어의 포인터와 비슷한 개념이지만, 자바는 참조형 변수간의 연산을 할 수 없어, 실제 연산에 사용되는 것은 모두 기본형 변수이다.

참조형 변수를 선언할 때는 변수의 타입으로 클래스의 이름을 사용하므로 새로운 클래스를 작성한다는 것은 새로운 참조형을 추가하는 셈이다.

상수와 리터럴(constant & literal)

상수

'상수(constant)' 는 변수와 마찬가지로 '값을 저장할 수 있는 공간' 이지만 변수와 달리 한번 값을 저장하면 다른 값으로 변경할 수 없다.
변수와 같이 선언하며, 변수 타입 앞에 final 키워드를 붙여준다.

상수는 선언과 동시에 초기화해야 하며, 그 이후에 값을 변경하는 것은 허용되지 않는다.

리터럴

'리터럴(literal)' 은 상수를 '값을 한번 저장하면 변경할 수 없는 저장공간'으로 정의하였기에 이와 구분하기 위해 상수를 다른 이름으로 부르기 위해 만든 용어이다.

//변수 = 하나의 값을 저장하기 위한 공간
//상수 = 값을 한번만 저장할 수 있는 공간
//리터럴 = 그 자체로 값을 의미 하는 것
int year = 2021;
final int MAX_VALUE = 100;
//year = 변수
//MAX_VALUE = 상수
//2014, 100 = 리터럴

리터럴의 타입과 접미사

변수에 타입이 있듯이 리터럴에도 타입이 있다.
변수의 타입은 값의 타입에 의해 결정되기 때문에, 리터럴에 타입이 없다면 변수의 타입도 필요 없을 것이다.

정수형과 실수형에 여러 타입이 존재하므로, 리터럴에 접미사를 붙여서 타입을 구분지어야 한다.

정수형에서는 int 가 기본 타입이기에 접미사는 생략 가능하다.
또한, byteshort 타입은 접미사가 없고, 접두사를 통해 진수를 표기할 수 있다.

int octNum = 010 // 8진수 10, 10진수로 8
int hexNum = 0x10 // 16진수로 10, 10진수로 16
int binNum = 0b10 // 2진수 10, 10진수로 2

long 타입에는 L을 붙히며, JDK1.7 부터 리터럴의 중간에 구분자 '_'를 넣을 수 있게 되었다.

long big = 100_000_000_000L;
long hex = 0xFFFF_FFFF_FFFF_FFFFL;

실수형 float 는 f, F double 는 d, D를 붙히나, 정수형의 기본 타입은 double 이라서 생략이 가능하다.

float pi = 3.14f; // f 생략 불가능
double rate = 1.618; // d 생략 가능

실수형 리터럴에는 제곱을 나타내는 기호 e나 접미사 f,F,d,D를 포함하고 있으면 실수형 리터럴로 간주된다.

자료형실수형 리터럴다른 형태의 동등한 표현
double10.10.0
double.100.10
float10f10.0f
float3.14e3f3140.0f
double1e110.0
double1e-30.001

타입 불일치

리터럴 타입은 저장될 변수의 타입과 일치하는게 보통이지만, 저장범위가 넓은 타입에 좁은 타입을 저장하는 것은 허용한다.

int i = 'A'; // 'A'의 유니코드 65는 int 범위 내이다.
long l = 123; // int 범위의 123은 long의 범위 내이다.
double d = 3.14f; // float보다 double의 범위가 더 넓다.

문자 리터럴과 문자열 리터럴

'A'와 같이 작은 따옴표로 문자 하나를 감싼 것을 '문자 리터럴', 두 글자 이상은 큰 따옴표로 감싸야 하며 '문자열 리터럴' 이라고 한다.

char 타입은 단 하나의 문자만 저장할 수 있고, 빈 글자로 초기화 할 수 없다. 반대로 String 타입은 빈 문자열을 허용한다.

String str = ""; // 빈 문자열 가능
char ch = ''; // 반드시 하나의 문자가 필요
char ch = ' '; // 공백(blank)로 초기화 가능

원래 String 은 클래스이기 때문에 new 연산자로 생성해야 하지만 위와 같은 선언도 허용한다.

String name = new String("JAVA"); // String 객체 생성

또 덧셈 연산자를 이용하여 문자열을 결합할 수 있다.

문자열 + any type -> 문자열 + 문자열 -> 문자열
any type + 문자열 -> 문자열 + 문자열 -> 문자열

또 기본형 타입의 값을 문자열로 변환할 때 빈 문자열을 더해주면 형 변환이 된다

System.out.println(7 + ""); // String "7"

형 변환

모든 변수와 리터럴에는 타입이 있다.
하지만 프로그램을 작성하다보면, 서로 다른 타입간의 연산을 수행해야 하는 경우도 있다.
이럴 때 연산을 수행하기 전에 타입을 일치시켜야 하는데, 변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형 변환이라고 한다.

형 변환 방법

(타입)피연산자 여기서 사용되는 괄호() 는 '캐스트 연산자', '형변환 연산자' 라고 한다.

double d = 85.4;
int score = (int)d;
==>
int score = (int)85.4;
int score = 85;

형변환 연산자는 그저 피연산자의 값을 읽어서 지정된 타입으로 변환 할 뿐, 피연산자의 값은 아무런 변화가 없다.

  • int -> byte 와 같이 큰 타입에서 작은 타입으로 형변환 시 값 손실이 일어날 수 있다.

  • double -> float로 형 변환시 double의 가수 52자리 중 23 자리만 저장되고 나머지는 버려지나, 24번째의 값이 1이면 반올림이 발생하여 23번째 자리의 값이 1 증가 한다.

  • float의 범위를 넘는 값 -> float 변환 시 +-무한대+-0의 결과를 얻는다.

  • 정수형 타입 -> 실수형 타입시 정밀도 제한으로 인한 오차가 발생할 수 있다.
    : int의 최대값은 약 20억으로 최대 10자리의 정밀도가 요구되지만, float는 약 7자리의 정밀도만 제공하므로, int -> float 변환 시 오차가 날 수 있다. 그래서 10진수로 8자리 이상의 값을 실수형으로 변환 할 때는 double 형으로 변환해야 오차가 발생하지 않는다.

  • 실수형 타입 -> 정수형 타입 형변환시 소수점 값은 버림 한다.

자동 형변환

서로 다른 타입간의 대입이나 연산 시, 형변환으로 타입을 일치시키는 것이 원칙이나, 경우에 따라 생략할 수 있다.

  • 명시적 형변환을 해주면, 프로그래머의 의도가 담긴 것으로 간주, 에러를 발생하지 않는다.
char ch = (char)1000 // 명시적 형변환, 에러x
  • 서로 다른 두 타입의 연산에서는 먼저 타입을 일치시켜야 하므로, 자동 형변환이 이루어진다.
int i = 3;
double d = 1.0 + i; // double d = 1.0 + (double)i;

서로 다른 두 타입간의 덧셈은 두 타입중 표현범위가 더 넓은 타입으로 형변환한다.

자동 형변환 규칙

형변환을 하는 이유는 주로 서로 다른 두 타입을 일치시키기 위해서 인데, 형변환을 생략하면 컴파일러가 알아서 형변환을 한다.
어떤 기준으로?

-> 표현 범위가 좁은 타입에서 넓은 타입으로 형변환하는 경우에 값 손실이 없으므로 두 타입중 넓은 범위의 타입으로 형변환한다.

byte(1byte) -> short, char(2byte) -> int(4byte) -> long(8byte) -> float(4byte) -> double(8byte)

이 화살표의 반대방향의 변환은 반드시 형변환을 시켜줘야한다.

  • 보통 자료형의 크기가 큰 것 일수록 표현범위가 크지만, 실수형은 정수형과 값을 표현하는 방식이 다르기 때문에 같은 크기라도, 실수형이 정수형보다 훨씬 더 큰 표현 범위를 갖는다.

  • char와 short는 둘 다 2byte이지만, char 범위는 0 ~ 65535 이고, short는 -32768 ~ 32767 으로 범위가 서로 달라 자동 형변환이 불가능하다.

정리

1. boolean을 제외한 나머지 기본형은 서로 형변환이 가능하다.
2. 기본형과 참조형은 서로 형변환 할 수 없다.
3. 서로 다른 타입의 변수간의 연산은 형변환을 하는 것이 원칙이지만, 값의 범위가 작은 타입에서 큰 타입으로의 형변환은 생략할 수 있다.

profile
I am me

0개의 댓글