Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags
more
Archives
Today
Total
관리 메뉴

공부를 하자

Week-02-Variables 본문

개발/자바

Week-02-Variables

Jade✨ 2021. 4. 17. 01:20

2주차 과제: 자바 데이터 타입, 변수 그리고 배열

목표

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

학습할 것

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

데이터 타입(Data type)

데이터가 메모리에 어떻게 저장되고 프로그램에서 어떻게 처리되어야 하는지를 명시적으로 알려주는 것이다.

데이터 타입은 크게 프리미티브(기본형) 타입과 레퍼런스 타입으로 나뉜다.

이미지 출처:  https://blog.naver.com/highkrs/220242895539

 

1. 기본형 타입(프리미티브 타입(Primitive type))

  • 기본 값이 있기 때문에 Null이 존재하지 않지만, 기본형 타입에 Null을 넣고 싶다면 래퍼 클래스를 활용할 수 있다.
  • 스택 메모리에 실제 값이 직접 저장된다.
  • 컴파일 시점에 데이터 크기가 할당 메모리 범위를 넘어서면 에러가 발생한다.
  • 프리미티브 타입 중 boolean을 제외한 나머지 타입은 서로 연산과 변환이 가능하다.
  • 정수 데이터 타입 중 int는 CPU가 가장 효율적으로 처리할 수 있는 타입으로 일반적으로 많이 사용된다.

프리미티브 타입 분류

  1. 논리형: true와 false 중 하나를 값으로 가지며, 조건식과 논리적 계산에 상용된다.
  2. 문자형: 문자를 저장하는 데 사용되며, 변수에 하나의 문자만 저장할 수 있다.
  3. 정수형: 정수를 저장하는 데 사용되며, 주로 int가 사용된다. byte는 이진 데이터를 다룰 때 사용되며, short는 C언어와의 호환을 위해서 추가되었다.
  4. 실수형: 실수를 저장하는 데 사용되며, 주로 double이 사용된다.
타입 종류 할당 메모리 범위 기본값 Wrapper class
boolean 논리형 8 bit / 1 byte true, false false Byte
byte 정수형 8 bit / 1 byte -128 ~ 127 0 Short
short 정수형 16 bit / 2 byte -32,768 ~ 32,767 0 Integer
int
(기본형)
정수형 32 bit / 4 byte -2,147,483,648
~ 2,147,483,647
0 Long
long 정수형 64 bit / 8 byte -2^63 ~ 2^63 - 1 0L Float
float 실수형 32 bit / 4 byte (3.4 X 10^-38)
~ (3.4 X 10^38) 의 근사값
0.0F Double
double
(기본형)
실수형 64 bit / 8 byte (1.7 X 10^-308)
~ (1.7 X 10^308) 의 근사값
0.0 Boolean
char 문자형 16 bit / 2 byte
(UniCode)
0 ~ 65,535 '\u0000' Char

부동 소수점 실수 변수(float, double)는 정확한 계산을 해야할 때(예)금액)에는 사용하지 않는 것이 좋다. 왜냐하면 정확한 값을 보장받을 수 없기 때문이다. 정확한 계산이 필요할 때엔 JAVA API인 BigDecimal을 사용하자.

해당 내용 참고: https://reference-m1.tistory.com/105

 


2. 레퍼런스 타입(Reference type)

Reference 타입

  • 8개의 기본형 변수를 사용하여 사용자가 직접 만들어 사용하는 데이터 타입을 의미
  • 값이 저장된 공간을 참조하는 주소값(memory address)힙(Heap)에 저장한다.
  • 빈 객체를 의미하는 Null이 존재, 그러나 해당 데이터를 Null 값으로 받으면 NullPointException이 발생하므로 변수값을 넣어야 함.
타입 할당 메모리
(객체의 주소값)
기본값 선언 예시
배열(Array) 4 byte Null int[] arr = new int[7];
열거(Enumeration) 4 byte Null  
클래스(Class) 4 byte Null Member member = new Member();
인터페이스(Interface) 4 byte Null  

