새소식

프로그래밍 언어/JAVA

자바 기초 - 4. 변수와 데이터 타입

  • -
💡 기초 복습 겸 다시 정리하고 있습니다. 설명이 부족한 부분이 있을 수 있으니 고려하여 읽어주시기 바랍니다.

 

변수(Variable)


프로그램은 필요에 따라 데이터를 메모리에 저장하고 사용하게 됩니다. 이러한 하나의 값만을 저장하는 메모리 공간을 변수라고 합니다.

 

변수에는 복수 개의 값을 저장할 수 없고, 한가지 타입의 값만 저장할 수 있습니다.

 

변수란 이름을 갖게 된 이유는 프로그램에 의해 수시로 값이 변동 될 수 있기 때문입니다.

 

 

📌 변수의 선언과 초기화


변수의 선언이란 데이터를 메모리에 저장하기 위해 공간을 확보하는 작업이라고 할 수 있습니다.

 

데이터 저장을 위해 얼마만큼의 메모리 공간을 확보해야하는지 컴파일러에게 알려줄 필요가 있는데, 이 때 데이터의 타입을 이용해서 알려줄 수 있습니다.

 

메모리 공간을 확보했다면, 확보된 메모리 공간의 주소를 알아야 데이터를 저장하거나 가져올 수 있습니다. 메모리 주소는 16진법으로 이루어져있는데, 이러한 16진수들을 매번 적어서 사용하기엔 불편함이 큽니다. 그래서 이러한 변수를 관리하기 쉽게 이름을 붙여주어 사용하게됩니다.

 

이렇게 데이터를 저장하기 위해 타입을 통해 공간을 확보하고 변수의 이름을 지정하는 것을 변수의 선언(Declaration)이라 합니다.

 

변수는 다음과 같이 선언할 수 있습니다.

// 타입 변수이름;
String name; // declaration
int age;

// 한번에 동일 타입의 여러 변수를 선언 가능
int x,y,z ;

 

 

📌 변수의 Naming Convention


 

자바에서는 다음과 같은 Naming 규칙을 지키도록 권장하고 있으며 시스템적으로 강제되는 부분이 존재합니다. 관례인 부분은 강제는 아니지만 거의 모든 개발자가 지키고 있는 규칙이므로 준수하는 것이 좋습니다. 

 

  1. 첫 번째 글자는 문자이거나 '$' , '_' 이어야 하고, 숫자로 시작할 수 없다. - 강제
  2. 영어의 대소문자가 구분된다. - 강제
  3. 자바 예약어는 사용할 수 없다. - 강제
  4. 카멜 케이스 명명 규칙을 따른다. (첫 문자는 영어 소문자로 시작, 다른 단어가 붙는다면 첫문자를 대문자로) - 관례
  5. 문자 수(길이)의 제한은 없다.(다만, 간단 명료하게 작성하도록 해야합니다.)
  6. 공백(띄어쓰기 등)은 사용할 수 없다.

 

예약어는 다음과 같습니다.

 

예약어란 이미 문법적인 용도로 사용되고 있기 때문에 식별자로 사용할 수 없는 단어를 의미

 

 

변수의 이름은 되도록이면 이 변수가 어떤 값을 저장하고 있는지 한눈에 알아볼 수 있도록 의미 있는 이름으로 짓는 것이 좋습니다. 

 

변수 이름으로 한글을 사용해도 상관없지만 되도록이면 영어를 사용하는 것이 좋습니다.

 

 

📌변수의 사용


변수를 사용하는 목적은 데이터를 저장하고 불러오기 위함이라고 앞서 이야기 했습니다.

 

선언된 변수에 처음으로 값(초기값)을 저장하는 것을 초기화(Initialization)이라고 합니다.

 

초기화는 다음과 같이 할 수 있습니다.

int age;
age = 20; // initialization

int price = 100; // 선언과 동시에 초기화

 

변수의 초기값은 코드에서 직접 입력하는 경우가 많은데, 소스 코드 내에서 직접 입력된 값을 리터럴(Literal)이라고 합니다.

 

