ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바 데이터 타입, 변수 그리고 배열
    Develop/Java 2021. 3. 25. 14:47
    -  프리미티브 타입 종류와 값의 범위 그리고 기본 값
    - 프리미티브 타입과 레퍼런스 타입
    - 리터럴
    - 변수 선언 및 초기화하는 방법
    - 변수의 스코프와 라이프타임
    - 타입 변환, 캐스팅 그리고 타입 프로모션
    - 1차 및 2차 배열 선언하기
    - 타입 추론, var

     

     

    Data Type

    데이터가 메모리에 어떻게 저장되고, 프로그램에서 어떻게 처리되어야 하는지를 나타낸다.

     

    Primitive Type

    총 8가지가 존재하고, 기본값이 있기 때문에 null이 존재하지 않는다. null을 넣을 경우, 래퍼 클래스를 활용한다.

    stack memory에 저장된다. 자료형에 담을 수 있는 크기를 벗어난다면, 컴파일 시점에 에러가 발생한다.

     

    논리형 boolean 1 byte true / false
    정수형 byte 1 byte -128 ~ 127
      short 2 byte -32,768 ~ 32,767
      int 4 byte -2,147,483,648 ~ 2,147,483,647
      long 8byte -9,223,372,036,854,775,808 
    ~ 9,223,372,036,854,775,807
    실수형 float 4byte 3.4 * 10^-38 ~ 3.4 * 10^38의 근사값
      double 8 byte 1.7 * 10^-308 ~ 1.7 * 10^308
    문자형 char byte ( 유니코드 ) 0 ~ 65,535

     

    Reference Type

    참조형, 기본적으로 java.lang.object를 상속받는다. 빈 객체를 의미하는 null이 존재한다.

    값이 저장되어있는 곳의 주소값을 저장하는 공간으로, 힙 메모리에 저장된다. 실행시키고 나서,런타임 에러가 발생할 수 있다. 

    ex ) NullPointerException

     

    배열 (array) null 4 byte ( 객체의 주소값 )
    열거 (enumeration) null
    클래스 (class) null
    인터페이스 (interface) null

     

     

    String Class

     string은 참조형에 속하지만, 기본적인 사용은 primitive type처럼 사용한다. 불변하는 immutable 객체이며, 값을 변경해주는 메서드들이 존재하긴 하지만 결국 새로운 string class 객체를 만들어 내는것이다. 일반 기본형 비교는 `==`으로 진행하는데, string 객체간의 비교는 `.equals`를 사용해야한다.

     

     

    Interface Type

    인터페이스를 만들면 새로운 참조 자료형 (Reference data type)을 만드는 것과 같음. 기존에 있는 자료형의 이름도 만들 수 있다.

     

     

     

    리터럴

    프로그램에서 직접 표현한 값. 소스코드의 고정된 값을 말한다. 종류는 정수, 실수, 문자, 논리, 문자열 리터럴이 존재한다.

    데이터 그 자체이며, 변수에 넣는, 변하지 않는 데이터를 의미한다.

     

    정수 리터럴

    10진수 / 8진수 / 16진수 / 2진수 리터럴 

    j = 0으로 시작하면 8진수

    k = 0x으로 시작하면 16진수

    l = 0b으로 시작하면 2진수. 

     

    정수 리터럴은 int형으로 컴파일한다. long 리터럴은, 숫자 뒤에 L 또는 l을 붙여서 표시한다.

    long e = 26L;

     

    실수 리터럴

    소수점 형태나 지수 형태로 표현한 값이다.

    실수 타입은 double타입으로 컴파일된다.

    숫자 뒤에 f ( float )나 d ( double ) 을 명시적으로 붙이기도 한다.

    float는 꼭 붙여줘야 하고, double은 생략 가능하다.

     

     

     

    문자 / 문자열 리터럴

    ' ' / " "로 문자를 표시한다.

     

    Java 변수의 초기화

    변수 초기화

    변수를 선언하고 처음으로 값을 저장하는것. 가능하면 변수는 선언시에 초기화하는것이 바람직하다. 멤버변수는 기본적으로 타입에 맞게 초기화가 되지만,  local변수는 사용 전에 반드시 초기화가 되어야 한다.

     

     

    멤버변수 초기화 방법 (explicit initialization)

    변수 선언과 동시에 초기화한다.

    초기화 블럭

    1. 클래스 초기화 블럭
      • 클래스를 초기화하는데 사용. 클래스가 처음 메모리에 로딩될 때 한번만 수행된다.
      • 인스턴스 변수 앞에 static을 붙이면, 모든 인스턴스가 같은 값을 공유한다
    2. 인스턴스 초기화 블럭
      • 인스턴스 초기화 시 사용.
      • 생성자와 같이 인스턴스가 생성될 때 수행된다. 계속 생성될때마다 수행하는것.
      • 인스턴스 초기화 블럭이 생성자보다 먼저 수행된다.

    초기화 블럭 내에서는 메서드 내에서와 같이 조건문, 반복문, 예외처리구문 등을 자유롭게 사용 가능하다.

    인스턴스 변수의 초기화는 주로 생성자를 이용한다.

    인스턴스 초기화 블럭은, 모든 생성자에서 공통으로 수행되어야 하는 코드를 넣는데에 사용한다.  => 코드 간결성 증가

     

    1. 클래스 초기화 블럭 -> 2. 인스턴스 블럭 초기화 -> 3. 생성자 초기화

     

    멤버변수 - 객체변수    - 객체속성변수

                                      - 객체 참조변수

                  - 클래스변수

                  - final변수

     

    클래스가 처음 로딩될 때 클래스변수들이 자동적으로 메모리에 만들어지고 나서 바로 클래스 초기화 블럭이 클래스 변수들을 초기화한다.

     

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

    Scope?

    영역. 변수에 접근하거나 접근할 수 있는 유효 범위,영역

     

    Lifetime?

    memory에서 변수가 살아있는 기간.

     

    인스턴스변수

    클래스 내부와 모든 메서드 및 블록 외부에서 선언된 변수를 말한다. 

    scope : 정적 method를 제외한 class 전체

    lifetime : 객체가 메모리에 남아있는 동안

     

    클래스변수

    클래스 내부, 모든 블록 외부에서 선언되고 static으로 표시된 변수

    scope : 클래스 전체

    lifetime : 프로그램이 끝날때까지 / 클래스가 메모리에 로드되는 동안

     

    지역변수

    인스턴스/클래스 변수가 아닌 모든 변수

    scope : 선언 블록 내에

    lifetime : 컨트롤이 선언블록을 떠날때까지

     

    타입 변환 : 캐스팅 , 타입 프로모션

    형변환

    연산을 수행하기 전에 타입을 일치시켜야한다. 이 때 다른 타입으로 변환하는 것을 형변환(casting)이라고 한다.

     

    방법

    (type) variable : 변환하고자 하는 type을 앞에 괄호로 명시해주면 된다.

     

    괄호는 '캐스트연산자' / ' 형변환 연산자' 라고 불린다.

     

    Primitive type에서 boolean을 제외한 나머지  type들은 서로 형변환이 가능하다. 기본형 / 참조형간의 형변환은 불가능하다.

     

    정수형간의 형변환

    큰 타입 -> 작은 타입으로의 변환일 경우 크기의 차이만큼 잘려나간다. 그래서 loss of data가 발생할 수 있음. 

    작은 타입 -> 큰 타입으로의 변환이 일어날 경우 빈공간이 0이나 1로 채워진다.

     

    자동형변환

    컴파일러가 생략된 형변환을 자동적으로 추가한다. 아무리 자동이어도 범위를 넘으면 error가 발생한다. - imcompatible types

     

    규칙

    기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환한다.

     

     

    byte ( 1 byte ) -> short / char ( 2 byte )  -> int ( 4 byte )  -> long ( 8 byte )  -> float  ( 4 byte ) -> double ( 8 byte ) 

     

    실수형은 정수형과 값을 표현하는 방식이 달라서 float와 double이 int나 long보다 오른쪽에 위치한다.

     

     

    DownCasting

    좁은 범위로의 형변환. data 손실이 일어날 수 있기 때문에 직접 선언해줘야 한다. (explicit)

     

    UpCasting

    넓은 범위로의 형변환. upcasting은 자동으로 변환한다. (implicit)

     

     

    Type promotion

    크기가 더 작은 자료형을 더 큰 자료형에 대입할 때 , 자동으로 작은 자료형이 큰 자료형으로 변환됨.

    캐스팅은 promotion과 다르게 명시적으로 형변환을 시키는 것이다. 즉, 묵시적 형변환이 promotion.

     

    1차 / 2차 배열 선언하기

    Array

    같은 type의 여러 변수를 하나의 묶음으로 다루는 것. 변수의 선언과 달리 다루어야 할 data의 수가 아무리 많아도, 배열의 길이를 바꾸면 된다.

     

     

     

               

    메모리에 위와 같이 생성된다.

     

     

    선언 방법

    배열의 길이, index

    배열의 각 저장공간은 element(요소)이다. 배열 이름[index]의 형식으로 요소에 접근 가능하다.

    index = 배열의 요소마다 붙여진 일련번호.

    범위 : 0 ~ (길이 - 1)

     

    초기화는 생성과 동시에 자동으로 자신의 type에 해당하는 기본값으로 초기화 된다. 하지만 원하는 값을 저장하려면 각 요소마다 값을 지정해주어야 한다.

     

    배열의 복사

    System.arraycopy()를 이용한 배열의 복사

    for문보다 효율적이긴 하다. arraycopy()는 지정된 범위의 값을 한번에 통째로 복사한다. for문은 배열의 요소 하나하나에 접근해서 복사한다.

     

    자바에서는 배열이 실제 객체이기 때문에 Heap 영역에 생성된다. 즉, 크기가 고정된다. fixed heap array.

     

    2차열 배열 선언

    int arr[][] = new int [2][3]

     

    크기를 동적으로 늘리고 줄이기 위해서는 heap dynamic array를 사용해야 한다. (동적 배열) ArrayList가 해당 연산을 지원한다.

     

     

    타입 추론 / var

    Java 10에서 var 라는 Local variable Type inference가 추가됨.

     

    타입 추론?

     

    정적 타이핑을 지원하는 언어에서 type이 정해지지 않은 변수에 대해서, 컴파일러가 변수의 타입을 스스로 찾아낼 수 있도록 하는 기능. 타입 추론이 가능하므로 type 명시를 안해도 되고, 코드 가독성이 증가하고 코드량을 감소시킬 수 있다.

     

    기존에는 generics와 lambda에서만 지원했다.

     

     

    주의해야 할 부분

     

    java 7에서 다이아몬드 연산자 방식이 추가되었는데, var와 함께 사용하게 되면 컴파일 에러가 발생한다.

    var messages = new ArrayList<>(); //컴파일러가 타입을 유추할 수 있는 정보가 없다

     

    var는 초기화 값이 있는 지역변수로만 선언이 가능하다. 이 조건을 만족하지 않으면 에러가 발생함.

     

    컴파일 시점에 var를 초기화 된 값을 보고 바이트코드에 명시적으로 타입을 명시해주기 때문에, 타입 추론 변수를 읽을 때 마다 타입을 알아내기 위한 오버헤드가 발생하지 않기 때문에, 런타임 오버헤드는 존재하지 않는다. var로 선언된 변수는, 중간에 타입이 절대 변경되지 않는다.

     

    특징

    • 초기화 없이 사용 불가능하다.
    • local 변수에서만 사용 가능하다.
    • null이 들어갈 수 없다.
    • 배열 선언시에는, var 대신 type을 명시해주어야 한다.
    • lambda expression에서는 명시적 type을 지정해주어야 한다.

    Usage

    foreach

    리스트 열거를 할 때 쓰던 for, for(Person person : personList)문에서 변수 선언할 때 var로 쓰면 유용하다. IDE에서는 이렇게 작성하면, var 키워드를 Person 클래스로 인식할 수 있는 기회가 주어지게 된다. Object 타입으로 미리 단정지을 필요도 없다.

     

    Lambda

    자바 11은 람다 인자에도 var를 넣게 지원해준다. 일반 람다의 경우 파라미터 어노테이션을 집어넣지 못한다. 어노테이션을 넣고 싶으면 메소드로 따로 빼던가 익명 클래스로 정의해야 한다. 하지만 자바 11부터는 타입 추론의 유연성이 추가된것.

    Consumer<Person> personConsumer = (@Nonnull var person) -> { // @Nonnull 어노테이션을 적용하면 null 체크 먼저 가능 }

     

     

     

     

     

    'Develop > Java' 카테고리의 다른 글

    연산자  (0) 2021.06.12
    JVM은 무엇이며, 자바 코드는 어떻게 실행하는 것인가?  (0) 2021.01.11
    Java String  (0) 2020.11.13

    댓글

Designed by Tistory.