백기선 님의 유튜브 온라인 자바 스터디를 정리한 글입니다
2주차
WEEK 02 :: 자바 데이터 타입, 변수 그리고 배열
- 프리미티브 타입 종류와 값의 범위 그리고 기본 값
- 프리미티브 타입과 레퍼런스 타입
- 리터럴
- 변수 선언 및 초기화하는 방법
- 변수의 스코프와 라이프타임
- 타입 변환, 캐스팅 그리고 타입 프로모션
- 1차 및 2차 배열 선언하기
- 타입 추론, var
프리미티브 타입 종류와 값의 범위 그리고 기본 값
- Primitive Type : 원시 타입, 기본형 타입. 변수의 주소 값에 값이 그대로 저장되는 데이터 타입
- 값이 할당되면서 실제 값을 JVM의 Runtime Data Area 영역 중 Stack 영역에 값이 저장
- 기본 값이 있기 때문에 Null이 존재하지 않는다. Null을 넣고 싶다면 래퍼(Wrapper) 클래스를 활용.
- 값이 범위를 벗어나면 컴파일 에러 발생
- 값 저장.
구분 | 타입 | 기본값 | 값의 표현 범위 | 할당되는 메모리 크기 |
---|---|---|---|---|
논리형 | boolean | false | true, false | 1byte |
정수형 | byte | 0 | -128 ~ 127 | 1byte |
short | 0 | -32,768 ~ 32,767 | 2byte | |
int | 0 | -2,147,483,648 ~ 2,147,483,647 | 4byte | |
long | 0L | - 9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 (-2^63 ~ 2^63-1) | 8byte | |
실수형 | float | 0.0f | (3.4 X 10^38) ~ (3.4 X 10^38) 의 근삿값 | 4byte |
double | 0.0 | (1.7 X 10 ^ -308) ~ (1.7 X 10^308)의 근삿값 | 8byte | |
문자형 | char | '\u0000' | 0 ~ 65,535 | 2byte |
- 1bit = 0 또는 1, 2진수 1자리
- 비트가 1자릿수 늘어나면 표현할 수 있는 표현 범위는 2배가 됨
- 2비트 = 4개, 3비트 = 8개, 4비트 = 16개.
- 즉 2의 제곱승(2^비트)으로 표현 가능
- 비트가 1자릿수 늘어나면 표현할 수 있는 표현 범위는 2배가 됨
- 1 byte = 8 bit
- 최상위 비트는 양수와 음수를 표현. - 부호비트
- 값이 1이면 음수, 0이면 양수
-
X 0 0 0 0 0 0 0 - 숫자 0은 값, X는 부호비트
- 실수는 부호, 가수, 지수로 구성. 부동 소수점 방식 사용
- 모둔 가수를 0보다 크거나 같고, 1보다 작은 값 범위의 값으로 만들고, 10의 제곱수로 표현
- float 타입 : 부호(1비트) + 지수(8비트) + 가수(23비트) = 32비트 = 4바이트
- double 타입 : 부호(1비트) + 지수(11비트) + 가수(52비트) = 64비트 = 8바이트
프리미티브 타입과 레퍼런스 타입
- Reference Type : 참조형 타입. Primitive Type을 제외한 타입들을 이야기 한다.
- 실제 값이 저장되어 있는 곳의 주솟값 을 저장하고 힙(Heap) 메모리에 저장된다.
실제 객체는 힙 영역에 저장되며 참조 타입 변수(인스턴스)는 스택 영역에 있는 실제 객체들의 주소를 저장하여, 객체를 사용할 때 마다 참조변수(인스턴스)에 젖아된 객체의 주소를 불러와 사용한다
.- 다만, 참조 변수의 값인 주솟값이 가리키는 실제 값은 가비지 컬렉션 힙 영역에 객체가 생성된다.
- Primitive Type의 경우 실제 값이 아닌 주소값이 복사되기 때문.
- 레퍼런스 타입은 미리 정의되어 있지 않고 종류는 무한하다. - 개발자가 작성해서 정의하기 때문
- 모든 레퍼런스 타입은 java.lang.Object 유형의 하위 클래스이다.
- Null을 저장할 수 있다.
- 주소값을 저장.
- Refrence Type 종류
- class
- interface
- array
- enum
- string
- 크기 : 4byte (객체의 주솟값)
- 주솟값을 참조한다?
public class Car {
private String name;
private int number;
public static void main(String[] args) {
String carName = "kia";
int carNumber = 4848;
Car kia = new Car(carName, carNumber);
}
}
- carName 와 carNumber 변수는 런타임 스택 영역에 생성된다.
- Car를 인스턴스화 (new) 시키면 Heap 영역에 name은 "kia", number는 "4848" 인
객체
가 생성되고, kia 변수는 Heap 영역에 저장된객체
의 주소가 저장된다. - 주소에 의한 복사(call by reference)
- 얕은 복사 : 주소값을 복사하여 동일한 객체를 참조.
- 값을 수정하면 복사된 원본 객체도 변함.
- 깊은 복사 : primitive type에서의 값에 의한 복사처럼 완전히 똑같은 새로운 객체를 만들어 복사.
- 값을 수정해도 복사된 원본 객체는 변하지 않음.
- 얕은 복사 : 주소값을 복사하여 동일한 객체를 참조.
- 정적 메모리 스택(Stack) 영역
- 스택 영역에는 Primitive Type 변수가 할당되고 변수의 실제
값
들이 저장된다. - Reference Type 의 변수들은 이 스택 영역에서 힙 영역에 생성된 객체들의
**주소 값을 저장**
한다 - 객체 안의 메소드의 작업이 종료되면 할당되었던 메모리 공간은 반환되어 비워진다.
- 스택 영역에는 Primitive Type 변수가 할당되고 변수의 실제
- 동적 메모리 힙(Heap) 영역
- 힙 영역에는 객체와 배열이 생성된다.
- 그리고
참조타입
(배열, 클래스, 인터페이스 등)들이이 객체들의 주소
를스택 영역
에 저장한다. - 프로그램 실행시 메모리에 동적으로 할당된다.
- 참조하는 변수가 없으면
가비지 컬렉터
가 회수해서 제거한다.
리터럴
- 실제로 변수나 상수에 저장되는 값 그 자체를 의미
- Primitive Type 과 String이 있다.
- 정수 리터럴, 실수 리터럴, 문자 리터럴, 논리 리터럴, 문자열 리터럴
int age = 28;
double average = 90.5;
boolean isHungry = true;
char firstCharacter = 'A';
String name = "ys";
- 다른 리터럴들은 Primitive Type 의 값을 표현하기 위해 존재.
- Primitive Type은 값을 Heap 메모리 영역 안에 있는 Constant Pool 이라는 메모리 영역에 할당
- 똑같은 값을 또 호출 했을 때 전에 할당했던 메모리 주소를 넘겨주게 됩니다.
- a == b 가 true인 이유는 a 와 b가 똑같은 메모리 주소를 가르키고 있기 때문입니다.
- **
==
은 메모리 주소를 비교.**
- **
- 문자열(String)은 Reference Type 이지만 literal 을 지원
- literal 방식으로 String 에 값을 주면 Heap 영역에서
String constant pool
이라는 특수한 영역에 값이 저장된다. - 동일한 값을 쓰는 경우에 다른 일반적인 레퍼런스타입 처럼 Heap 에
또 올라가지 않고
, String constant pool 에 존재하는 값을 참조하는 방식으로 작동
변수 선언 및 초기화하는 방법
- 선언 : 타입 변수명;
- 초기화 : Primitive 타입은 대입 연산자로 대입, Reference 타입은 대입 연산자로 대입하거나 new로 선언
int brotherAge; // 선언
brotherAge = 30; // 초기화. 선언한 다음 초기화
int age = 28; // 대입연산자로 대입. 선언과 동시에 초기화
Car kia;
kia = new Car();
Car audi = new Car();
- 변수를 선언하고 나면 해당 공간에는 쓰레기 값이 들어가 있게 된다.
- 초기화를 해주지 않으면 컴파일 에러가 난다.
- ReferenceType의 경우 NullPointerException이 발생.
변수의 스코프와 라이프타임
- 스코프(Scope) : 범위.
- 변수의 스코프란 변수의 해당 변수를 사용할 수 있는 범위이다.
- 라이프타임(Lifetime) : 생존 기간
- 변수가 메모리에서 살아있는 기간을 뜻한다.
- 변수의 스코프는 자바에서는 일반적으로 블록 스코프를 사용한다 { } (블록 : {}, 중괄호)
변수 유형
- Instance Variables(인스턴스 변수)
- 클래스 내부와 메소드 본문 외부에 선언된 변수
- 스코프 : 정적 메서드(static method)를 제외한 클래스 전체
- 라이프타임 : 클래스를 인스턴스화 한 객체가 메모리에 남아있을 때 까지
- 생성 시기 : 인스턴스가 생성 되었을 때
- Local Variables(지역 변수)
- 인스턴스 및 클래스 변수가 아닌 변수. 메소드 내에 사용할 수 있다.
- 로컬 변수는 정적(static)으로 선언할 수 없다.
- 스코프 : 변수가 선언된 {}(블록) 내부
- 라이프타임 : 선언 된 블록을 떠날 때 까지
- 생성 시기 : 변수 선언문이 수행 되었을 때
- Class Variables (클래스 변수)
- 클래스 내부, 모든 블록 외부에서 선언되고 정적(static)으로 표시된 변수
- 스코프 : 클래스 전체
- 라이프타임 : 프로그램 종료시 까지
- 생성 시기 : 클래스가 메모리에 올라갈 때
- 어떠한 method나 block안에서 선언되지 않은 변수
- scope - static method를 제외한 클래스 전체
- lifetime - 클래스를 인스턴스화한 객체가 메모리에서 사라질 때 까지
public class SimpleCalculator {
private int x; // 인스턴스 변수
private int y; // 인스턴스 변수
private static final double PI = 3.14; // 클래스 변수
public int sum(int x, int y) { // x, y는 지역 변수
return x + y;
}
public void printSum(int x, int y) { // x, y는 지역 변수
int sum = x + y; // 지역 변수
System.out.println("print sum. result : " + sum);
}
...
}
타입 변환, 캐스팅 그리고 타입 프로모션
- 타입 변환 : 자료형을 다른 데이터 타입으로 변환하는것
- 타입 변환에는 2가지 종류가 있다. 타입 프로모션(Type promotion) 과 타입 캐스팅(Type casting)
- 타입 프로모션과 타입 캐스팅을 구분하기 위해서는
메모리 크기
가 아닌 데이터 표현 범위를 생각해야 한다. -
이렇게 원본 데이터가 담긴 데이터 타입의 표현 범위를 변환 할 데이터 타입의 표현 범위가 모두 수용하지 못할 경우 데이터 손실이 발생할 수 있는데, 이것을 타입 캐스팅 이라고 한다.
- 타입 프로모션과 타입 캐스팅을 구분하기 위해서는
- class 타입 객체들도 형변환이 가능한데, 타입캐스팅과 프로모션 캐스팅을 정리한 다음에 정리해놓았습니다.
타입 캐스팅(Type casting)
- 크기가 더 큰 자료형을 더 작은 자료형으로 변환하는것 ->
변환할 자료형 변수 = (변환할 자료형)변환할 변수;
자신의 표현 범위를 모두 포함하지 못한 데이터 티입으로의 변환
- 원본 데이터가 담긴 데이터 타입의 표현 범위를, 변환 할 데이터 타입의 표현 범위가 모두 수용하지 못할 경우 데이터 손실이 발생할 수 있다
- Primitive Type들은
boolean을 제외
하고는 타입 캐스팅이 모두 가능하며, 데이터 손실이 있을 수는 있지만 캐스팅이 실패하지는 않는다.
int intValue = 10;
byte byteValue = (byte)intValue;
System.out.println(byteValue); // -> 10
(byte 는 -256 ~ 255 까지 표현할 수 있고, 원본 데이터인 10은 표현 범위를 벗어나지 않으므로 타입캐스팅을 했을 때 데이터 변형이나
손실은 오지 않는다)
// ----------------------
int intValue = 10000;
byte byteValue = (byte)intVAlue;
System.out.println(byteValue); // -> 16
(byte의 표현범위를 벗어나는 값을 강제로 타입캐스팅해 수용하지 못하므로 10000에서 16으로 데이터에 변형이 생겼다)
타입 프로모션(Type promotion)
- 기존 타입에서 더 큰 타입으로 변경을 할 때 프로모션 변경이 발생.
자신의 표현 범위를 모두 포함한 데이터 타입으로의 변환
- 원본 데이터가 담긴 데이터 타입의 표현 범위를 모두 수용할 수 있다.
- 타입 프로모션의 경우 어떤 데이터 타입으로 변환해야하는지 명시하지 않아도 됩니다.
(변환할 자료형)
이 필요 없음- 자동으로 변환.
byte byteValue = 10;
int intValue = byteValue;
System.out.println(intValue); // -> 10
Class 타입 형변환
- 클래스 타입 변환은 상속 관계에 있는 클래스 사이에서 가능합니다.
- 자바에서는 객체지향의 특징인
다형성
을 통해서.
- 자바에서는 객체지향의 특징인
상속 관계가 아니면 클래스 타입에서는 타입 캐스팅이 불가능합니다.
- 업캐스팅과 다운 캐스팅이 있습니다.
public class Parent {
}
public class Child extends Parent {
}
업캐스팅 (Upcasting)
- 자식 타입 클래스의 객체가 부모 클래스 타입으로 형 변환 하는 것.
Child child = new Child();
Parent parent = child;
- 자식 타입은 부모 타입으로 자동 타입 변환이 가능하다.
Parent parent = child;
- 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있습니.
- 자식의 자식인 손자여도 (상속 계층에서의 상위타입) 자동 타입 변환이 가능합니다.
- 부모 클래스 타입으로 형 변환된 자식 객체는, 부모 클래스에 선언된 필드와 메서드만 접근, 사용 가능합니다
- 비록 변수는 자식 객체를 참조하지만, 변수로 접근 가능한 멤버는 부모 클래스 멤버로 한정
- 예외로, A라는 메서드가 자식 클래스에서
오버라이딩
되었다면 자식 클래스의 오버라이딩된 A메서드가 대신 호출됩니다.
다운캐스팅(Downcasting)
- 부모타입 클래스의 객체가 자식 클래스 타입으로 형 변환 하는 것
Parent parent = new Parent();
Child child = (Child)parent;
- 부모 타입은 자식 타입으로 자동으로 타입 변환이 불가능 하기에 명시적으로 자식 클래스 자료형을 명시해줘야합니다.
- 형 변환하게되면 자식 클래스에서 선언된 메서드와 필드를 사용할 수 있습니다.
- 왜 자식 -> 부모는 자동 형변환이 가능하고, 부모 -> 자식은 명시적 타입 캐스팅이 필요할까?
- 자식클래스는 부모클래스의 필드나 메소드를 물려받음으로 자식클래스타입의 객체를 부모클래스타입으로 바꾼다고 해서 데이터의 손실이나 변형이 일어나진 않기 때문이다.
1차 및 2차 배열 선언하기
- 배열 (Array) : 동일한 타입의 데이터를 연속된 공간에 저장하기 위한 레퍼런스 타입의 자료구조
- 동일한 데이터 타입을 하나의 배열로 관리할 수 있고, 인덱스는 1이아닌 0번부터 시작한다.
- 배열은 다음과 같이 선언할 수 있다.
- 자료형[] 변수명 = new 자료형[배열 크기]
int[] array = new int[10];
- 배열 변수는 JVM 런타임 스택 영역에 생성되고, 배열의 값들은 가비지 컬렉션 힙 영역에 객체가 생성된다.
- 이 힙 영역의 주소 값이 런타임 스택 영역에 생성된 배열 변수에 값으로 할당된다.
- 배열은 한번 생성하면 줄이거나 늘릴 수 없고, 자바에서는 같은 타입들만이 배열의 원소로 사용된다.
1차원배열
- 선언 : 자료형[] 변수명 = new 자료형[배열 크기]
int[] array = new int[10]; // 선언
int[] otherArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 선언과 할당
- 한줄로 이어져 있다고 생각하면 된다.
2차원 배열
- 선언 :
자료형[][] 변수명 = new 자료형[열][행]
int[][] array = new int[3][5]
- 정수를 5개씩 저장할 수 있는 3개의 배열
- 행렬 또는 큐브 형태라고 생각하면 된다.
타입 추론, var
- 타입 추론이란, 데이터타입(자료형)을 명시하지 않아도 컴파일러가 데이터 타입이 무엇인지 추론하는 것을 의미.
- 명시적이게 선언하지 않고 var로 선언하는것
- 자바10부터 지원
public static void main(String[] args) {
var str = "hi";
var intValue = "1";
}
- 타입 추론 (var)을 사용할 경우 제약 사항이 있다.
- 로컬 변수(local vairables) 이여야 한다.
- 선언과 동시에 값이 초기화 되어야 한다.
- null 값이 들어갈 수 없다.
- Lambda Expression에서는 명시적으로 타입을 지정해 줘야 한다
- 배열을 선언할 때 var 대신 타입을 명시 해줘야 한다.
- var는 키워드가 아니고 예약어가 아니다.
- 참조 및 출처
https://www.learningjournal.guru/article/programming-in-java/scope-and-lifetime-of-a-variable/
https://www.geeksforgeeks.org/types-references-java/
https://www.javatpoint.com/reference-data-types-in-java
'Java > whiteship-java-study' 카테고리의 다른 글
6주차 - 상속 (0) | 2022.08.28 |
---|---|
4주차 - 제어문 (0) | 2022.08.15 |
3주차 - 자바 연산자 (0) | 2022.07.31 |
1주차 - JVM은 무엇이며 어떻게 실행하는 것인가? (0) | 2022.07.30 |
Whiteship Java Study 목차 (0) | 2022.07.30 |