리터럴은 다음과 같은 종류가 있으며, 각각 정해진 표기법대로 작성되어야 합니다.

 

  • 정수 리터럴 - byte, char, short, int, long
// 소수점이 없는 정수 리터럴은 10진수
0, 75, -100

// 0 으로 시작되는 리터럴은 8진수
02, -04

// 0x 또는 0X로 시작하고 0~9나 A,B,C,D,E,F(소문자도 가능)로 구성된 리터럴은 16진수
0x5, 0xA, 0xB3

 

  • 실수 리터럴 - float, double
// 소수점이 있는 리터럴은 10진수 실수
0.25, -3.14

// 대문자 E 또는 e 가 있는 리터럴은 10진수 지수와 가수
5E7 // 5 * 10^7

 

  • 문자 리터럴 - char
// 작은 따옴표(')로 묶은 하나의 문자는 문자 리터럴
'A', '한'

// 역슬래쉬(\)가 붙은 문자 리터럴은 이스케이프 문자로 특수한 용도로 사용
 '\n', '\t'

 

  • 문자열 리터럴 - String
// 큰 따옴표로 묶은 문자들은 문자열 리터럴
"대한민국", "토리"

// 문자가 없더라도 문자열 리터럴로 간주
""

 

  • 논리 리터럴 - boolean
// 참과 거짓의 논리 리터럴로 두가지만 존재
true, false

 

변수는 중괄호 {} 블록 내에서 선언되며, 선언된 블록 내에서만 사용될 수 있습니다.

자세한 내용은 밑의 변수의 종류에서 다뤄보도록 하겠습니다.

 

📌 변수의 종류


자바에서 변수는 선언 위치에 따라 사용될 수 있는 범위(Scope)가 달라지며, 크게 두 종류로 나눌 수 있습니다.

 

 

🔎 전역 변수(Global Variable)


함수 바깥에서 선언되어 어느 위치에서든 호출하여 사용 가능한 변수를 전역 변수라고 합니다.

 

자바에서는 클래스 영역에 선언된 변수를 뜻하며 멤버 변수 및 field 라고 불립니다.

 

전역 변수는 다시 static 변수인지 아닌지로 나뉩니다.

 

 

📢 클래스 변수(Class Variable)

static과 함께 선언된 변수로 모든 인스턴스가 공통된 변수를 공유하게 됩니다.

 

클래스가 로딩될 때 생성되며 원시타입의 경우, 초기화하지 않으면 해당 타입의 기본값으로 자동으로 초기화됩니다.

 

public class Example {
    static int staticVariable = 10; // 클래스 변수

    public void method() {
        System.out.println(staticVariable); // 10
    }
 
}

 

📢 인스턴스 변수(Instance Variable)

클래스의 인스턴스마다 고유한 값을 가지는 변수로 인스턴스간에 공유되지 않습니다.

 

클래스 인스턴스가 생성될 때 만들어지며 원시타입의 경우, 초기화하지 않으면 해당 타입의 기본값으로 자동으로 초기화됩니다.

 

public class Example {
    int instanceVariable = 10; // 인스턴스 변수

    public void method() {
        System.out.println(instanceVariable); // 10
    }
    
}

 

 

🔎 지역 변수(Local Variable)


블록 내에 선언되어 블록 내에서만 사용되는 변수를 지역변수라고 합니다.

 

자바에서는 메서드 내부(생성자 및 초기화블록 포함)에서 선언되어 메서드 내에서만 사용하는 변수를 의미합니다.

 

초기화하지 않고 사용하면 컴파일 오류가 발생하게 됩니다.

 

public class Example {

    public void method() {
        int localVariable = 10; // 지역 변수
        System.out.println(localVariable);
    }
    
}

 

 

데이터 타입 (Data Type)


모든 변수는 타입을 가지고 있으며, 타입에 따라 저장할 수 있는 값의 종류와 범위가 달라지게 됩니다.

 

변수를 선언할 때 주어진 타입은 도중에 변경할 수 없으므로, 사용하는 상황에 맞춰 신중하게 결정해야 합니다.

 

데이터 타입은 두 종류로 나눠볼 수 있습니다.

 

