[라이브 스터디]자바 데이터 타입, 변수 그리고 배열

sjhello·2020년 11월 21일
0

자바 데이터 타입, 변수 그리고 배열

프리미티브 타입(기본 타입) 종류와 값의 범위 그리고 기본값

출처: https://kingpodo.tistory.com/54

각각의 데이터 타입의 범위는 메모리 사용 크기에 결정되는데
byte의 경우로 예를 들자면 byte의 크기는 1바이트이다 1바이트는 8비트의 크기를 갖는다
컴퓨터는 2진수 체계를 사용한다 즉 1비트당 값을 2개(0,1) 가질 수 있다

2비트라면? 00, 01, 10, 11 4개의 값을 가진다 → 2^2개(4개)

3비트 라면? 000, 001, 010, 011, 100, 101, 110, 111 → 2^3개(8개)

따라서 1비트 부터 8비트의 숫자 표현은 2^8개(256개)의 값을 가질 수 있으며 byte는 음수와 양수를 지원한다(signed)

signed 자료형이 음수를 표현하기 위해서는 첫번째 비트를 사용하는데
첫번째 비트가 1이라면 음수, 0이라면 양수가 된다

자바를 만든 제임스 고슬링은 char를 제외한 자료형에 unsigned 키워드를 아예 없애버렸다고 한다
이유는 c++에서 unsinged로 인한 오류를 너무 많이 보고 겪었기 때문에...

기선님 11/21 라이브 방송중 추가 내용
Java 8 버전 부터 unsinged 가 추가되었다고 한다

프리미티브 타입과 레퍼런스 타입

