Skip to content
290 changes: 290 additions & 0 deletions 3주차/자바 기초.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
# [Java] Java 기초(2)
## 1. 기본형 타입(Primitive type)과 참조형 타입(Reference type)
### 1-1. 기본형 타입(Primitive type)
- 총 8가지의 기본형 타입을 미리 정의하여 제공한다.
- 기본값이 있기 때문에 **Null**이 존재하지 않는다.
(만약 기본형 타입에 Null을 넣고 싶다면 **<span style="color:blue">래퍼 클래스</span>**를 활용한다.
- **실제 값**을 저장하는 공간으로 **<span style="color:blue">스택(Stack)</span>** 메모리에 저장된다.
- 만약 컴파일 시점에 담을 수 있는 크기를 벗어나 에러를 발생시키는 컴파일 에러가 발생한다. 주로 문법상의 에러가 많다.
ex) 세미콜론(;)을 안붙였다는 이유로 빨간 줄이 쳐지는 경우

<table>
<tr>
<th></th>
<th>타입</th>
<th>할당되는 메모리 크기</th>
<th>기본값</th>
<th>데이터의 표현 범위</th>
</tr>
<tr>
<td>boolean</td>
<td>논리형</td>
<td>1 byte</td>
<td>false</td>
<td>true, false</td>
</tr>
<tr>
<td>byte</td>
<td>정수형</td>
<td>1 byte</td>
<td>0</td>
<td>-128 ~ 127</td>
</tr>
<tr>
<td>short</td>
<td>정수형</td>
<td>2 byte</td>
<td>0</td>
<td>-32,768 ~ 32,767</td>
</tr>
<tr>
<td><strong>int(기본)</strong></td>
<td>정수형</td>
<td><strong>4 byte</strong></td>
<td>0</td>
<td>-2,147,483,648 ~ 2,147,483,647</td>
</tr>
<tr>
<td>long</td>
<td>정수형</td>
<td>8 byte</td>
<td>0L</td>
<td>-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807</td>
</tr>
<tr>
<td>float</td>
<td>실수형</td>
<td>4 byte</td>
<td>0.0F</td>
<td>(3.4 X 10-38) ~ (3.4 X 1038) 의 근사값</td>
</tr>
<tr>
<td><strong>double(기본)</strong></td>
<td>실수형</td>
<td><strong>8 byte</strong></td>
<td>0.0</td>
<td>(1.7 X 10-308) ~ (1.7 X 10308) 의 근사값</td>
</tr>
<tr>
<td>char</td>
<td>문자형</td>
<td>2 byte(유니코드)</td>
<td>'\u0000'</td>
<td>0 ~ 65,535</td>
</tr>
</table>

### 1-2. 참조형 타입(Reference type)
- 기본형 타입을 제외한 타입들이 모두 참조형 타입이다.
- 빈 객체를 의미하는 Null이 존재한다.
- 값이 저장되어 있는 곳의 **주소값**을 저장하는 공간으로 **<span style="color:blue">힙(Heap)</span>** 메모리에 저장된다.
- 문법상으로는 에러가 없지만, 실행시켰을 때 에러가 나는 런타임 에러가 발생한다.
ex) 객체나 배열을 Null 값으로 받으면 NulloPointException이 발생하므로 변수값을 넣어야 한다.

<table>
<tr>
<th>타입</th>
<th>기본값</th>
<th>할당되는 메모리 크기</th>
</tr>
<tr>
<td>배열(Array)</td>
<td>Null</td>
<td>4 byte(객체의 주소값)</td>
</tr>
<tr>
<td>열거(Enumeration)</td>
<td>Null</td>
<td>4 byte(객체의 주소값)</td>
</tr>
<tr>
<td>클래스(Class)</td>
<td>Null</td>
<td>4 byte(객체의 주소값)</td>
</tr>
<tr>
<td>인터페이스(Interface)</td>
<td>Null</td>
<td>4 byte(객체의 주소값)</td>
</tr>
</table>

## 2. 리터럴(Literal)
리터럴은 변수에 넣는 변하지 않는 **<span style="color:red">데이터</span>** 자체를 의미한다.
보통은 기본형의 데이터를 의미하지만, 특정 객체(Immutable class, VO class)에 한해서는 리터럴이 될 수 있다.