📌 기본 타입 (원시 타입, Primitive Type)


리터럴을 직접 저장하는 타입들을 의미합니다.

 

기본 타입에는 다음과 같은 타입들이 존재합니다.

 

리터럴을 저장하는 기본 타입들

 

타입에 저장할수 있는 값의 범위를 초과하는 값을 저장하게 되는 경우, 올바르지 않은 값인 쓰레기 값이 저장되므로 각 타입이 어느정도의 크기를 가지고 있는지 알고 있으면 좋습니다..

 

📢 byte

색상 정보 및 파일, 이미지 등의 바이너리(이진) 데이터를 처리할 때 주로 사용됩니다.

 

1byte(8bit)의 크기를 가지고 있기에 -2^7 ~ (2^7 -1) 인  -128 ~ 127 까지의 수를 저장할 수 있습니다.

 

💡 8bit가 2^8이 아닌 2^7인 이유는 최상위 비트(MSB)가 정수 값의 부호(-,+)를 결정하기 때문입니다.

 

public class Example {

	public static void main(String[] args){
    
    	byte var1 = -128;
        byte var2 = -50;
        byte var3 = 0;
        byte var4 = 50;
        byte var5 = 127;
        // byte var6 = 128; // 컴파일 에러 발생
    }
}

 

 

📢 char

문자 하나를 저장할 때 주로 사용됩니다.

 

문자 리터럴은 유니코드로 변환되어 저장되는데, 자바는 하나의 유니코드를 저장하기 위해 2byte 크기인 char 타입을 제공하고 있습니다.

 

문자에는 음수가 없기 때문에 char 타입에는 음수 값을 저장할 수 없고, 그에 따라 0 ~ 65535(2^16 -1) 만큼의 크기를 갖습니다.

 

public class Example {

	public static void main(String[] args){
    	
        // 문자를 ' ' 작은 따옴표로 감싸야 합니다.
    	char var1 = 'A';
        char var2 = '5';
        char var3 = '가';
        // char var4 = ''; // 빈 문자를 대입시 컴파일 에러 발생, 공백을 원할 경우 ' ' 한칸 띄어서 사용
       
        // 유니코드를 알고 싶다면 char 변수를 int 변수에 저장
        int uniCode = var3;
        
        System.out.println(uniCode); // 44032

		// 문자가 아닌 유니코드 정수 값으로도 저장 가능(10진수, 16진수)
        char unicodeLiteral = 44032;
        
        System.out.println(unicodeLiteral); // 가
        
        // 16진수로 저장할 경우 \u + 16진수값의 형태로 저장
        char example = '\u0041';
        
        // 작은 따옴표를 연달아 붙여 초기화할 수 없으므로, 필요하다면 공백을 넣어 초기화
        char empty = ' ';
    }
}

 

📢 short

2byte로 표현되는 정수 값을 저장할 때 사용 합니다.

C언어와의 호환을 위해 사용되며 비교적 잘 사용되지 않습니다.

 

 

📢 int

4byte로 표현되는 정수값을 저장할 때 사용합니다.

 

자바에서는 정수 연산 시, 기본적으로 int 타입으로 연산이 이루어집니다. 때문에 메모리 아낀다고 byte나 short로 저장해서 사용하면 메모리는 얻을지언정 속도가 느려집니다...

 

값을  8진수, 10진수, 16진수로 표현해 저장할 수 있습니다.

 

 

📢 long

8byte로 표현되는 정수값을 저장할 때 사용합니다.

 

보통 수치가 큰 데이터를 다룰 때 사용합니다. long타입보다 큰 수를 다뤄야한다면, 참조타입을 사용한 여러가지 방법(BigDecimal 등등..)이 존재합니다. 이는 다음에 해당 주제를 다룰 때 설명하도록 하겠습니다.

 

int 타입보다 큰 수를 long 타입의 변수에 초기화할 때에는 정수값 뒤에 소문자 l이나 L을 붙여 컴파일러에 8byte 정수 데이터임을 알려주어야 합니다. 보통은 대문자 L을 사용합니다.

 

public class Example {

