[JAVA] 데이터 타입, 변수 그리고 배열

handa·2023년 3월 5일
0

데이터 타입 전 메모리에 대해서

  • 코드영역: 실행할 프로그램의 코드가 할당 될 공간
  • 데이터 영역: 프로그램이 종료될 때 까지 유지해야 할 데이터를 저장할 공간
  • 스택 영역: 아주 잠깐 사용하고 삭제할 데이터의 저장공간 변수는 모두 메모리에 저장됨.
  • 힙 영역: 긴 생명주기를 가진 데이터들이 저장됨.

1. 데이터 타입 (Primitive type, Reference type)

data의 종류는 크게 문자와 숫자, 숫자는 정수와 실수로 나눌 수 있다.
이러한 값의 타입에 따라 저장될 공간의 크기와 저장 형식을 정의한 것이 자료형, data type 이다.

1-1. 기본형 타입 (Primitive type)

논리형, 문자형, 정수형, 실수형 계산을 위한 실제 값을 저장한다.

  • 논리형: boolean
    true와 false 중에 하나를 값으로 가지며 조건식과 논리적 계산에 사용된다.

  • 문자형: char
    문자를 저장하는데 사용되며 변수 당 하나의 문자만 저장할 수 있다.

  • 정수형: byte, short, int, long
    정수 값을 저장하는데 사용된다.
    byte는 이진 데이터를 다루는데 주로 사용, short는 C언어와 호환을 위해서 추가되었다.

  • 실수형: float, double
    실수를 저장하는데 사용된다.

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

변수마다 사용할 수 있는 값의 범위가 있다. 이 범위를 초과하게 되면 오버플로우(overflow)현상이 발생한다.

실수형의 정밀도
실수형은 정수형과 저장 방식이 다르기에 같은 크기라도 훨씬 큰 값을 표현할 수는 있지만,
오차가 발생할 수 있다. 그래서 정밀도(precision)가 중요한데, 정밀도가 높을수록 오차의 범위가 줄어든다.

1-2. 참조형 타입 (Reference type)

참조형 타입은 위의 기본형 타입을 뺀 모든 형태(type)를 참조형 타입으로 볼 수 있다.
배열 (array[]), 열거 (enum), 클래스 (class), 인터페이스 (interface) 모두 참조형이라고 한다.

  • 기본형 과는 달리 실제 값이 저장되지 않고, 자료가 저장된 공간의 주소를 저장한다.
  • 실제 값은 다른곳에 있으면 값이 있는 주소를 가지고 있어서 나중에 그 주소를 참조해서 값을 가져온다.
  • 메모리의 힙(heap)에 실제 값을 저장하고, 그 참조값(주소값)을 갖는 변수는 스택에 저장
  • 참조형 변수는 null로 초기화 시킬 수 있다.
String name = "홍길동";
String[] hobby = new String() {"독서", "게임", "등산"};
Date Date = new Date();

2. 리터럴 (Literal)

리터럴은 데이터 그 자체를 뜻한다. 변수에 넣는 변하지 않는 데이터를 의미

2-1. 정수 리터럴

int a = 1;

a라는 변수에 1이라는 값을 직접적으로 초기화 시켰다.
변하지 않는 고정적인 값을 리터럴이라고 한다.

long e = 21L;

정수 리터럴은 int형으로 컴파일 되며, long 타입 리터럴은 숫자 뒤에 L 또는 l을 붙여 표시한다.

int a = 10;
int b = 10;

10이라는 값을 Heap 메모리 영역 안에 있는 Constant Pool이라는 메모리 영역에 할당한다.
똑같은 값의 변수가 2개이지만 자바는 똑같은 값을 가진 변수를 호출 했을 때 전에 할당했던 메모리 주소를 넘겨준다.

a==b가 true가 나오는 이유도 a와 b가 똑같은 메모리 주소를 가르키고 있기 때문이다.
==은 메모리 주소를 비교합니다.

Constant Pool

Integer, String 같은 래퍼런스 타입의 데이터 값 또는, 메소드 호출 Class 호출 등을 저장하는 JVM의 메모리 공간 중 하나이다.

2-2. 실수 리터럴