## 3. 변수의 선언 및 초기화
변수(Variable)는 데이터를 저장하는 메모리 영역을 의미한다.
변수는 수시로 값이 변경될 수 있으며 하나의 값만 저장할 수 있다.
> ### 상수(Constant)
> **<span style="color:red">변하지 않는 변수</span>**를 의미한다.
> **<span style="color:red">final</span>** 키워드로 선언하며, 대문자로 주로 표기한다.

###
자바의 변수는 다음과 같은 종류로 구분할 수 있다.
- 인스턴스 변수 : 클래스 선언시 ```static```키워드 없이 선언된 필드. 이 필드는 인스턴스 별로 다른 값을 가질 수 있기 때문에 인스턴스 변수라고 불린다.
- 클래스 변수 : 클래스 선언시 ```static```키워드와 함께 선언된 필드. 이 필드는 모든 인스턴스들이 공유하는 값이다. 클래스 명으로 접근이 가능하고, 클래스 하나에 한 값이기 때문에 클래스 변수라고 불린다.
- 로컬 변수 : 메소드 선언 사이에 등장하는 변수로 다른 클래스에서 접근할 수 없는 변수. 메소드 영역에서만 임시로 사용되는 변수이다.
- 매개 변수 : 매개 변수는 메소드의 인자로 전달되는 변수를 의미한다.

인스턴스 변수와 클래스 변수는 멤버 변수라고 통칭하기도 한다. 멤버 변수는 꼭 초기화를 해주지 않더라도 기본값으로 초기화되지만, 로컬 변수는 반드시 초기화를 해주어야 한다.

```java
class Variables {
int instanceVar; // 0으로 초기화되는 인스턴스 변수
static int classVar; // 0으로 초기화되는 클래스 변수
int initInstanceVar = 10; // 명시적으로 초기화
static int initClassVar = 10; // 명시적으로 초기화

void method(int num) { // 매개변수는 초기화 할 수 없고, 전달받는 값을 사용만 할 수 있음
int a; // 선언은 가능
// int b = a; 자동으로 초기화 되지 않으므로 동작하지 않음
a = 10; // 선언을 미리 해줬다면 이렇게 초기화 가능
int b = a; // 선언과 동시에 초기화
}
}
```

## 4. 변수의 스코프와 라이프타임
### 4-1. 스코프(Scope)
스코프는 변수가 유효한 범위를 의미한다.

### 4-2. 라이프타임(LifeTime)
라이프타임은 변수가 메모리에서 살아있는 기간을 의미한다.
<br>

|변수 타입|스코프|라이프타임|
|:---:|---|---|
|인스턴스변수|클래스 전체(static 블록과 static 메소드 제외)|객체가 생성되고 객체가 메모리에 살아있는 동안|
|클래스변수|클래스 전체|클래스가 초기화되고 프로그램이 끝날 때까지
|로컬변수|변수가 선언된 블록 내부|변수 선언 이후부터 블록을 벗어날 때까지|

## 5. 타입 변환, 캐스팅 그리고 타입 프로모션
타입 변환은 어떤 값이나 변수의 타입을 다른 타입으로 변경하는 것이다.
이 때 타입은 **확장(자동 형변환)**과 **축소(명시적 형변환)**두 가지 방향으로 변환될 수 있다.
### 5-1. 확장, 자동 형변환
확장은 다음 조건에서 두 데이터 타입이 자동으로 변환되는 경우이다.

1. 두 데이터 타입은 호환되어야 한다.
2. 더 작은 데이터 타입의 값을 더 큰 범위의 타입에 할당할 때만 동작한다.
(바이트 크기가 아닌 표현 가능한 값의 범위)

자바에서의 숫자 타입은 ```byte -> short -> int -> long -> float -> double``` 순으로 자동 형변환이 된다.

### 5-2. 축소, 명시적 형변환(Casting)
축소는 더 큰 범위의 타입의 값을 더 작은 범위의 타입에 할당하기 위해서 형변환을 명시해주어야 한다.
또, 확장과 달리 호환되지 않는 데이터 타입에도 사용할 수 있다.

```(타겟 타입) 값or변수```로 강제로 형변환을 할 수 있다.
```java
void 명시적_형변환() {
// 동작하지 않는 코드
char ch = 'c';
int num = 88;
ch = num;

// 동작하기 위해선 아래와 같이 수행해야 합니다.
ch = (char) num;
}
```

### 5-3. 타입 프로모션
타입 프로모션은 식을 평가할 때 중간에 피연산자의 범위를 초과할 수 있기 때문에 자동으로 값이 승격되는 것을 의미한다.

