본문 바로가기
java

[Java: 변수]

by proudev 2023. 3. 8.

변수: 값을 저장할 수 있는 곳(메모리공간 : RAM)

 

변수 이름: 저장할 메모리 공간의 이름(변수 이름을 이용해서 값을 사용함)

 

변수 초기화 : 변수를 사용하기 전에 값을 넣는 것을 말함

 

변수 명명 규칙

1. 대소문자를 구분한다

2. 예약어 사용하면 안된다

  - int, private, for 등 

3. 숫자로 시작하면 안된다.

  - 123abc ( X ), abc123( O )

4. 특수문자는 "_" , " $ " 이외는 안된다.

 

권장하는 규칙(필수는 아님)

1. 클래스는 첫글자 대문자 / 변수, 메소드는 첫 글자 소문자

2. 여러단어 이루어진 부분 첫글자를 대문자 

  - studentName, employerSalary

3. 상수는 모두 대문자, 이어진 경우"_" 붙이기

  - CARD_HEIGHT,  BOX_TOP_SIZE

4. 의미 있는 변수 이름 사용하기

 

변수의 타입은 기본형과 참조형으로 나눠 볼 수 있다.

 


1. 기본형: 실제 값을 저장

  - 오직 8개, 실제 값 저장

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

  - char = 'A' 는 실제 저장될때는 숫자 65(유니코드)로 저장되기 때문에 정수형이랑 다를게 없고 연산 가능

  - boolean은 연산 불가능

  - (byte,short,int,long) 중 기본형은 " int "

  - (float,double) 중 기본형은 "double"

  ** int는 cpu 가장 효율적으로 처리함

  ** byte, short는 메모리 공간은 덜 사용되나 연산시 int로 변환되기 때문에 효율은 int 비해 떨어지는 편임

자료형 정밀도  
float 7자리 7자리까지는 정확한 값 도출 그외 불확실함
double 15자리 15자리까지는 정확한값 도출 그외 불확실함

float, double에서 말하는 7자리는 앞에서 7자리다.

즉, 숫자 앞에서 7자리는 정확히 나오고 그 뒤로는 정확하지 않는 값이 나온다.

예를 들어 아래와 같이 float의 값이 있다면,

  float a = 456456456f;

그러면 맨 앞의 4564564까지는 정확히 나오지면 그 뒤로는 정확하지 않다.

 float a = 456456456f;

 System.out.println("a = " + a); //4.56456448E8

출력을 해보면 4.564564까지 정확하고 그뒤는 48E8로 원래 56값과 일치하지 않는다.

 

변수 초기화하는 방법

변수 초기화 하는 방법은 직접적으로 넣어주는 방법이 있다.(아래 예시 코드)

int x = 0; 
int y = 5;

여기서 위와 같이 타입이 같은 경우에는 타입을 하나로 지정하고  아래와 같이 여러 변수들이 입력할 수 있다. 

int x = 0, y = 0; // 위 두줄을 한주로 표현 가능

* 지역변수는 반드시 초기화 작업시 값을 지정해주어야 한다. 왜냐하면 맴버변수와 달리 자동 초기화를 하지 않기 때문이다.


변수의 타입

1. 변수의 타입은 저장할 값의 타입에 의해 결정된다.

 int age = 25; // 일치
 age = 3.14 // 불일치

2. 저장할 값의 타입과 일치하는 타입으로 변수를 선언

 char ch = '가'; // char는 문자 타입
 double pi = 3.14; // double은 실수 타입

* (중요) 클래스의 이름이 참조변수의 타입이 된다. 그래서 새로운 클래스를 작성한다는 것은 새로운 참조형(타입)을 추가하는 셈이다.


변수의 용량(자리수)

  - JVM 32bit 객체주소 크기: 4byte 

  - 32bit JVM 은 40억 

  - JVM 64bit 객체주소 크기: 8byte

  - 64bit JVM 은 40억 X 40억 = 1600억 = 1600만TB 를 다룬다.

 

