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

파이 ఇ·2023년 4월 29일
2
post-thumbnail

💡 목표 : 자바의 프리미티브 타입, 변수 그리고 배열을 사용하는 방법을 익힙니다.

⚡️ 목차

  • 프리미티브 타입 종류와 값의 범위 그리고 기본 값
  • 프리미티브 타입과 레퍼런스 타입
  • 리터럴
  • 변수 선언 및 초기화하는 방법
  • 변수의 스코프와 라이프타임
  • 타입 변환, 캐스팅 그리고 타입 프로모션
  • 1차 및 2차 배열 선언하기
  • 타입 추론, var

📌 프리미티브 타입 종류와 값의 범위 그리고 기본 값


Java에서 프리미티브 타입(Primitive type)이란 ? Java에서 제공하는 기본 변수 타입

  • 타입이란 ? 컴퓨터가 해당 데이터를 어떻게 식별할지 알려주는 분류 기준이라고 생각하면 된다

✔️ boolean
참, 거짓을 구분해주는 논리타입. Java가 데이터를 다루는 최소 범위가 1Byte이기 때문에 낭비적이지만 1Byte를 사용한다.
✔️ char
음수의 범위 없이 유니코드(0~65535) 범위를 문자 타입으로 저장한다. Java에서 유일하게 제공되는 unsigned 형태

  • unsigned ? 음수 없이 0부터 시작하여 양수 값만 가지는 데이터

✔️ byte, short, int, long
정수 타입을 나타낸다. 자료형에 따라 표현 가능한 범위가 다르며 정수 연산의 기본 타입은 int형으로 사용된다. 정수형 타입은 모두 기본값을 0으로 가지고 long 타입의 경우 0L로 가진다.
✔️ float, double
실수형 타입을 나타낸다. 자료형에 따라 float 타입은 소수점 아래 9자리 까지, double 타입은 소수점 18자리까지 나타낸다. double의 기본값은 0.0 float의 기본값은 0.0f이다

📌 프리미티브 타입(Primitive Type)과 래퍼런스 타입(Reference Type)

Java는 프리미티브(Primitive Type) 타입과 래퍼런스(Reference Type)로 나눌 수 있다. 프리미티브 타입은 기본형 타입. 또는 원시타입. 정수, 실수, 문자, 논리 등의 실제 데이터 값을 저장한다. 래퍼런스 타입new 키워드를 통해 생성된 객체 주소를 참조하는 타입이다. 배열, Class, 열거형(Enumeration = Enum), Interface가 래퍼런스 타입에 해당된다. 래퍼런스 타입의 데이터 크기는 가변적이고, 동적이기 때문에 1주차에서 배운 동적으로 관리되는 Heap 메모리 영역에 주소값을 저장한다. 또한, 래퍼런스 타입은 빈 객체를 의미하는 Null 값을 가지며, 호출이 완료된 이후에 더 이상 참조하는 값이 없다면 Java가 판단해 GC를 진행한다. 프리미티브 타입과 래퍼런스 타입의 가장 큰 차이점은 호출 방식이다.

프리미티브 타입인 경우 값에 의한 호출 (Call by value)로 변수를 호출하므로 메모리에서 변수의 값을 복사해서 사용하기 때문에 변수의 값을 바꾸더라도 메모리에 있는 값이 바뀌지 않는다. 하지만 래퍼런스 타입의 경우 참조에 의한 호출이다. 여기서 참조에 의한 호출(Call by Reference)이란 호출되는 변수의 메모리 주소를 복사해서 사용하는것이다. 따라서 참조에 의한 호출로 가져온 변수의 값을 바꾼다면 메모리 주소를 참조해서 사용했기 때문에 원본 값도 같이 바뀐다.

📌 리터럴

리터럴의 정의는 소스 코드의 고정된 값이다. 예를 들어 int a = 2; 여기서 a의 값은 2다.
그렇다면 리터럴은 2 가 된다.
✔️ 정수형 리터럴
정수형 리터럴은 long타입의 경우 L로 끝나고 나머지 정수형 리터럴은 int 타입이다. int 타입은 10진수, 2진수(Ob__), 16진수(0x__)로 나타낼 수 있다.