- Java에서는 ```byte```, ```short```, ```char```를 식 평가시 자동으로 ```int```로 프로모션 된다.
- 피연산자가 ```long```, ```float```, ```double```인 경우 전체 표현식이 각각 ```long```, ```float```, ```double```로 프로모션된다.

```java
void 타입_프로모션() {
byte b = 42;
char c = 'a';
short s = 1024;
int i = 50000;
float f = 5.67f;
double d = .1234;

// 표현식(명시적 형변환 없이 자동으로 형변환 되며, 값은 피연산자의 타입으로 프로모션 됩니다.)
double result = (f * b) + (i / c) - (d * s);
}
```

## 6. 1차원 및 2차원 배열 선언하기
### 6-1. 1차원 배열 선언
```java
int[] intArr1;
int []intArr2; // 권장하지 않음
int intArr3[]; // 권장하지 않음
```
셋 다 가능하지만, 가장 위의 스타일이 선호된다.

### 6-2. 1차원 배열 초기화
```java
int[] intArr1 = new int[10];
```
위와 같이 선언하면, 해당 크기만큼의 배열의 요소가 초기화되어 생성된다.
배열의 각 요소에는 인덱스로 접근할 수 있다.

또한 다음과 같이 초기화할 수도 있다.
```java
int[] anArray = {
100, 200, 300,
400, 500, 600,
700, 800, 900, 1000
};

int[] anArray = new int[] {100, 200, 300};
```
이런 경우 배열의 길이는 중괄호 사이에 선언된 요소의 수로 결정된다.
Java는 배열도 객체이기 때문에 힙 영역에 배열이 생성되며, ```new```라는 키워드를 써줘야 한다.

### 6-3. 2차원 배열 선언
```java
int[][] ints;
```
위와 같이 선언할 수 있다. 또한 Java에서의 다차원 배열은 **요소 자체가 배열**인 배열이다.
각 요소 배열간 길이는 다를 수 있다.

### 6-4. 2차원 배열 초기화
```java
String[][] names = {
{ "Mr.", "Mrs.", "Ms." },
{ "Smith", "Jones" }
};
// 각 배열 요소의 길이는 초기화시에 지정을 해주지 않아도 됩니다. 단, null로 초기화됩니다.
String[][] names2 = new String[10][];

// 혹은 지정해줄 수도 있습니다. 이 경우 같은 크기를 가지게 됩니다. 이 경우 배열이 초기화 됩니다.
String[][] names3 = new String[10][10];
```
이차원 배열도 마찬가지로 요소의 인덱스로 접근할 수 있다.

> 배열의 크기는 ```length``` 속성으로 알 수 있다. 그리고 배열은 한번 초기화하고 나면 변경할 수 없다.

## 7. 타입 추론, var
```var``` 키워드는 로컬 변수의 타입 추론이라고 한다.
이 키워드의 사용은 반복되는 타입 선언을 줄여주고, 코드의 가독성을 높여준다.
이는 컴파일러가 데이터의 타입을 추론해낼 수 있기 때문이다.

```java
var num = 3;
```
```3```은 ```int``` 타입을 반환하기 때문에 로컬 변수 ```num```은 ```int``` 타입임을 추론할 수 있다.

이렇게 이미 타입이 정의되었기 때문에 ```var```는 다른 타입의 재할당을 허용하지 않는다.

- ```var```를 사용할 수 없는 경우
1. 필드 혹은 메소드 시그니처에서 사용이 불가능하다. 지역 변수에만 사용할 수 있다.
2. 명시적인 초기화없이 ```var```만 단독으로 선언할 수 없다.
3. ```var``` 변수는 ```null```로 초기화할 수 없다.
4. 람다식과 ```var```는 명시적으로 타겟이 되는 타입을 알아야 하기 때문에 같이 사용할 수 없다.
- 주의해야할 ```var``` 선언
```java
var list = new ArrayList<>();
```
이 코드는 컴파일되지만, 실제 ```list```의 타입은 ```ArrayList<Object>```로 컴파일되며, 제네릭의 이점을 얻지 못하기 때문에 피하는 것이 좋다.

타입 추론은 가독성을 높일 수 있는 경우와 그것을 사용한 것이 유용한 경우에만 선택적으로 사용해야한다.

이 말의 의미는 편하게 코드를 작성하기 위해 ```var```를 쓰는 것이 아니라, 가독성을 높이는 목적으로 사용해야 한다는 의미이다.

```var```의 유형을 개발자가 추적할 수 없거나 어려운 경우에는 ```var```를 사용하지 않는 것이 좋다.
Loading