소수점 형태나 지수 형태로 표현한 값을 의미한다.
실수 타입 리터럴은 float, double 타입으로 컴파일 된다.

float h = 0.1234f;
float double = .1234D;

숫자 뒤에 f나 d를 명시적으로 붙이기도한다.
float 같은 경우에는 f를 꼭 붙여줘야하며, double는 생략 가능하다

2-3. 문자 리터럴

문자 리터럴은 단일 인용부호('')로 문자를 표현한다.

char a = 'a';
char b = '한';
char c = \uae00;

유니코드나 직접 입력이 불가능한 문자들에 대해서는 역슬래쉬()를 이용하여 표시할 수 있다.

2-4. 문자열 리터럴

문자열 리터럴은 기본타입이 아니며, 이중 인용 부호("")로 지정하여 사용한다.

class Test {
	public static void main(String[] args) {
    	String s1 = "str";
        String s2 = "str";
        
        System.out.println(System.identityHashCode(s1));	// 1134712904
        System.out.println(System.identityHashcode(s2));	// 1134712904
    }
}

3. 변수 선언 및 초기화

3-1. 변수 선언

변수를 선언하는 것은 미리 자원을 확보하는 동시에 사용한다는 의미를 가지고 있기 때문에 변수를 선언하지 않는다면 프로그램은 값(데이터)을 담아둘 공간이 없어 값을 사용할 수 없다.

public class Test {
	// 필드, 멤버변수, 전역변수
	char ch;
    
    double var1;
	
	String str = "";
    
    public static void main(String[] args) {
    	
    	//지역변수
        int a;		//int 타입의 변수 a 선언
        a = 10;		//변수 a에 10의 정수값으로 초기화

        int b = 'b';	//변수 b를 선언하면서 'b'의 값을 저장

        int c;		//int 타입의 변수 c 선언
        c = a;		//변수 c에 변수 a의 값을 저장
    }
}

3-2. 명시적 초기화

변수를 선언하고 바로 뒤에 '=' 대입 연산자를 사용해 변수에 데이터를 집어넣는 걸 명시적 초기화라고 한다.

public class Test{
	//필드, 전역(멤버) 변수
    int a = 1000;
}

전역변수에서는 선언을 하자마자 0으로 초기화
지역 변수는 아무것도 들어가 있지 않는다

public class Test{
	//필드, 전역(멤버) 변수
    int a;		//a=>0
    
    double b;	//b=>0.0
    
    void test(){
    	//지역 변수
    	int a;		//초기화X
        double b;	//초기화X
    }
}

3-3. 블록 초기화

  • 일반적인 초기화 블록(인스턴스 초기화 블럭) - 인스턴스 변수의 복잡한 초기화에 사용된다. 모든 생성자가 공통으로 수행해야 하는 로직이 있을 때 사용.
    Class가 new 를 통해 인스턴스를 생성하는 순간 초기화가 진행

  • 정적 초기화 블록(클래스 초기화 블럭) - 클래스 변수의 복잡한 초기화에 사용된다. 블럭 내에서는 로직도 추가할 수 있기에 명시적 초기화만으로 부족할 때 사용
    JVM이 클래스로더로 로딩 시점에 초기화 진행

class test{
	int hi = 3;
	
    static int hello = 10;
    
    //인스턴스 초기화 블럭
    {
    	hi = 5;
    }
    
    //클래스 초기화 블럭
	static {
    	hello = 20;
    }
}

4. 변수의 스코프와 라이프타임

스코프 (영역)
변수에 접근하거나 접근할 수 있는 유효 범위/영역
변수가 선언된 블록내에서만 엑세스 할 수 있다.
블록은 왼쪽 중괄호 { 로 시작하고 오른쪽 }로 끝난다.

변수의 라이프타임 (LifeTime)
변수가 메모리에서 살아있는 기간

4-1. 인스턴스 변수 (Instance Variables)

클래스 내부와 모든 메소드 및 블록 외부에서 선언된 변수

  • 스코프 - 정적 메서드를 제외한 클래스 전체

  • 라이프타임 - 객체가 메모리에 남아있을 때까지

4-2. 클래스 변수 (Class Variables)