3. 리터럴

리터럴(literal)

변수에 넣은 데이터 그 자체를 의미하며 변하지 않는다. (메모리 안에 위치한 값)

 

상수(Constant): 변하지 않는 변수(한 번 값을 입력하면 다시는 바꿀 수 없다), final 지시자 사용

예) `final int DAY_OF_WEEK = 7`

이미지 출처: https://dololak.tistory.com/676

  • 프리미티브 타입 변수에 저장되는 데이터를 리터럴이라고 칭한다.
  • 클래스 데이터인 인스턴스는 리터럴이 될 수 없으나(인스턴스는 값을 동적으로 사용하기 위해 작성되기 때문), 데이터가 변하지 않도록 설계가 가능하다. 이를 불변 클래스(immutable class)라고 칭한다.
    예) 자바의 String 같은 클래스
  • 종류: 정수형, 실수형, 문자형, 논리형, 문자열 리터럴이 존재한다,

이미지 출처:  https://mine-it-record.tistory.com/100

1) 정수 리터럴

  • 정수 리터럴은 int 형으로 컴파일
  • long(혹은 Long) 타입 리터럴은 숫자 뒤에 'l' 또는 'L'을 붙여서 표시
  • byteshort 타입의 리터럴은 별도로 존재하지 않으며, byteshort 타입의 변수에 값을 저장할 때는 int 타입의 리터럴을 사용한다.
int a = 15;        // 10진수 리터럴 15
int b = 015;    // 8진수(0으로 시작), 10진수 값으로 13
int c = 0x15;    // 16진수(0x로 시작), 10진수 값으로 21
int d = 0b0101;    // 2진수(0b로 시작), 10진수 값으로 5

long l = 10000L;

2) 실수 리터럴

  • 소수점 형태나 지수 형태로 표현한 값, double 타입으로 컴파일
  • 숫자 뒤에 'f'(float)나 'd'(double)을 명시적으로 붙이기도 하며, f(혹은 F)를 붙이면 float 타입, d(혹은 D)를 붙이면 double 타입으로 강제적으로 된다. (float은 f를 꼭 붙여줘야 하고, double은 생략이 가능함)
  • 리터럴에 소수점이나 10의 제곱을 나타내는 기호 'E' 혹은 'e'가 포함되어 있으면 실수형 리터럴로 간주한다.
double f = 0.1234;
double g = 1234E-4; // 1234*10*(-4) 이므로 0.1234와 동일

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

3) 문자 리터럴

  • 단일 인용부호('')로 문자를 표현하거나, '\u' 다음에 유니코드 값을 입력해 표현할 수 있다.
  • 문자 리터럴에는 영문자 이외에 tab이나 backspace 등의 특수문자를 저장하기 위해 조금 다른 방법을 사용해야 한다.
char a = 'H';
char b = "한";
char c = '\uac00';    // '가'라는 문자 표현, 유니코드 값(\u다음에 4자리 16진수로, 2바이트의 유니코드)
특수문자
리터럴
의미 특수문자
리터럴
의미
'\b' 백스페이스(backspace) '\r' 캐리지 리턴(carriage return)
'\t' 탭(tab) '\ "' 큰 따옴표(double quote)
'\n' 라인피드(line feed) '\ '' 작은 따옴표(single quote)
'\f' 폼피드(form feed) '\\' 역슬래시(backslash)

4) 논리 타입 리터럴과 그 외 리터럴

  • boolean 타입 변수에 치환하거나 조건문을 이용
  • 자바에서는 1,0을 true, false로 사용할 수 없다. boolean b = 1이라는 코드를 입력했을 때 오류 발생
boolean b1 = true;
boolean b2 = 5 < 3;    // 결과는 false이므로 b2에 false라는 값이 저장됨
  • null 리터럴은 레퍼런스에 대입해서 사용
  • 프리미티브 타입에는 사용이 불가하고 String 같은 경우에는 사용이 가능하다.