	public static void main(String[] args){
    	
    	long var1 = 10;
        long var2 = 10L;
        long var3 = 10000000000L;
        // long var4 = 10000000000; // 컴파일 에러 발생
      
    }

}

 

📢 float, double

소수점이 있는 실수 데이터를 저장할 때 사용합니다.

메모리 사용 크기가 int와 long과 동일하지만 부동 소수점 방식으로 저장되기 때문에 정수 타입보다 더 큰 범위의 값을 저장할 수 있습니다.

 

조금 더 정밀하게 값을 저장하고 싶다면 float 대신 double을 사용하는 것이 좋습니다.

 

자바는 실수 리터럴의 기본 타입을 double 타입으로 간주하므로, 실수 타입을 float 타입으로 저장하려면 리터럴 뒤에 소문자 f나 대문자 F를 붙여야합니다.

 

정수 리터럴에 10의 지수를 나타내는 E 또는 e를 포함하고 있다면 정수타입 변수에 저장할 수 없고 실수 타입 변수에 저장해야 합니다.

 

public class Example {

	public static void main(String[] args){
    	
    	float var1 = 3.14f;
        // float var2 = 3.14; // 컴파일 에러
        double var3 = 3.14;
       	double var4 = 3e6; // 3000000
      
    }

}

 

자바에서는 부동소수점 방식으로 인해 실수 연산 시 정확한 값을 도출하지 못할 수 있습니다. 그렇기 때문에 되도록이면 실수 연산을 지양하고 필요하다면 BigDecimal이라는 참조 타입을 사용하는 것이 좋습니다.

 

public class Example {

	public static void main(String[] args){
    	
    	int x = 1;
        double y = 0.1;
        
        int num = 7;
        
        double result = x - y * num;
        
        System.out.println(result);  // 0.3이 아닌 0.29999999999999993 출력
      
    }

}

 

 

📢 boolean

두 가지 상태값을 저장할 때 사용되며 주로 조건문과 제어문의 실행 흐름을 변경하는데 사용됩니다.

 

true 와 false를 저장할 수 있습니다. (다른 언어와 달리 1이나 0을 저장할 수 없습니다. 정수는 int형으로 취급하기 때문입니다.)

 

 

📌 참조 타입 (Reference Type)


객체의 주소를 저장하는 타입을 의미합니다.

 

정확히는 객체가 저장되고 있는 메모리의 주소 값이 저장되며, 해당 주소값을 통해 객체를 참조하게 됩니다.

 

String, 배열 타입, 열거 타입, 클래스, 인터페이스 등이 이에 해당됩니다.

 

 

📌 기본 타입 vs 참조 타입


  기본 타입 참조 타입
값 저장 위치 Stack Heap
null 허용 X O
Generic 타입에서 사용여부 X O
성능 우세 열세
== 비교 연산 값 비교 주소 비교

 

 

타입 변환


데이터 타입을 다른 데이터 타입으로 변환하는 것을 타입 변환이라 합니다.

 

타입 변환에는 두가지 종류가 존재합니다.

 

📌 자동 타입 변환 (Promotion)


프로그램 실행 도중 자동적(묵시적)으로 타입 변환이 일어나는 것을 뜻합니다.

 

보통 작은 메모리 크기를 가진 타입이 큰 메모리 크기를 가진 타입에 저장될 때 이루어집니다.

큰 크기 타입 = 작은 크기 타입 // 자동 타입 변환 발생!!

 

원시 타입에서 크기별로 타입을 정리하면 다음과 같습니다.

byte < short < int < long < float < double

// float가 long보다 큰 이유는 표현할 수 있는 값의 범위가 float가 더 크기 때문

 

예외적으로 char 타입의 경우, 음수 값을 가질 수 없기 때문에 음수값이 저장될 수 있는 byte 타입은 char로 자동변환할 수 없습니다.

 

참조 타입에서는 부모 타입에 자식 타입을 저장할 수 있습니다. 자세한 내용은 다형성이나 상속을 다룰 때 설명하겠습니다.

 

public class Example {