int a = 1;        // 10진수
int a2 = 0b11;    // 2진수
int a3 = 0x12;    // 16진수
long a4 = 1L;     //long 타입의 리터럴

✔️ 실수형 리터럴
실수형 리터럴은 float 타입의 경우 f로 끝나고, 나머지 실수형 리터럴은 double 타입이다.

float b = 1.111f;    // float 타입
double b2 = 1.111;   // double 타입

✔️ 문자 리터럴
문자 리터럴은 char 타입이고 문자열 리터럴은 String이다. 문자, 문자열 리터럴은 유니코드 값을 포함 할 수 있다.

char c = 'C';                // 문자 리터럴
char c2 = '\u1001';          // 문자 리터럴 (유니코드)
String c3 = "Hello world!"   // 문자열 리터럴

또한, Java는 문자, 문자열 리터럴에서 이스케이프 문자를 지원한다.

이스케이프 문자용도유니코드
\t수평 탭0x0009
\n줄 바꿈0x000a
\r리턴0x000d
\"큰 따옴표 표시0x0022
\'작은 따옴표 표시0x0027
\\ 역슬래쉬 표시0x005c
\u16진수16진수에 해당하는 유니코드0x0000 ~ 0xffff

✔️ 논리 리터럴
논리 리터럴은 boolean 타입이고 false, true 값 중 하나이다.

boolean b = true;
boolean ba = false; 

📌 변수 선언 및 초기화 하는 방법

변수란 ? 하나의 값을 저장하기 위해 프로그램에 의해 이름을 할당받은 메모리 공간
초기화란 ? 변수에 초기값을 주는 행위 또는 수에 값을 저장하는 행위

class subMain {
	private int sub;
  }
  
class Main {
	public static void main(String[]args) {
    	int a = 10;           // 기본타입 10 초기화
        int b;                // 초기화x
        int c, d;             // 여러개 변수 선언 (초기화x)
        int e = 10, f = 5;    // 여러개 변수 선언 (초기화o)
        Sub sub = new Sub();  // 래퍼런스 타입 선언
     }
}
// int e = 10, f - 5; -> 🚨서로 같은 타입만 여러개 변수 선언, 초기화 할 수 있음. 타입이 다르면 X

📌 변수의 스코프와 라이프 타임

스코프는 영어로 범위 라는 뜻. Java에서 변수의 스코프란 변수에 대한 접근과 변수가 존재할 수 있는 영역을 의미한다. Java는 {}(블록)을 벗어나면 변수가 소멸되는데 이런 변수를 지역 변수(local variable)라 하고 변수의 생성부터 소멸까지를 라이프 타임이라고 한다.

class Main {
	public static void main(String[]args) {
		int a = 10;     // 지역변수 {} 블록 내에서만 유효하다
		System.out.println(a);
	}
}

또 다른 예를 보면, a가 main메서드 밖에 존재한다. 그렇기 때문에 static int a = 10;은 Main 클래스 내에서 모두 접근이 가능하다 이러한 변수를 전역 변수라고 한다.

class Main {
	static int a = 10;   // 전역 변수  static을 붙여서 만든다.

	public static void main(String[]args) {
		System.out.println(a);
	}
}

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

타입 변환이란 특정 데이터 타입을 다른 데이터 타입으로 변환 시킬 수 있는것. int 타입의 경우 long 타입으로 변환이 가능한데 이런 것을 타입 변환이라 한다

int a = 10;
long b = a;  // int 타입인 a를 long 타입으로 변환

그렇다면 캐스팅프로모션은 무엇일까 ? 캐스팅과 프로모션은 모두 타입의 변환이라는 점에서 동일하지만, 타입의 범위에 따라 용어 구분한다.

✔️ 타입 프로모션
자동 형 변환이라고도 한다. 크기가 더 작은 타입을 더 큰 타입에 대입할 때 자동으로 작은 타입이 큰 타입으로 변환되는 현상.

int a = 10;
float b = a;