클래스 내부, 모든 블록 외부에서 선언되고 static으로 표시된 변수

  • 스코프 - 클래스 전체

  • 라이프타임 - 프로그램이 끝날때까지 또는 클래스가 메모리에 로드 되는 동안

4-3. 지역 변수 (Local Variables)

인스턴스 및 클래스 변수가 아닌 모든 변수

  • 스코프 - 선언된 블록 내에 있음

  • 라이프타임 - 컨트롤이 선언 된 블록을 떠날때까지

5. 타입 변환, 캐스팅 그리고 타입 프로모션

연산을 수행하는 코드에서는 같은 타입끼리만 가능하다.
연산을 수행하기 전에 같은 타입으로 만드는 것을 타입변환이라고한다.
자바는 boolean을 제외한 나머지 기본 타입 간의 타입 변환을 할 수 있다.

  • 프로모션(자동/묵시적 형변환) - 작은 데이터 타입에서 큰 데이터 타입으로 형 변환

  • 캐스팅(명시적 형 변환) - 큰 데이터 타입에서 작은 데이터 타입으로 형 변환

5-1. 자동 형변환(프로모션)

자동 형변환은 두 데이터 타입이 자동으로 변환이 이루어지는 것을 말한다.
자바에서는 데이터의 손실이 발생하지 않거나 손실이 최소화되는 방향으로 타입 변환을 진행하며 범위가 작은 데이터 값을 더 큰 데이터 타입으로 할당하는 경우에만 동작한다.

char a = 'a';

int num = a;
System.out.println(num)	//char 타입의 변수 a가 int형으로 자동 형변환 되어 97 출력

5-2. 명시적 형변환(캐스팅)

명시적 형변환은 범위가 큰 타입의 값을 작은 타입으로 할당하기 위해서 사용한다.

char a = 'a';
int num = 100;
a = (char)num;

6. 1차 및 2차 배열 선언하기

int[] arr1 = new int[5]{1,2,3,4,5}; 	//1차 배열 선언 및 생성


int[][] arr2 = new int[2][2]{{1,2},{3,4}}; 	 //2차 배열 선언 및 생성

배열은 실제 값이 저장되어 있는 메모리의 주소를 가리키는 배열의 주소를 가지고 있다.

7. 타입 추론, var

7-1. 타입 추론 (Type Inference)

  • 변수의 타입을 명시적으로 적어주지 않아도, 컴파일러가 알아서 이 변수의 타입을 대입된 리터럴로 추론하는 것

  • 컴파일 시점에, 컴파일러가 오르쪽에 있는 초기화 값 리터럴로 타입을 추론한다.

public class test {
	public static void main(String[] args) {
    	var str = "Hello type inference";
        
        if(str instanceof String) {
        	System.out.println("str 변수의 타입은 String 이다.");	//str 변수가 String 타입으로 선언되어 출력된다.
        }
    }
}

7


-2. var

  • var는 키워드가 아니다
    어떠한 타입도 아니고, 클래스에서 사용할 수 있는 예약어가 아니다.
    int를 변수 이름으로 만들수는 없지만, var라는 문자를 변수로 사용 가능핟.
public class test {
	public static void main(String[] args) {
    	var var = 3;	//에러 발생 X
    }
}
  • var는 런타임 옵더헤드가 없다.
    자바스크립트와 같;은 언어들은 let으로 선언되 변수를 중간에 다른 값으로 변경할 수 있다.
    ex)let number = 10; -> number = "Hello";

자바에서는 컴파일러 에러가 발생한다.

public class test {
	public static void main(String[] args) {
    	var var = 3;
        var = "Hello";	//컴파일러 에러 발생
    }
}
  • var의 잘못된 사용법
public class test {
	
    //var 타입은 로컬 변수에만 선언이 가능하다.
	var var = "No member variable";
    int number = 3;
    
    private void test() {
    	var var1 = "No member variable";
    }
    
	public static void main(String[] args) {
    
    	//var는 초기화없이 사용할 수 없다.
    	var var;
        
        //var 타입 변수에는 null 값이 들어갈 수 없다.
        var var = null;
    }
}
profile
진짜 해보자

0개의 댓글