기본 타입(프리미티브 타입)

  • 변수에 할당된 값을 직접 메모리(Stack 영역)에 할당한다
  • 기본 타입에 null을 담지 못한다(null은 아무것도 정의되지 않은 상태를 의미하며, null은 레퍼런스 타입에 담을 수 있다

참조 타입(레퍼런스 타입)

  • 실제 값이 위치한 주소를 메모리에 할당한다
  • 레퍼런스 타입 또한 기본 타입과 마찬가지로 JVM Stack 영역에 쌓이게 되는데 값에는 메모리의 주소값이 들어간다 이 주소값은 JVM Heap 영역에 생성이 되고 변수는 Stack 영역에 생성된다

리터럴

  • 특정 타입의 데이터를 담는 그릇을 변수라고 하는데 변수 안에 저장되어지는 값을 리터럴이라고 한다

  • 변수에 저장되는 값 그 자체 이며 이 값은 변하지 않는다

    int number = 1    // number는 변수, 1은 리터럴
  • 변수에 담을 수 있는 데이터 타입이 있듯이 리터럴 또한 데이터 타입이 있다

    • 정수 리터럴, 실수 리터럴, 문자 리터럴 등...

변수의 선언 및 초기화 하는 방법

변수의 선언

int a;

변수를 선언하는 방법이다 변수를 선언하게 되면 Stack 영역에 변수의 메모리 공간이 생긴다

변수의 초기화

int a;
a = 10;

a라는 변수를 선언하고 a에 10이라는 값으로 a를 초기화 하였다

int a = 10;

변수의 선언과 초기화를 같이 할 수도 있다

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

자바에서 사용하는 변수의 종류는 3가지 정도가 있다

클래스 변수, 인스턴스 변수, 지역 변수

public class varScope {
    int instanceVal;        // 인스턴스 변수
    static double b = 30;   // 클래스 변수

    public static void main(String[] args) {
        varScope vs = new varScope();
        
        System.out.println(varScope.b);
        System.out.println(varScope.instanceVal);   // error -> static 키워드가 없기 에러, 인스턴스 생성 후에 호출 가능
        System.out.println(vs.instanceVal);
        
        vs.foo("name");
        System.out.println(fooNumber);   // error -> 메서드내에 선언된 변수(지역변수)는 해당 메서드 내에서만 실행 가능
        System.out.println(name);       // error -> 매서드에 보내진 매개변수는 매서드가 호출될 때 생성 되고 매서드 실행이 끝나면 소멸
    }

    public void foo(String name) {
        int fooNumber;      // 지역변수
        fooNumber = 20;
        System.out.println(name);       // "name"
    }
}

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

자바에서는 2가지 타입변환이 있다

  • 캐스팅(명시적 형변환): 큰 타입을 작은 타입으로 변환 할 때
    • 컴파일러는 타입 변환을 하려는 자료형들의 사이즈를 비교한다
    • 작은 자료형에서 큰 자료형으로 타입 변환 할때에는 값의 변환이 일어나지 않기 때문에 컴파일러가 자동으로 형변환을 해준다
  • 타입 프로모션(묵시적 형변환, 자동 형변환): 작은 타입을 큰 타입으로 변환 할 때
    • 큰 자료형에서 작은 자료형으로 타입 변환을 하려는 상황이다
    • 큰 사이즈에서 작은 사이즈로 변환하는것 이지만 컴파일러는 단순하게 자료형의 크기로 프로모션인지 캐스팅인지 따진다
    • 때문에 변환하려는 자료형을 직접 명시해줘야하며 이 과정에서 값이 손실될 수도 있다

기본 자료형에서의 타입 변환

public class CastingTest {
    public static void main(String[] args) {
        int a = 10;
        long b = 20;

        b = a;      // int 값의 범위가 long 값의 범위보다 적다 따라서 타입 프로모션 가능
        a = (int)b; // long 값의 범위가 int 값의 범위보다 크다 따라서 long -> int로 변환 과정 중 값의 손실이 있을 수 있음
    }
}

참조 자료형에서의 타입 변환

기본 자료형에서의 타입 변환은 해당 자료형의 사이즈로 프로모션인지, 캐스팅인지 따졌다면
참조 자료형에서는 해당 객체가 부모 객체인지, 자식 객체인지로 따진다

public class CastingTest {
    public static void main(String[] args) {
        Parent parent = new Child();    // 프로모션
				
		Parent parent2 = new Child();
        Child child = (Child)parent2;   // 캐스팅
    }
}

class Parent {
    public void getParent() {
        System.out.println("parent");
    }
}

class Child extends Parent {
    public void getChild() {
        System.out.println("child");
    }
}

Parent parent = new Child(); // 프로모션

Parent 객체는 Child 객체의 부모이다 자바에서 상속은 부모 객체의 있는 것(필드, 메서드 등)을 자식 객체가 그대로 사용 할 수 있게 하는 것이다
따라서 부모 클래스에서 사용할 수 있는 것들을 자식 클래스에서 그대로 사용할 수 있기 때문에 전혀 문제없이 프로모션이 된다

Parent parent2 = new Child(); // 프로모션
Child child = (Child)parent2; // 캐스팅

캐스팅의 경우는 부모 클래스를 자식 클래스로 변환 하는 경우인데 부모 클래스는 자식객체의 메서드나 필드에 접근 할 수 없다 때문에 부모 클래스를 자식 클래스로 프로모션 한 후 자식 클래스에 할당 할때에는 캐스팅을 해야한다

Child child2 = (Child)new Parent(); // 컴파일 오류는 넘겼지만 실행 시에 에러발생

이건 왜 안될까?
child2에 집어 넣으려는 new Parent()를 Child로 형변환 하였지만 실제로는 new Parent()객체이다 때문에 Child 객체에 할당 할 수 없다

1차 및 2차 배열 선언하기

1차원 배열

public class arrayTest {
    public static void main(String[] args) {
        int [] arr;
        int arr2 [];

        int [] arr3 = {1,2,3,4,5};      // 배열의 선언과 초기화를 동시에 함

        arr = new int[3];
        arr2 = new int[]{1,2,3};
    }
}
public class arrayTest {
    public static void main(String[] args) {
        int [][] arr = new int[3][];
        arr[0] = new int[3];
        arr[0][0] = 1;
        arr[0][1] = 2;
        arr[0][2] = 2;

        int arr2 [][] = new int[3][];
        arr[0] = new int[]{1,2,3};

        int [][] arr3 = {{1,2,3}, {4,5,6}};    // 선언과 동시에 초기화
    }
}

타입 추론, var

Java 10 버전부터 추가된 기능입니다.
Java 9 버전 까지는 지역변수에 명시적으로 타입을 지정했지만 var를 사용하면 명시적으로 타입을 지정해주지 않아도 컴파일러가 알아서 타입 추론을 해준다

public class varTest {
    public static void main(String[] args) {
        String message = "hello java";
        var varMessage = "var로 만든 hello java ";

        System.out.println(message);
        System.out.println(varMessage);
    }
}

var를 사용 할 수 없는 경우

  • 선언과 동시에 초기화를 해주지 않은 경우

  • var로 선언된 변수에 null을 할당 한 경우

  • 지역변수가 아닌 다른 스코프에서 사용할 경우

    • 인스턴스 변수

      public class varTest {
          var aa = "mamama";    // It won't work for non-local variables
      ...
      }
    • 메서드의 매개변수로 사용한 경우

      public class varTest {
      ...
          public void getVar(var aa) {
      
          }
      }
  • var를 사용하여 배열을 초기화 한 경우

var arr = {1,2,3};    // Array initializer is not allowed here
  • 람다를 사용하는 경우(람다에 대해서는 추후 학습..)
var aa = () => {
            
};

0개의 댓글