int a = null; // 에러
String str = null;
str="JAVA";

5) 문자열 리터럴

  • 큰 따옴표( "" )로 문자열을 묶어서 표현, 참고로 문자열은 기본 데이터 타입에 포함되지 않는다.
    • 문자열: 기본 데이터 타입에는 속하지 않으며, String 클래스를 이용해 선언할 수 있다. 문자열과 문자열 간의 연결은 '+'연산을 이용해 연결한다.
String str = "Hello!";

 


4. 변수 선언 및 초기화

변수(variable)

데이터를 저장하기 위해 프로그램에 의해 이름을 할당받은 메모리 공간을 의미한다.
즉, 변수란 데이터를 저장할 수 있는 메모리 공간을 의미하며, 이렇게 저장된 값은 변경될 수 있다.

변수의 이름 생성 규칙

  1. 변수의 이름은 영문자(대소문자), 숫자, 언더스코어(_), 달러($)로만 구성할 수 있음
  2. 변수의 이름은 숫자로 시작할 수 없음
  3. 변수의 이름 사이에는 공백을 포함할 수 없음
  4. 변수의 이름으로 자바에서 미리 정의된 키워드(keyword)는 사용 불가

변수의 이름은 메모리 공간에 이름을 붙여주는 것이기 때문에 해당 변수에 저장될 데이터의 의미를 잘 나타내도록 짓는 것이 좋다.

변수의 선언

변수를 사용하기 전에 반드시 먼저 변수를 선언하고 초기화 해야 하며, 변수를 선언하는 방법에는 두 가지가 있다.

변수의 초기화

변수에 값을 저장할 때는 대입연산자 =을 사용한다. 대입연산자는 오른쪽의 값을 왼쪽(변수)에 저장하는 연산자다.

변수의 종류에 따라 변수의 초기화를 생략할 수 있지만, 사용하기 전에 적절한 값으로 초기화를 하는 것이 좋다. 지역변수는 사용하기 전에 초기화가 반드시 필요하지만, 클래스변수와 인스턴스변수는 초기화를 생략할 수 있다.

변수 선언만 하는 방법

먼저 변수를 선언하여 메모리 공간을 할당받고, 나중에 변수를 초기화 하는 방법이다.
이렇게 선언만 된 변수는 초기화되지 않았으므로 해당 메모리 공간에는 알 수 없는 쓰레깃값만이 들어가 있다. 따라서, 선언만 된 변수는 반드시 초기화 한 후에 사용해야 한다.

자바에서는 프로그램의 안전성을 위해 초기화하지 않은 변수는 사용할 수 없다. 만약 초기화되지 않은 변수를 사용하려고 하면, 자바 컴파일러는 오류를 발생시킨다.

/* 
변수 선언만 하는 방법: 타입 변수이름; 
*/
int num;                // 변수 선언
System.out.println(num); // 오류 발생
num = 20;
System.out.println(num); // 20

변수 선언과 동시에 초기화 하는 방법

변수의 선언과 동시에 그 값을 초기화 할 수 있다. 선언하고자 하는 변수들의 타입이 같다면 이를 동시에 선언 할 수 있고, 선언과 동시에 초기화도 가능하다.

/*
변수의 선언과 동시에 초기화 하는 방법
1) 타입 변수이름[, 변수이름];
2) 타입 변수이름 = 초기 설정 값[, 변수이름 = 초기 설정 값]
*/
int num1, num2;                    // 같은 타입의 변수를 동시에 선언
double num3 = 3.14;                // 선언과 동시에 초기화
double num4 = 1.23, num5 = 4.56;   // 같은 타입의 변수들을 동시에 선언하면서 초기화

선언하고자 하는 변수의 타입이 서로 다르면 동시에 선언할 수 없다.

또한 다음 예제처럼 이미 선언된 여러 변수를 동시에 초기화 할 수 없다.

double num1, num2;            // 같은 타입의 변수를 동시에 선언
...
num1 = 1.23, num2 = 4.56;    // 하지만 이미 선언된 여러 변수를 동시에 초기화 할 수없음