1bit는 0 또는 1 2개로 표현할 수 있음
2bit는 00, 10, 11, 01 ,4개 표현할 수 있음
n비트로 표현할 수 있는 값의 개수 : 2ⁿ 개
n비트로 표현할 수 있는 부호없는 정수의 범위 : 0 ~ 2ⁿ -1 
n비트로 표현할 수 있는 부호있는 정수의 범위 : - 2^(n-1) ~ 2^(n-1) -1

 

1. byte : - 2^7 ~ 2^7 -1
 [s][7bit]
 [s] : 부호비트
 [7bit]: 숫자 


2. short:  - 2^15 ~ 2^15-1
 [s][15 bit] : -32768 ~ 32767

 [s] : 부호비트
 [15bit]: 숫자 


3. char: 0 ~ 2^16-1
[16bit] : 숫자(양의 정수만 취급하기 때문에 부호정수가 없다.) 

양의 정수만 표현할뿐이지 short와의 표현하는 값의 개수는 동일하다.
char는 문자를 저장하는 타입이지만 컴퓨터는 모든 것을 숫자로 저장하기 때문에 
지정된 문자코드로 변환된다.
char ch ='A' 저장하면
char ch = 65로 저장된다. 보이는 것은 'A' 보이지만 컴퓨터는 65라고 판단함
엄밀히 말하자만 2진수로 저장된다(0000000001000001)

4. int: - 2^31 ~ 2^31 -1 : 약 20억
[s][31bit] 

5. long - 2^63 ~ 2^63-1 : 800경
[s][63 bit]

* 800경을 넘으면 실수 타입 또는 BigInteger 사용한다.


실수형 리터럴 형식

10. -> 10.0
.10 -> 0.10
10f -> 10.0f
1e3 -> 1000.0 (왜냐하면 e는 실수형에만 사용하기 때문이다)


변수의 타입과 리터털의 타입이 일치해야한다.

* 변수와 리터럴의 타입 불일치
1. 범위가 '변수 > 리터럴' 인 경우 OK  

byte b = -128  // OK


2. 범위가 '변수 < 리터럴' 인 경우 에러

byte b = 516151  // Error
int i = 30_0000_0000; // 에러 int의 범위(+-20억) 벗어남
long l = 3.14f; // 에러, long < float : 실수형은 정수형 보다 범위가 넓다.
float f = 3.14 // float < double

3. byte, short 변수에 int 리터럴 저장가능 (단, 변수의 타입의 범위 이내이어야 함)

byte와 short는 int 형태의 리터럴 값을 받는다. 즉, byte와 short의 구분하는 리터럴 접두사, 접미사는 없다.

그러나 int 리터럴을 사용하되 해당 변수가 받을 수 있을 값의 범위 안에서만 사용해야한다.

만약 값의 범위를 넘는 int 값을 사용하면 컴파일 에러가 발생한다.

byte = 127 // 리터럴 값의 타입은 int이다 . 그러나 byte가 허용한 범위에서 사용되어야한다.
short = 12314
byte b = 100; // OK, byte의 범위(-128~127)에 속함
byte b = 128; // 에러, byte의 범위를 벗어남

 


2. 참조형: 객체의 주소를 저장

  - 기본형을 제외 모든 타입 

  - 참조변수 타입은 클래스 타입 (클래스이름 변수이름 : Student s1, employee e1)

  - Student s2 = null (객체 주소가 저장되지 않았음을 뜻함)

  - 메모리 주소를 저장(4byte or 8byte)
  - 메모리는 0,1,2,3 양의 정수의 주소를 가진다.


3. 상수(final)  (예: final ROOM_CAPACITY = 200)

  - 상수:  한번만 값을 저장 가능한 변수
  - 리터럴 그 자체로 값을 의미하는 것

  - 상수는 한번 정하면 값을 바꿀 수 없다. 값을 바꿀 경우 에러 발생함.

  - 상수는 반드시 초기화 해주어야함

  - 권장: 변수이름 대문자  / 단어는 "_" 이어줌 