int 타입이 나타낼 수 있는 범위보다 float 타입이 나타낼 수 있는 범위가 더 넓으므로 int 타입 변수가 float 타입 변수로 대입된다. 이렇게 java는 자동으로 타입을 변환해주는데 이런 현상을 타입 프로모션 이라고 한다.

✔️ 타입 캐스팅
타입 프로모션과는 반대. 크기가 더 큰 타입을 더 작은 타입에 대입할 때 타입을 명시함으로써 강제로 집어넣는 현상

float a = 10;
int b = a; 

float 타입이 나타낼 수 있는 범위보다 int 타입이 나타낼 수 있는 범위가 더 작으므로 해당 코드는 에러를 발생 시킨다. 따라서, 캐스팅을 해줘야하는데 int b = (int) a;와 같이 명시적으로 타입을 변환해준다. 타입 캐스팅의 경우 큰 타입에서 작은 타입으로 변환시키는 것이기 때문에 데이터의 손실이 일어날 수 있다.

✔️ 참조 변수의 타입 변환
참조 변수 타입의 경우에는 상속 관계가 성립할 때만 타입 변환이 가능하다.

class Car {
	String color;
	int door;
}

class Suv extends Car {
	void info() {
		System.out.println("suv");
	}
}

참조 변수 타입이 캐스팅 되는 경우는 2가지로 나눌 수 있는데, upcastdowncast이다. upcast의 경우 서브 클래스에서 슈퍼 클래스로 변환되는 경우이며 타입을 명시해 줄 필요가 없다.

Car car = new Car();
Suv suv = new Suv();
car = suv;      // upcast

반대로 downcast의 경우 슈퍼 클래스가 서브 클래스로 변환되는 경우이며, 타입을 명시해 줄 필요가 있다.

Car car = new Car();
Suv suv (Suv) car;      // downcast

📌 1차 및 2차 배열 선언하기

배열(Array)란 순차적이고 인덱스 값을 가지고 직접 접근이 가능한 Random Access 특징을 가진다. 배열이 선언되면 데이터는 Heap 메모리에 저장된다.
✔️1차원 배열 선언

class Main {
	public static void main(String[]args) {
		//1차원 배열의 선언
		int[] arr = {1,2,3};
		int[] arr2 = new int[3];
	}
}

arr배열은 int 타입으로 1,2,3을 값으로 가지는 3크기의 배열을 생성한다.
arr2의 경우 배열의 크기로 선언해준다. (이러한 경우 초기화는 0으로 통일)
arr배열과 arr2 배열은 Heap에 아래와 같은 형식으로 저장된다.

✔️2차원 배열 선언

class Main {
	public static void main(String[]args) {
		//1차원 배열의 선언
		int[][] arr = {{1,2},{3,4}};
		int[][] arr2 = new int[2][2];
	}
}

2차원 배열은 먼저 인덱스로 해당 배열 주소에 접근한 후 해당 주소를 가지고 데이터에 다시 접근한다. 그림으로 보자

arr2의 경우에는 동일한 형식으로 데이터가 저장되며 똑같이 0으로 초기화 된다. 지금까지 보여준 배열은 프리미티브 타입의 배열인데, 참조타입의 배열인 경우 어떤식으로 접근이 될까 ?
✔️참조 타입 배열 선언
참조타입은 new 키워드로 동적으로 할당되기 때문에 해당 데이터의 주소값을 생성시에 가지고있다. 따라서, 참조타입의 배열은 2차원 배열과 비슷한 느낌으로 참조 타입 생성 객체 주소에 접근할 것이고 생성된 객체가 가지고 있는 주소에 해당 데이터가 존재할 것이다.

📌 타입 추론, var

Java의 타입 추론이란 코드 작성 당시 타입이 정해지지 않았지만, 컴파일러가 그 타입을 유추하는 것을 말한다. Java 10 이하 버전에서 타입 추론은 제네릭과 람다식에서 타입 추론 개념이 존재했다.

[출처]

profile
⋆。゚★⋆⁺₊⋆ ゚☾ ゚。⋆ ☁︎。₊⋆

0개의 댓글