멤버변수의 초기화

멤버변수(클래스 변수와 인스턴스 변수)는 지역 변수와 달리 여러가지의 초기화 방법이 존재한다.

 

1) 명시적 초기화

명시적 초기화는 변수를 선언과 동시에 초기화하는 것이다. 가장 기본적이고 간단한 초기화 방법으로 우선적으로 고려된다.

class InitTest {
   int number = 1;        // 프리미티브 타입 변수의 명시적 초기화
   Car car = new Car();    // 참조형 변수의 명시적 초기화
}

2) 생성자

생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드다. 인스턴스 변수의 초기화 작업에 주로 사용되며. 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다. 생성자는 메서드처럼 클래스 내에 선언되며, 리턴 값이 없다.

class InitTest {
    int number;
    String name;

    InitTest() {    // 생성자
        number = 10;
        name = "Yun";
    }
}

3) 초기화 블럭

초기화 블럭에는 클래스 초기화 블럭과 인스턴스 초기화 블럭 두 가지 종류가 있다.

인스턴스 초기화 블럭은 인스턴스 변수의 초기화에 사용 되며, 클래스 내에 {} 블럭을 만들고 그 안에 코드를 작성하면 된다.

클래스 초기화 블럭은 클래스 변수의 초기화에 사용 되며, 인스턴스 초기화 블럭과 같이 작성하되 블럭 앞에 static 키워드를 붙여주면 된다.

class InitTest {
    static {  // 클래스 변수 초기화 블럭
        int number = 10;
        String name = "Yun";
    }

    {  // 인스턴스 변수 초기화 블럭
        int year = 2021;
        String month = "April";
    }

}

클래스 변수와 인스턴스 변수의 초기화 순서는 다음과 같다.

분류 초기화 순서
클래스 변수 기본값 -> 명시적 초기화 -> 클래스 초기화 블럭
인스턴스 변수 기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자

참고로, 클래스 변수는 항상 인스턴스 변수보다 먼저 생성 및 초기화 된다.


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

스코프(Scope)

변수에 대한 접근과 변수가 존재할 수 있는 영역, 사용 가능한 범위를 의미한다. {} 블럭 안에서 변수를 선언했을 경우 영역이 끝나기 전까지는 어디서든 사용이 가능하다.

public class ValableScopeExam {    // Class 영역
    int globalScope = 10;        // Class 영역에서 선언한 변수(Global Variable)

    public void scopeTest(int value){    // 메서드 영역
        int localScope = 10;                // 메서드 영역 안에서 선언한 변수(Local Variable)
        System.out.println(globalScope);    // 사용 가능
        System.out.println(localScope);        // 사용 가능
        System.out.println(value);        // 사용 가능
    }

    public static void main(String[] args){
        // 메인 메서드에서는 static 변수가 아닐 경우 객체화해야 클래스 변수를 사용할 수 있음
        System.out.println(globalScope);    // 사용 불가
        System.out.println(localScope);        // 사용 불가
        System.out.println(value);        // 사용 불가
    }
}
  • globalScope는 클래스 영역에서 선언한 변수이므로 사용범위는 클래스 전체다.
  • value는 블럭 밖에 존재하지만, 메서드 선언부에 존재하므로 사용범위는 scopeTest 메서드 내부다.
  • localScope는 메서드 영역 내에서 선언한 변수이므로 사용범위는 scopeTest 메서드 내부다.

하지만 위의 예시처럼 메인 메서드(혹은 static 메서드) 에서는 globalScope와 같은 인스턴스 변수를 사용할 수 없다. static 변수만 static 메서드에서 사용할 수 있다.

static

static한 변수(변수 앞에 static 키워드를 붙힘)나, 메서드는 클래스를 인스턴스화 하지 않아도 사용할 수 있다. 그래서 static 변수는 클래스 변수라고도 부른다.

public class VariableScopeExam {
    int globalScope = 10; 
    static int staticVal = 7;