* JDK 1.6부터 상수를 선언과 동시에 초기화 하지 않아도 되며, 사용하기 전에만 초기화하면 되도록 바뀌었다.

* 그래도 상수는 선언과 동시에 초기화 하는 습관을 들이는 것이 좋다.


4. 리터럴 

  - 해당 변수의 값

  - int abc = 8 , String color="red", final int SIZE = 100

  - 위 변수 중 리터럴에 해당 되는 것은 8 , "red", 100

  - 접미사가 있는 리터럴

기본형   적용 접미사
long  int 범위 안에 있는 값은 " L " or " l " 안붙여도 됨   선택 " L " or " l "
 int 범위를 넘어서면  " L " or " l " 붙여야함(1000000000L) 필수
float  반드시 붙여야함 (예: 0.004f, 12.33F) 필수 " F " or " f "
double  선택사항임(예: 13.111D, 123.111111d, 10.00) 선택 " D " or " d "

 - 접두사가 있는 리터럴

진수 접두사 예시
2진수 "0b" or "0B"  int binum=0b10, binum2=0B11
8진수 "0"  int oct=072
16진수 "OX" or "0x"  int hex=0X1AB, hex1=0x19AF

 - 타입이 일치하지 않아도 변수타입의 범위가 넓으면 허용됨

   예시) double num= 11.0f / int ch='C' / long num1=333

 

 - 문자 리터럴, 문자열 리터럴

   * 문자 리터럴: char ch ='A'

     - 작은 따옴표 안에 하나의 문자가 들어감, char ch1='AA' 문자열이기 때문에 에러 발생

     - char ch1= ' '    에러 발생(반드시 1개 문자가 있어야함)

     - char ch2 ='  '   공백도 하나의 숫자형태로 저장되어 있고 이에 하나의 문자로 간주됨

     - String ss="" 빈공백(empty) 

   * 문자열 리터럴: String str = "AA" 

  

 - String str= 1 + "" / 숫자가 아닌 문자열 "1", 즉, 숫자 뒤나 앞 큰 따움표를 붙이면 문자열로 바뀜

 - 덧셈 연산자는 왼쪽에서 오른쪽으로 수행함!!! 대입연산다(=)와 방향이 다름

    예시: String n = 9 + 9 + "" / n=18

             String n1= "" + 9 + 9 / n=99    


5. System.out.println()

println()의 단점 - 출력형식 지정 불가
1. 실수의 자리수 조절불가 - 소수점 n자리만 출력하려면(지정해서)
 System.out.println(10.0/3); 
 
2. 10진수로만 출력된다. - 8 진수, 16진수로 출력하려면
 System.out.println(0x1A); // 26


6. System.out.printf()

기존에 자주 사용하는 System.out.println()은 괄호안에 내용을 그대로 표현해주고 한 줄을 띄우고 출력준다.

그러나 System.out.printf()는 괄호안에 내가 원하는 형식되로 출력이 가능하나 한 줄을 띄어주진 않는다. 

지시자  
 %b  boolean
 %c  문자
 %s  문자열
 %d  10진수
 %o  8 진수
 %X,%x  16진수
 %#o ,%#X  접두사 + 숫자
 %f  부동소수점
 %e, %E  지수
 %n  한 줄뛰기

 

		// %b : boolean
		boolean bo=true;
		boolean bo1=false;
		System.out.printf("bo=%b%n",bo);
		System.out.printf("bo1=%b%n",bo1);
		
		// %c : 문자
		char ch='A';
		System.out.printf("ch=%c%n",ch);
		
		// %s : 문자열
		String str="abc";
		System.out.printf("str=%s%n",str);
		
		// %d : 10진수
		int num=100;
		System.out.printf("num=%d%n",num);
		
		// %o : 8진수
		int oct=016;
		System.out.printf("oct=%o%n",oct); // oct=16
		System.out.printf("oct=%#o%n",oct);// oct=016
		
		// %x or %X : 16진수
		int hex=0xAF;
		System.out.printf("hex=%x%n",hex); //hex=af (%x : 소문자로 표시)
		System.out.printf("hex=%X%n",hex); //hex=AF (%X : 대문자로 표시)
		System.out.printf("hex=%#X%n",hex);//hex=0XAF​

 

