Unicorns
All the things
All the things
Primitive Type 은 자바의 기본 데이터 타입으로
문자형 1개 , 정수형 4개, 실수형 2개, 참/거짓 1개 총 8개다.
메모리에는 0과 1을 저장하는 최소 기억 단위인 비트(bit)가 있다. 그리고 8개의 비트를 묶어서 바이트(byte)라고 한다.
Primitive Type은 정해진 메모리 사용 크기(바이트 크기)로 값을 지정하는데
바이트 크기가 클수록 표현하는 값의 범위가 크다.
public class DataType {
public static void main(String[] args) {
char var1 = 'A';
char var2 = 'B';
char var3 = '가';
char var4 = '각';
// 유니코드를 알고 싶은 경우
int uniCode = var1;
System.out.println(uniCode); // 65
uniCode = var3;
System.out.println(uniCode); // 44032
}
}
값의 범위를 초과하면 컴파일 에러가 발생한다.
실행 중에 값의 범위를 초과할 경우
(127을 넘으면 -128부터 , -128 보다 작아지면 127 부터) 다시 시작
public class DataType {
public static void main(String[] args) {
byte b = -128;
System.out.println(b); // -128
b--;
System.out.println(b); // 127
b++;
System.out.println(b); // -128
}
}
public class DataType {
public static void main(String[] args) {
int num = 10;
}
}
float 와 double의 메모리 사용 크기는 각각 int 와 long의 크기와 같지만, 정수 타입과는 다른 저장 방식 때문에
정수 타입보다 훨씬 더 큰 범위의 값을 저장 할 수 있다.
실수는 부동 소수점 (floating-point) 방식으로 저장된다.
가수 m 의 범위 : 0 <= m < 1
float 타입과 double 타입은 가수와 지수를 저장하기 위해 전체 bit를 나누어 사용한다.
부동 소수점 방식의 오차
부동 소수점 방식은 10진수를 정확하게 표현할 수 없다.
public class DataType {
public static void main(String[] args) {
double num = 0.1;
for (int i=0; i<1000; i++) {
num += 0.1; // 0.1을 1000번 더함
}
System.out.println(num); // 100.09999999999859
}
}
0.1을 1000번 더하면 100이 나와야 하는데 100.09999999999859가 나왔다.
컴퓨터는 실수를 가지고 수행하는 모든 연산에서 언제나 작은 오차가 존재한다.
float형과 double형의 정밀도 차이
public class DataType {
public static void main(String[] args) {
float num1 = 1.23456789f;
double num2 = 1.23456789;
System.out.println("float형 변수 num1 = " + num1);
System.out.println("double형 변수 num2 = " + num2);
}
}
float형 타입 : 소수 6자리까지 정확하게 표현할 수 있다.
double형 타입 : 소수 부분 15자리 까지 정확하게 표현할 수 있다.
그 이상 넘어가면 두 타입 모두 작은 오차가 발생한다.
public static void main(String[] args) {
int num = 5;
String str = "hello";
}
변수는 스택 영역에 객체는 힙영역에 저장되는데
int 타입인 변수 num 에는 실제 값이 5가 저장되고
문자열 클래스 String 참조 타입인 변수 str에는
값이 저장되는 것이 아니라 힙에 생성된 hello 라는 문자열의 메모리 주소를 저장한다.
즉, str은 hello 문자열의 메모리 주소를 참조하는 것이다.
그렇기 때문에 변수 str을 참조 변수라고 부른다.
리터럴(literal) 은 소스 코드 내에서 직접 입력된 값을 말한다.
public static void main(String[] args){
int num= 5;
String str= "hello";
boolean check= true;
}
5 , "hello" , true 가 리터럴이다.
여기서 각 타입에 따라
정수 리터럴 , 문자열 리터럴 , 실수 리터럴 , 논리 리터럴, 문자 리터럴이라고 부르는 것이다.
작은 따옴표(')로 묶은 텍스트는 하나의 문자 리터럴로 간주한다.
큰따옴표(")로 묶은 텍스트는 문자열 리터럴로 간주한다.
true 와 false는 논리 리터럴로 간주한다.
변수란 ?
하나의 값을 저장할 수 있는 메모리 공간을 말한다.
변수의 선언
값을 저장할 변수를 선언 해보자
int age;
나이의 값을 저장해주는 age 라는 변수를 선언 하였는데
나이는 숫자로 나타내기 때문에 정수형 int 타입을 사용하였다.
이제 메모리에 age라는 저장 공간이 생겼고 이제 값을 넣어주면 된다.
int age;
age = 28;
대입 연산자를 사용해서 age 변수에 28이라는 값을 저장하였다.
위와 같이 변수에 처음으로 값을 저장하는 것을 초기화라고 한다.
변수눈 선언된 블록 내에서 사용 가능하며 선언 위치에 따라 세 가지 타입으로 나눌 수 있다.
변수 타입 | 스코프(scope) | 라이프타임(lifetime) |
---|---|---|
인스턴스 변수 | static 메서드를 제외한 클래스 전체 | 객체 인스턴스가 메모리에 있을 때 |
클래스 변수 | 클래스 전체 | 프로그램이 종료 될 때 |
로컬 변수 | 선언된 블록({ }) 내부 | 블록이 끝나는 지점 |
타입 변환은 말 그대로 타입을 다른 타입으로 변환하는 것을 말한다.
타입 변환에는 자동 타입 변환과 강제 타입 변환이 있다.
ex)
int x = 20;
long y = x; // 자동 타입 변환
ex)
int i = 2;
byte b = (byte) i;
※ 타입 변환 시 float는 4byte 크기 인데 long (8byte) 보다 더 큰 타입으로 표시되는 이유는 표현할 수 있는 값의 범위가 float가 더 크기 때문이다.
int i = 5;
long l = 10;
long result = l + i;
배열 : 같은 타입의 데이터를 연속 된 공간에 나열시키고, 각 데이터에 인덱스(index)를 부여해 놓은 자료구조
배열을 사용하기 위해 배열을 선언해보자
배열 변수를 선언할 때 대괄호 []를 사용하는데
타입 [] 변수;
타입 변수 [];
대괄호 []는 타입 뒤에 붙을 수도 있고 변수 뒤에 붙을 수 도 있다.
배열을 생성 할 때 중괄호{} 안에 선언된 값으로 초기화 할 수 있다.
초기화된 값이 들어있는 배열 객체의 주소를 변수가 참조한다.
데이터 타입[] 변수 = {값1, 값2, 값3, 값4};
ex)
int arr[] = {10,13,23,35};
위의 배열은 데이터 타입이 primitive type(기본 타입)으로 배열 인덱스에 값을 직접 저장한다.
반면에 배열 데이터 타입이 String과 같은 참조 타입이면 배열 인덱스에 객체의 주소를 저장한다.
String fruits[] = {"orange" ,"apple", "banana" ,"mango"};
생성값을 초기화 하지 않고 값들을 저장할 배열을 미리 만들고 싶을 때 사용한다.
배열 객체 안에 있는 값들은 지정된 데이터 타입의 초기값이 설정 되어있다.
데이터 타입[] 변수 = new 타입[길이];
위의 코드 처럼 배열의 길이를 지정할 수 있다.
ex)
int arr[] = new int[4];
값을 지정하지 않았기 때문에 int 데이터 타입의 기본값인 0으로 초기화
이후 각 인덱스별로 값을 초기화 할 수 있다.
arr[0] = 21; // 값 21 초기화
arr[1] = 15; // 값 1 초기화
arr[2] = 20; // 값 20 초기화
arr[3] = 19; // 값 19 초기화
arr[4] = 45; // ArrayIndexOutOfBoundsException 발생
이때 인덱스 범위를 벗어나면 런타임 에러가 발생한다.
String fruits = new String[4];
값을 지정하기 않았기 때문에 String 데이터 타입의 기본값인 null로 초기화
행과 열로 구성된 배열을 2차원 배열이라고 한다.
타입[][] 변수;
타입 변수[][];
int [][] arr = new int[2][3]; // 2행 3열
행의 크기가 2 , 열의 크기가 3인 2차원 배열이다.
0번 인덱스와 1번 인덱스에 각 각 크기가 3인 배열의 참조 주소가 저장되어있다.
값은 int 형의 기본 값인 0이다.
그런데 자바에서는 수학 행렬 구조가 아닌 계단식 구조를 가질 수 있다.
즉, 열의 크기가 제각기 다른 2차원 배열을 만들수 있다.
int [][] arr = new int[2][];
행의 크기만 정해 놓고 열의 크기는 각 행에 따로 지정할 수 있다.
arr[0] = new int[3];
arr[1] = new int[4];
배열 초기화 하기
arr[0][0] = 1;
arr[0][1] = 5;
arr[0][2] = 10;
arr[1][0] = 2;
arr[1][1] = 25;
arr[1][2] = 30;
arr[1][3] = 35;
값 목록으로 배열 생성
public class JaggedArray {
public static void main(String[] args) {
int arr[][] = {{1,5,10} , {2,25,30,35}}; // 크기가 각각 3, 4 인 배열을 참조
// 1 5 10
// 2 25 30 35
System.out.println(arr[0][0]); // 1
System.out.println(arr[0][1]); // 5
System.out.println(arr[0][2]); // 10
System.out.println(arr[1][0]); // 2
System.out.println(arr[1][1]); // 25
System.out.println(arr[1][2]); // 30
System.out.println(arr[1][3]); // 35
System.out.println(arr[1][4]); // ArrayIndexOutOfBoundsException 에러 발생
}
}
배열을 다른 배열에 복사해서 사용 할 수 있는데, 깊은 복사(deep copy)와 얕은 복사(shallow copy)가 있다.
배열은 객체라고 하였다. 그렇게 때문에 값이 저장되는 것이 아니라 참조 주소가 저장되는데,
깊은 복사는 참조하는 객체를 새로 생성해서 값만 복사하는 것 을 말한다.
public class DeepCopy {
public static void main(String[] args) {
int arr[] = {3, 5, 10};
int newArr[] = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
System.out.println(newArr == arr); // false
}
}
clone() 메서드를 사용해서 깊은 복사를 할 수도 있다.
public class DeepCopy {
public static void main(String[] args) {
int arr[] = {3, 5, 10};
int newArr[] = arr.clone();
System.out.println(arr == newArr); // false
}
}
참조하는 주소값이 다르기 때문에
배열의 인덱스를 변경하여도 원본 배열에는 지장이 없다.
public class DeepCopy {
public static void main(String[] args) {
int arr[] = {3, 5, 10};
int newArr[] = arr.clone();
newArr[0] = 5;
System.out.println(arr == newArr); // false
System.out.println(Arrays.toString(arr)); // [3,5,10];
System.out.println(Arrays.toString(newArr)); // [5,5,10];
}
}
참조하는 주소값을 복사한다.
그렇기 때문에 참조하는 주소가 같다.
public class ShallowCopy {
public static void main(String[] args) {
int arr[] = {3, 5, 10};
int newArr[] = arr; // 얕은 복사
System.out.println(arr == newArr); // true
newArr[0] = 5;
System.out.println(Arrays.toString(arr));
}
}
얕은 복사는 배열을 복사 한 뒤 값을 수정 할 때 주의해야 한다.
public class ShallowCopy {
public static void main(String[] args) {
int arr[] = {3, 5, 10};
int newArr[] = arr; // 얕은 복사
System.out.println(arr == newArr); // true
newArr[0] = 5;
System.out.println(Arrays.toString(arr)); // [5,5,10]
System.out.println(Arrays.toString(newArr)); // [5,5,10]
}
}
같은 객체를 참조하기 때문에
복사한 배열의 값을 수정하면 원본 배열의 값도 함께 수정 된다.
이 점을 주의해서 사용해야 한다.
같은 객체를 참조하기 때문에 두 배열 모두 0번 인덱스 값이 5로 수정되었다.
java 10 이후 부터 java 에서 지원되는 것으로
컴파일러가 데이터 타입을 자동으로 결정해주는 것을 말한다.
public static void main(String[] args) {
var message ="Good bye , java 9";
}
REFERENCE
https://techvidvan.com/tutorials/data-types-in-java/
https://www.atnyla.com/tutorial/variable---in-java/0/31
https://www.learningjournal.guru/article/programming-in-java/scope-and-lifetime-of-a-variable/
http://tcpschool.com/java/java_datatype_floatingPointNumber
https://www.javatpoint.com/array-in-java
자바의 정석
이것이 자바다
[Java Study] - Garbage Collection(GC) in JVM (0) | 2021.09.26 |
---|---|
[Java Study] - LinkedList , Queue in Collection framework (0) | 2021.09.26 |
[Java Study] - 연산자 , 연산자의 종류 (0) | 2021.09.23 |
[Java Study] - JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가. (2) | 2021.09.16 |
[Java] 문자열 앞뒤 공백 잘라내기- trim() (0) | 2021.05.14 |