    public void scopeTest(int value){
        int localScope = 20;        
    }

    public static void main(String[] args) {
        System.out.println(globalScope);    // 사용 불가
        System.out.println(staticVal);      // 사용 가능

        VariableScopeExam v1 = new VariableScopeExam();
        System.out.println(v1.globalScope); // 사용 가능
    }

}

static 변수는 값을 저장할 수 있는 공간이 하나만 생성되므로, 인스턴스가 여러개 생성되어도 static 변수는 하나로 공유된다.

public class VariableScopeExam {
    int globalScope = 10; 
    static int staticVal = 7;

    public static void main(String[] args) {
        ValableScopeExam v1 = new ValableScopeExam();
        ValableScopeExam v2 = new ValableScopeExam();
        v1.globalScope = 20;
        v2.globalScope = 30; 

        System.out.println(v1.globalScope);  // 20 출력 
        System.out.println(v2.globalScope);  // 30 출력 

        v1.staticVal = 10;
        v2.staticVal = 20; 

        System.out.println(v1.staticVal);  // 20 출력
        System.out.println(v2.staticVal);  // 20 출력
    }
}
  • globalScope 같은 변수는 인스턴스가 생성될 때 생성되기 때문에 인스턴스 변수라고 한다.
  • staticVal 같이 static한 변수는 클래스 변수라고 한다.
  • 클래스 변수는 레퍼런스.변수명 으로 사용하기 보다는 클래스.변수명으로 사용하는 것이 바람직하다.
    예) VariableScopeExam.staticVal

라이프타임(Lifetime)

변수가 메모리에 생존하는 기간, 즉 생성된 후 부터 폐기될 때 까지의 기간을 의미한다.

변수 별 스코프와 라이프타임은 다음과 같다.

변수 종류 스코프(Scope) 라이프타임(Lifetime)
클래스 변수 클래스 전 영역 프로그램이 종료될 때까지
인스턴스 변수 static 메서드를 제외한 클래스 전 영역 클래스의 객체(인스턴스)가 메모리에 남아있을 때까지
로컬 변수
(지역 변수)
변수가 선언된 블럭 내부
(예: 메서드, 생성자, 초기화 블럭 등)
프로그램의 실행(컨트롤)이 지역 변수가 선언된 블록을 떠날 때까지

 


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

타입 변환(Type conversion)

타입 변환(Type conversion) 혹은 형변환(casting)은 어떤 데이터의 타입을 다른 타입으로 바꾸는 것이다.

자바에서 연산은 동일한 데이터 타입에서 가능하다. 하지만, 서로 다른 데이터 타입끼리의 연산이 필요할 때가 발생하는데, 이 때 변수의 데이터 타입을 바꿔주는 작업이 필요하게 된다.

 

자바에서는 boolean형을 제외한 나머지 기본 타입 간의 타입 변환을 자유롭게 수행할 수 있다.

메모리에 할당받은 바이트의 크기가 상대적으로 작은 타입에서 큰 타입으로의 타입 변환은 생략할 수 있다. 하지만, 메모리에 할당받은 바이트의 크기가 큰 타입에서 작은 타입으로의 타입 변환은 데이터의 손실이 발생한다. 따라서, 상대적으로 바이트의 크기가 작은 타입으로 타입 변환을 할 경우 컴파일 오류가 발생한다.

 

데이터 타입 변환의 종류는 자동 타입 변환(묵시적 타입 변환, Type Promotion), 강제 타입 변환(명시적 타입 변환, Type Casting)이 있다.

자동 타입 변환(Type Promotion)

대입 연산이나 산술 연산에서 컴파일러가 자동으로 수행해주는 타입 변환을 말한다.

자바에서는 데이터의 손실이 발생하지 않거나, 데이터의 손실이 최소화되는 방향으로 자동 타입 변환을 진행한다. 또한, 자바에서는 데이터의 손실이 발생하는 대입 연산은 허용하지 않는다.