printf()의 지시자

%10d : 양의 정수 10는 총 10칸으로 표현되고 d에 지정된 숫자는 오른쪽 정렬 나머지 값은 빈 공백으로 출력한다.

%-10d : 음의 정수 10는 총 10칸으로 표현되고 d에 지정된 숫자는 왼쪽 정렬 나머지 값은 빈 공백으로 출력한다

 

앞에 0이 붙는 것: 위와 동일하나 빈공백 대신 0을 넣는다.

 

%06d : 양의 정수 06는 총 6칸으로 표현되고 d에 지정된 숫자는 오른쪽 정렬 나머지 값은 0으로 출력한다.

%-06d : 양의 정수 06는 총 6칸으로 표현되고 d에 지정된 숫자는 왼쪽정렬 나머지 값은 0으로 출력한다.

System.out.printf("[%10d]",1564)  // [      1564]
System.out.printf("[%-10d]",1564) // [1564      ]
System.out.printf("[%010d]",1564) // [0000001564]
System.out.printf("[%06d]",1564) //  [001564]
System.out.printf("[%-06d]",1564) // [156400]

 

%.3s : 점( . ) 3은 총 3자리를 부분출력한다.

String a = "가나다라마바사";
System.out.println("[%.3s]",a); // 가나다

 

int a = 23.123456789;
System.out.printf("a=[%17.13f"], a); // a = [ 23.1234567890000] 

전체 17자리 중 소수점 아래 13자리 
나머지 4자리는 앞의 정수로 표현되며 ".(소수점)"도 포함한 개수다.
즉, 앞의 정수는 4자리를 표현할 수 있는데 현재 a의 정수는 소수점 포함해서 3자리이다( 2 3 . )
그래서 나머지 남은 정수에는 공백으로 채워진다( 공백 2 3 . )
그리고 뒤에 소수점 아래 값은 9개인데 13자리까지 표현된다. 남은 뒤에 4자리는 0으로 표현된다.
.1234567890000

그래서 %17.13f 는 전체 17자리(소수점 포함)를 표현을 해야되고 소수점 뒤에 나머지 빈값은 0
앞에 정수 부분에 나온 빈값은 공백으로 표현된다.
System.out.printf("a=[%17.13f"], a); // a = [ 23.1234567890000]

* 10진수를 2진수로 출력해주는 지시자는 없기 때문에, 정수를 2진 문자열로 변화내주는 Integer.toBinaryString(int i) 사용해야한다.

System.out.printf("binNum=%s%n",Integer.toBinaryString(binNum));

 

7. 인코딩과 디코딩

 - 문자를 코드로 바꾸는 것이 인코딩

 - 반대로, 코드를 문자로 바꾸는 것이 디코딩

 

8. UTF-16, UTF-8

 - UTF-16 모든 문자를 2byte로 저장함

 - UTF-8가변적이며 1-4byte로 저장함(3byte: 한글/ 1byte: 영어,숫자)

 

9. 정수형(byte, int, short, long)

 - JVM은 피연산자를 4byte로 저장하기 때문에 4byte보다 작은 byte, short 값은 변수는 int로 다시 변환해주는 작업을 함.

 - 그러나, int를 사용해서 연산 작업을 하면 int가 4byte이기 때문에 변환해주는 작업을 안해도 되서 보다 효율적임.

 