	public static void main(String[] args){
    	
        // 올바른 예
    	byte byteVal = 10;    
        int intVal = byteVal;  // byte -> int 로 자동 타입 변환
        double doubleVal = intVal; // int -> double
        
        
        // // 자식 타입을 부모 타입으로 자동 타입 변환
        Cat cat = new Cat();
        Animal animal = cat;
      
    }

}

 

앞서 정수 연산은 int를 이용해서 한다고 했는데, int보다 작은 값들은 int로 변환, 만약 long이 있다면 long으로 변환되어 계산됩니다. (크기가 큰 타입에 맞춰서 변환하여 계산하되, int보다 작은 타입끼리의 계산은 int로 변환하여 계산됩니다.)

 

📌 강제 타입 변환 (Casting)


큰 크기의 타입을 작은 크기의 타입으로 강제(명시적)로 변환하는 것을 의미합니다.

 

강제 타입 변환은 캐스팅 연산자 ( ) 를 사용합니다.

작은 크기 타입 = (작은 크기 타입) 큰 크기 타입 // 명시적으로 타입변환을 작성

 

만약 큰 크기의 타입의 값이 작은 크기의 타입에 들어갈 정도의 크기라면 원래의 값이 보존되지만, 그렇지않다면 원래의 값은 보존되지 않습니다.

 

특히 정수 값을 실수로 변환할 때 조심해서 사용해야 합니다.

예를 들어, int 값의 크기는 32비트지만, float의 가수는 23비트이므로 강제 변환 시 손실이 발생될 수 있습니다.(double은 가능)

public class Example {

	public static void main(String[] args){
    	
        // 올바른 예
    	int intVal = 10;
        byte byteVal = (byte)intVal;  // int -> byte 로 강제 타입 변환
        
        // 큰값을 작은 데이터 타입으로 캐스팅하는 경우
        int intVal2 = 10000;
        byte byteVal2 = (byte)intVal2;  // 16
        
        String binary = Integer.toBinaryString(10000); // 10011100010000 , 여기서 뒤의 8비트가 끊어져서 저장이 됩니다.
        int decimal = Integer.parseInt("00010000", 2); // 16
     
     	// 부모 타입을 자식 타입으로 강제 캐스팅
        Animal animal = new Animal();  
        Cat cat = (Cat)animal;
      
    }

}

 

📌 연산식에서의 자동 타입 변환


연산은 기본적으로 같은 타입 간에만 수행되기 때문에 서로 다른 타입을 연산할 경우, 두 피연산자 중 크기가 큰 타입으로 자동 변환된 후 연산이 수행됩니다. 

 

자바는 정수 연산이 기본적으로 int 타입으로 이루어지므로, int 타입보다 작은 타입들의 연산의 결과는 int 타입으로 저장 됩니다.

 

실수 연산의 경우, 실수 리터럴이나 double 변수의 연산이 이루어진다면 연산의 결과는 double 타입으로 저장됩니다.

 

public class Example {

	public static void main(String[] args){
        
		byte byte1 = 10;
		byte byte2 = 10;
        
		// byte result1 = byte1 + byte2; // 결과가 int로 나오므로 컴파일 에러
		int result2 = byte1 + byte2; 
      	
      	double double1 = 1.5;
      	double result3 = 1.4 + dobule1;
        
        // float float1 = 1.4 + 1.4f; // 실수 리터럴이 포함되어 결과가 double이므로 컴파일 에러
    }

}

 

 

참고자료

이것이 자바다 - 신용권의 JAVA 프로그래밍 정복

https://velog.io/@skyepodium/%EC%9E%90%EB%B0%94-%EC%84%A0%EC%96%B8%EC%9C%84%EC%B9%98%EC%97%90-%EB%94%B0%EB%A5%B8-%EB%B3%80%EC%88%98%EC%9D%98-%EC%A2%85%EB%A5%98-3%EA%B0%80%EC%A7%80

https://velog.io/@ikerbm94/%EC%A0%84%EC%97%AD%EB%B3%80%EC%88%98Global-Variable%EC%99%80-%EC%A7%80%EC%97%AD%EB%B3%80%EC%88%98Local-Variable

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.