double num1 = 10;    // int형 데이터인 10이 double형으로 자동 타입 변환
int num2 = 3.14;    // 데이터의 손실이 발생(데이터 표현 범위: double > int)하여 컴파일 오류 발생
double num3 = 7.0f + 3.14;    // float형 데이터가 double형으로 자동 타입 변환되며 산술 진행

System.out.println(num1);    // 10.0 출력
System.out.println(num3);    // 10.14 출력

다음과 같이 자바 컴파일러가 자동으로 수행하는 타입 변환은 언제나 데이터의 손실이 최소화 되는 방향으로 이루어지며, 다음과 같은 방향으로 자동 타입 변환이 이루어진다.

byte(1 byte) -> short (2 byte) -> int (4 byte) -> long (8 byte) -> float (4 byte) -> double (8 byte)
                 char (2 byte) ↗
byte num1 = 100;        // 자동 타입 변환(byte형 변수가 표현할 수 있는 범위내에 있음)
byte num2 = 200;        // 오류 발생(byte형 변수가 표현할 수 있는 범위를 벗어남)

int num3 = 9876543210;  // 오류 발생(int형 변수가 표현할 수 있는 최대 범위(2,147,483,647) 초과)
long num4 = 9876543210; // 오류 발생(int형 변수가 표현할 수 있는 최대 범위(2,147,483,647) 초과)

float num5 = 3.14;      // 오류 발생(float형 변수가 표현할 수 있는 범위를 벗어남)

int num3 = 9876543210L;  // 오류 발생(int형 변수가 표현할 수 있는 범위를 벗어남)
long num4 = 9876543210L; // 자동 타입 변환(리터럴의 마지막에 L이나 l 접미사를 추가하여 long형 리터럴로 명시)

강제 타입 변환(Type Casting)

사용자가 타입 캐스트 연산자()를 사용하여 강제적으로 수행하는 타입 변환으로 자바에서는 다음과 같이 명시적 타입 변환을 수행할 수 있다.

(변환할 타입) 변환할데이터

변환시키고자 하는 데이터의 앞에 괄호를 넣고 그 괄호 안에 변환할 타입을 작성하면 된다. 자바에서는 이 때 사용하는 괄호를 타입 캐스트(Type cast) 연산자라고 한다.

int num1 = 1, num2 = 4;

// 나눗셈의 결과로 0 출력(int형으로 자동타입 변환), 그리고 자동 형변환 실행(0.0)
double result1 = num1 / num2; 

// num1을 double형으로 강제 타입 변환, 따라서 연산 수행을 위해 num2도 double형으로 자동 형변환 실행
double result2 = (double) num1 / num2;

System.out.println(result1);    // 0.0 출력
System.out.println(result2);    // 0.25 출력

 


7. 1차 및 2차 배열 선언

배열(array)

같은 타입의 변수들을 하나의 묶음(유한 집합)으로 다루는 것을 배열이라고 한다.

  • 배열 요소(element): 배열을 구성하는 각각의 값
  • 인덱스(index): 배열에서의 위치를 가리키는 숫자, 자바에서 인덱스는 언제나 0부터 시작하며, 0을 포함한 양의 정수만을 가질 수 있다.

같은 타입의 데이터를 많이 다뤄야 하는 경우에 사용할 수 있는 가장 기본적인 자료구조로, 배열은 선언되는 형식에 따라 1차원 배열, 2차원 배열 그리고 그 이상의 다차원 배열로 선언할 수 있다.

1차원 배열

타입은 배열 요소로 저장되는 변수의 타입을 명시한다. 배열 이름은 배열이 선언된 후에 배열에 접근하기 위해 사용된다.

자바에서는 배열 선언 방법으로 두 가지 방법을 모두 사용할 수 있지만, 첫 번째 방법 타입[] 배열이름만을 사용하는 것이 좋다.

자바에서는 배열도 모두 객체이므로, 각각의 배열은 모두 자신만의 필드와 메소드를 가지고 있다.

선언 및 생성 방법

***선언 방법***
1) 타입[] 배열이름;
2) 타입 배열이름[];