10. 정수형 오버플로어

 - 타입이 표현할 수 있는 값의 범위를 넘어가는 것

  예시)

       - int 최대값 + @ = @ 

       - int 최솟값 - @ = int의 최대값 - @

 

11. 실수형(float, double)

  - 실수형은 정밀도가 중요함

  - float앞의 7자리까지는 정확하게 표현하나 그 외의 값은 정확하지 않음

  - double 앞의 15자리까지 정확하게 표현하나 그 외의 값은 정확하지 않음

  - 더 정확히 값을 표현하고 쉽다면 double, 메모리를 적게 사용하고 싶으면 float

* 정수형과 달리 실수형에서는 오버플로우가 발생하면 변수의 값은 '무한대(infinity)'가 됩니다. 

* 정수형에는 없는 '언더플로우(underflow)'가 있는데, '언더플로우'는 실수형으로 표현할 수 없는 아주 작은 값

* 즉, 양의 최소값보다 작은 값이 되는 경우를 말합니다. 이 때 변수의 값은 0이 됩니다.


1. 형변환

  - 변수 or 상수를 다른 타입 변환해주는 것: (변환하고자 하는 변수타입) 값 

int ab=(int) 5.14; // 5 (소수점 값은 버림)
int ab1=(int) 11.3f;// 11 (소수점 값은 버림)

 - 기본형은 boolean 이외에 형변환 가능 ( O )  

 - 기본형과 참조형은 형변환 (X)

double d = 1234.11;
int a = (int)d;
int a = (int)1234.11;
int a = 1234;
이 과정에서 알수 있듯이, 형변환 연산자는 그저 피연산자의 값을 읽어서 
지정된 타입으로 형변환하고 그 결과를 반환할 뿐이다.
그래서 피연산자인 변수 d의 값은 형변환 후에도 아무런 변화가 없다.

 

2. 정수형, 실수형 간의 형변환

 -  double을 float로 변환할 경우 가수 24번째 자리가 1이면 반올림하여 23번째 자리의 가수의 값이 1 증가함

 -  실수에서 정수로 변환시 소수점 값은 버림

 

3. 자동 형변환

  - 값의 범위가 작은 타입에서 큰 타입으로 형변환할 경우 생략할 수 있음

	int o1='a'; // char(2byte)
	long o3='A'; // char(2byte)
	long o2=123; // int(4byte)
	double a1=123.44f; //float(4byte)
	double a2='a'; // char(2byte)

정리하자면,

1. boolean을 제외한 나머지 7개의 기본형은 서로 형변환이 가능하다.

2. 기본형과 참조형은 서로 형변환할 수 없다.

3. 서로 다른 타입의 변수간의 연산은 형변환을 하는 것이 원칙이지만, 

값의 범위가 작은타입에서 큰 타입으로의 형변환은 생략할 수 있다.


문제

1. 변수, 변수이름, 변수 초기화 
2. 변수 명명 규칙 4가지 
3. 기본형 참조형에 대해서 설명
4. 상수에 대해서 설명
5. 리터럴에서 접미사와 접두사가 들어간 경우에 대한 설명
6. 인코딩, 디코딩 , UTF-8 / UTF-16 설명
7. 왜 int 가 byte, short에 비해 효율적인지 설명
8. 정밀도에 대해 설명
9. 정수형 오버플로어란
10. 정수형, 실수형의 간의 형변환 특징
11. 자동형변환이 가능한 경우는

 

본 글은 [자바의 정석 3판 - 저자 남궁성] 참고하여 작성했습니다!

틀린 부분이나 궁금한 부분 있으면 댓글 달아주세요  

'java' 카테고리의 다른 글

[java] 배열  (0) 2023.08.12
[java] 조건문, 반복문  (0) 2023.08.10
[정규표현식과 Pattern]  (0) 2023.03.14
[java] 연산자  (0) 2023.03.11
[Java 의 특징]  (0) 2023.03.06

댓글