***생성 방법***
배열이름 = new 타입[배열길이];

***선언과 생성을 동시에 하는 방법***
타입[] 배열이름 = new 타입[배열길이];
int[] grade1;
int grade2[];

grade1 = new int[5];

int[] grade3 = new int[7];

다음과 같이 인덱스를 이용하면 각각의 배열요소에 따로 접근할 수 있다.
또한, grade2 배열 처럼 배열의 길이보다 적은 수의 배열 요소만을 초기화할 경우, 나머지 배열 요소들은 배열의 타입에 맞게 자동으로 초기화 된다.

int[] grade1 = new int[3]; // 길이가 3인 int형 배열의 선언 및 생성
int[] grade2 = new int[3]; // 길이가 3인 int형 배열의 선언 및 생성 

grade1[0] = 85; // 인덱스를 이용한 배열의 초기화
grade1[1] = 65;
grade1[2] = 90; 

grade2[0] = 85; // 배열의 길이보다 적은 수의 배열 요소만 초기화 

for (int i = 0; i < grade1.length; i++) {
    System.out.print(grade1[i] + " "); // 인덱스를 이용한 배열로의 접근, 85 65 90 출력
}

for (int i = 0; i < grade2.length; i++) {
    System.out.print(grade2[i] + " "); // 인덱스를 이용한 배열로의 접근, 85 0 0 출력 
}

하지만 다음과 같이 해당 배열의 길이를 초과하는 인덱스를 사용하면, ArrayIndexOutOfBounds 예외가 발생한다.

int[] grade = new int[3];   // 길이가 3인 int형 배열의 선언 및 생성
grade[0] = 85;              // 인덱스를 이용한 배열의 초기화
grade[1] = 65;
grade[2] = 90;

System.out.print(grade[4]); // ArrayIndexOutOfBounds 예외 발생

배열의 초기화

배열도 선언과 동시에 초기화가 가능하며, 다음과 같이 {} 괄호(초기화 블록, initialization block)를 사용하여 초깃값을 나열할 수 있다.

***선언 및 초기화 방법***
1. 타입[] 배열이름 = {배열요소1, 배열요소2, ...};
2. 타입[] 배열이름 = new 타입[]{배열요소1, 배열요소2, ...};

두 가지 방법 모두 초기화 블록에 맞춰 자동으로 배열의 길이가 설정된다. 그러나 다음과 같은 경우에는 위의 2번째 방법만을 사용하여 초기화 해야 한다.

  1. 배열의 선언과 초기화를 따로 진행해야 할 경우
  2. 메소드의 인수로 배열을 전달하면서 초기화해야 할 경우
int[] grade1 = {70, 80, 90};        // 선언과 동시에 초기화 방법1
int[] grade2 = new int[]{70, 90, 80};// 선언과 동시에 초기화 방법2

int[] grade3;
grade3 = {70, 90, 80};            // 이미 선언된 배열을 해당 방법으로 초기화하면 오류가 발생

int[] grade4;
grade4 = new int[]{70, 90, 80};    // 이미 선언된 배열은 이 방법으로만 초기화 할 수 있음

2차원 배열(Two dimensional array)

2차원 배열이란 배열의 요소로 1차원 배열을 가지는 배열이다. 자바에서는 2차원 배열을 나타내는 타입을 따로 제공하지 않는다. 대신, 1차원 배열의 배열 요소로 또 다른 1차원 배열을 사용하여 2차원 배열을 나타낼 수 있다.

자바에서 2차원 배열은 다음과 같은 문법으로 선언할 수 있다.

***선언 방법***
1. 타입[][] = 배열이름;
2. 타입 배열 이름[][];
3. 타입[] 배열이름[];

다음 그림은 2차원 배열을 이해하기 쉽도록 도식적으로 표현한 그림이다.

이미지 출처: http://www.tcpschool.com/java/java_array_twoDimensional

int[][] arr = new int[2][3];    // 2차원 배열 선언 및 생성 방법

int k = 10;
for (int i = 0; i < arr.length; i++) {
    for (int j = 0; j < arr[i].length; j++) {
        arr[i][j] = k; // 인덱스를 이용한 초기화
        k += 10;
    }
} 

for (int i = 0; i < arr.length; i++) {
    for (int j = 0; j < arr[i].length; j++) {
        System.out.print(arr[i][j] + " ");
    }
    System.out.println();    // 10 20 30(줄바꿈)40 50 60 출력
}

배열의 선언과 동시에 초기화

1차원 배열과 마찬가지로 2차원 배열도 선언과 동시에 초기화가 가능하며, 자바에서는 2차원 배열의 모든 요소를 좀 더 직관적으로 초기화할 수 있다.

***선언 및 초기화 방법***
타입 배열이름[열의길이][행의길이] = {
    {배열요소[0][0], 배열요소[0][1], 배열요소[0][2], ...},
    {배열요소[1][0], 배열요소[1][1], 배열요소[1][2], ...},
    {배열요소[2][0], 배열요소[2][1], 배열요소[2][2], ...},
    ...
};
int[][] arr = {
    {10, 20, 30},
    {40, 50, 60}
};

가변 배열(dynamic array)

자바에서는 2차원 배열을 생성할 때 열의 길이를 명시하지 않음으로써, 행마다 다른 길이의 배열을 요소로 저장할 수 있다. 이렇게 행마다 다른 길이의 배열을 저장할 수 있는 배열을 가변배열이라고 한다.

또한 가변 배열도 초기화 블록을 사용하여 배열을 선언과 동시에 초기화할 수 있다.

int[][] arr = new int[3][];
arr[0] = new int[2];
arr[1] = new int[4];
arr[2] = new int[1];

int[][] arr2 = {
    {10, 20},
    {10, 20, 30, 40},
    {10}
};

 


8. 타입 추론, var

타입 추론(Type Inference)

타입 추론은 코드 작성 당시 변수의 타입이 정해지지 않았지만, 컴파일러가 그 타입을 유추하는 것을 의미한다.

Java 10 이상에서 var라는 Local Variable Type-Inference가 추가되었다.
(Java 9 버전 이하에서는 일반 변수에 대해 타입 추론을 지원하지 않으며, 이 때의 타입 추론은 Generic과 Lambda에 대한 타입 추론을 의미한다.)

var

var는 local variable이면서 선언과 동시에 초기화가 필수적으로 요구된다.

// java 9 이하
String message = "Good bye, Java 9";
// java 10 이상
var message = "Hello, Java 10";

데이터 타입을 명시하지 않아도 컴파일러는 변수에 대입한 오른쪽에 있는 리터럴의 유형으로부터 타입을 유추하여 주입한다. 이 기능은 초기화값이 있는 로컬 변수에만 사용할 수 있다.

var는 키워드가 아니고 int와 같은 타입의 이름이다. 변수의 유형은 컴파일 후 추론되며, 나중에 변경할 수 없다.

 

 


참조 URL

https://gbsb.tistory.com/6

https://blog.naver.com/highkrs/220242895539

https://blog.naver.com/brickbot/220511845770

https://mine-it-record.tistory.com/100

https://roseee.tistory.com/entry/Java-변수-선언하기-데이터-타입과-타입-변환

http://www.tcpschool.com/java/java_datatype_variable

https://programmers.co.kr/learn/courses/5/lessons/231

https://wakestand.tistory.com/179

https://lemontia.tistory.com/649

http://www.tcpschool.com/java/java_datatype_typeConversion

https://stage-loving-developers.tistory.com/8

https://velog.io/@bk_log/Java-타입-추론

https://www.baeldung.com/java-10-local-variable-type-inference

yadon079.github.io/2020/java%20study%20halle/week-02

catsbi.oopy.io/6541026f-1e19-4117-8fef-aea145e4fc1b

 

'개발 > 자바' 카테고리의 다른 글

Week-01-JVM  (0) 2021.04.13