코딩하는 털보

STUDY HALLE - 2주차 본문

Diary/Study Halle

STUDY HALLE - 2주차

이정인 2020. 12. 20. 16:58

STUDY HALLE

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


목표

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

학습할 것

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

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

Data Type Size Range of Values Default Value
byte 1 byte -128 to 127 0
short 2 bytes -32,768 to 32,767 0
int 4 bytes -2,147,483,648 to 2,147,483,647 0
long 8 bytes -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 0L
float 4 bytes upto 7 decimal digits 0.0f
double 8 bytes upto 16 decimal digits 0.0d
boolean 1 bit true or false values false
char 2 bytes 0 to 65535 ('\u0000' ~ 'uFFFF') '\u0000'

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

프리미티브 타입은 리터럴을 대입할 수 있는 위 8가지 데이터 타입이며,

레퍼런스 타입은 프리미티브 타입 외의 모든 타입(클래스, 인터페이스, 배열, 리스트)이다.

이 둘의 궁극적인 차이점은

프리미티브 타입 같은 경우 변수 선언시 할당되는 메모리 공간에 실제 값을 담아 놓지만,

레퍼런스 타입은 다른 곳을 참조하는 주소 값을 담아 놓는다는 것이다.

public class Hello {

    public static void main(String args[]) {
        Student student;
        student = new Student();
        System.out.println(student);
    }

}
[/Users/ijeong-in/Documents]> javac Hello.java
[/Users/ijeong-in/Documents]> java Hello      
Student@6504e3b2

프리미티브 타입은 기본값이 있어서 선언 할 때 초기화를 하지 않더라도 기본값을 사용하지만

레퍼런스 타입은 별도의 기본값이 없기 때문에 그냥 선언하면 'null'이 된다.(참고로 프리미티브 타입은 'null'이 될 수 없다.)

레퍼런스 타입 변수가 'null'이라는 것은 해당 변수가 아무것도 참조하고 있지 않다는 의미이다.

public class Hello {

    Student student;
    int i;

}
public class Test {
  public static void main(String args[]) {
    Hello hello = new Hello();
    System.out.println(hello.student);
        System.out.println(hello.i);
    }
}
[/Users/ijeong-in/Documents]> javac Test.java
[/Users/ijeong-in/Documents]> java Test
null
0

리터럴

리터럴 : 프로그램에서 사용하는 모든 숫자, 값, 논리 값이며 '데이터' 그 자체를 의미한다.

  • 리터럴은 변수에 대입할 수 있으며 변하지 않는다.

    int num = 10; //변수 num을 리터럴 10으로 초기화
  • 모든 리터럴은 메소드 영역의 런타임 상수 풀(runtime constant pool)에 저장 된다.

  • 일반적인 클래스는 변하는 성질을 가지므로 리터럴을 대입할 수 없지만,

    Java에서 제공되는 불변 클래스인 String 등은 객체의 데이터가 변하지 않으므로 리터럴을 대입할 수 있다.

상수 : '변하지 않는다'는 속성은 리터럴과 같으나 상수는 변하지 않는 '데이터'가 아닌 '참조 값'이다.

  • Java에서는 상수를 위해 변수 생성에 final 키워드를 사용한다.
int final num = 10; //상수 num

변수 선언 및 초기화

변수는 _선언_이 필요하다.

선언 방법 :
자료형 변수이름;
(ex) int age;

package variable;

public class VariableTest {

    public static void main(String[] args) {
        int age, count; //선언
        age = 30; //초기화
        int age_2 = 20; //선언과 동시에 초기화

        System.out.println(age);
        System.out.println(age_2);
    }
}

‘=’표시는 같다는 의미가 아니고 대입의 의미이다. (l-value=r-value : r-value를 l-value에 대입)
그렇기 때문에 언제든지 변수는 바뀔 수 있다.

선언은 여러 변수를 한번에 할 수 도 있고

        int age, count;

선언과 동시에 초기화(대입)할 수도 있다.

        int age_2 = 20;

선언은 해당 변수형의 크기 만큼 메모리를 사용한다.
(ex int age; -> 4byte 메모리 점유)

변수이름은…

  1. 숫자로 시작할 수 없다.
  2. 특수문자는 ‘_’와 ‘$’만 가능하다.
  3. 예약어는 쓸 수 없다. (ex : while, for, int, etc…)
  4. 쓰임에 맞게 명명해야 가독성이 좋다. (줄여서 약어로 쓰지 말자.)

되도록 소문자로 시작하고 단어가 바뀔때 대문자를 사용한다. (camel notation)


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

변수의 스코프 : 특정 변수를 사용할 수 있는 범위이자 변수가 선언된 블럭이다.

  • 블럭 == "{ }"
  • 동일한 스코프 내에서 동일한 이름의 변수를 사용할 수 없다.
public class Student {

  public int id = 1;
  public String global = "GLOBAL";
  // id, global 변수의 스코프는 Student 클래스이다.
  // 이렇게 클래스에서 어디서나 사용할 수 있는 변수를 '전역 변수'라고 한다.
  // (static 메서드에서는 사용할 수 없다.)
  public static String stat = "STATIC";
  // 전역 변수 중에서 static 키워드가 달린 변수를 '정적 변수'라고 한다.
  // 정적 변수는 static 메서드에서도 사용할 수 있으며 외부에서 객체 생성 없이 사용할 수 있다는 특징이 있다.

  public void getLocal() {
    String local = "LOCAL";
    // local 변수의 스코프는 getLocal() 메서드이다.
    // local 변수는 getLocal() 메서드 내에서만 사용할 수 있다.
    // 이렇게 특정 메소드나 생성자, 초기화 블럭, 반복문 내부에서만 사용할 수 있는 변수를 '지역 변수'라고 한다.
  }

  public static void getStat() {
    System.out.println(stat);
    //System.out.println(global);
    //static 메서드에서 전역 변수는 사용할 수 없지만 정적 변수는 사용할 수 있다.
  }

  for (int i = 0; i < 10; i++) {
    int forNum = i; //이 반복문 내에서만 사용할 수 있다.
    }

  {
    int block = 100; //이 블럭 내에서만 사용할 수 있다.
    }

  //global = local; //컴파일 에러
  //id = forNum; //컴파일 에러
  //id = block; //컴파일 에러

}
public class Test {
  public static void main(String args[]) {
    System.out.println(Student.stat); //클래스를 생성하지 않아도 정적 변수는 참조할 수 있다. 
    Student student = new Student(); //전역 변수는 클래스를 생성하면 참조할 수 있다.
    System.out.println(student.id);
    System.out.println(student.global);
        //System.out.println(student.local); //지역 변수는 참조할 수 없다.
    //System.out.println(student.forNum);
    //System.out.println(student.block);
    }
}

변수 라이프 타임 : 변수가 메모리에서 살아있는 기간이다.

  • 전역 변수의 라이프 타임 : 객체가 생성되고부터 메모리에서 사라질 때 까지
  • 정적 변수의 라이프 타임 : 프로그램 시작부터 종료까지
  • 지역 변수의 라이프 타임 : 블록이 실행된 후 부터 종료될 때 까지

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

타입 변환 : 형 변환이라고도 하며 변수의 타입을 변환하는 것이다. 다만 형 변환의 궁극적인 목적은 변수 타입의 변환이 아닌 OOP의 다형성에 활용하기 위함이다. 형 변환의 방향에 따라 캐스팅과 프로모션으로 나뉘어진다.

  • 프로모션 : 작은 수 -> 큰 수, 덜 정밀한 수 -> 더 정밀한 수로 대입되는 경우이다.

    • 특별한 명시를 하지 않아도 JVM이 알아서 변환해줄 수 있다.(묵시적 형 변환)
    • 업캐스팅이라고도 한다.
  • 캐스팅 : 큰 수 -> 작은 수, 더 정밀한 수 -> 덜 정밀한 수로 대입되는 경우이다.

    • 변환 될 자료 형을 명시해야한다.(명시적 형 변환)

    • 자료 손실이 발생할 수 있다.

    • 다운캐스팅이라고도 한다.

package variable;

public class ImplicitConversion {
    public static void main(String[] args) {

        byte bNum = 10;
        int iNum = bNum; //더 큰수로 묵시적 형 변환(byte -> int)

        System.out.println(bNum);
        System.out.println(iNum);

        int iNum2 = 20;
        float fNum = iNum2; //더 정밀한 수로 형 변환(int -> float)

        System.out.println(fNum);

        double dNum;
        dNum = fNum + iNum; //더 정밀한 수로 형 변환 2회 i->f->d
        System.out.println(dNum);

    }

}
package variable;

public class ExplicitConversion {
    public static void main(String[] args) {

        int i = 1000;
        //byte bNum = i;
        byte bNum = (byte)i; //명시적 형 변환(int -> byte)
        System.out.println(Integer.toBinaryString(i)); //1111101000
          System.out.println(bNum); //-24 (1110 1000), 왼쪽 2bit 데이터 유실

        double dNum = 1.2;
        float fNum = 0.9F;

        //int iNum1 = dNum + fNum;
        int iNum1 = (int)(dNum + fNum);
        int iNum2 = (int)dNum + (int)fNum;
        System.out.println(iNum1); //데이터 유실 2.1 -> 2
        System.out.println(iNum2); //데이터 유실 1.2+0.9 -> 1+0

    }
}

1차 및 2차 배열 선언

배열(Array) : 동일한 자료형의 순차적 자료 구조.
ex) 학생 100명에 대한 학번 변수

배열 선언

int[] arr = new int[10]; //int 10개 = 40byte length=10, 0~9
int arr[] = new int[10];
  • 배열은 fixed length이다.
    만약 배열의 길이를 늘리고 싶다면, 더 긴 배열을 선언한 뒤 값을 복사해야 한다.

  • 배열은 연속적이어야 한다. (중간에 비어있으면 안된다.)

  • 데이터가 들어가거나 빠질때 추가적인 작업이 필요하다.

  • 배열을 사용하는 가장 큰 이유 : 인덱스 연산자 'Array[ ]'

arr[4] //arr배열의 다섯번째 값 추출, 추출이 편하고 속도가 빠름
package array;

public class ArrayTest {

    public static void main(String[] args) {

        int[] arr = new int[10]; //기본자료형 Array
        int[] arr2 = new int[] {1,2,3}; //선언과 동시에 초기화 가능
        int[] arr3 = {1,2,3}; //위와 동일
        int total = 0;

        for (int i=0;i<arr.length;i++) {
            System.out.println(arr[i]); //0으로 10개가 초기화되어 있음
        }

        for (int i=0,num=1;i<arr.length;i++,num++) { //배열 arr의 모든 요소를 1씩 증가하도록 변경
            arr[i]=num;
        }

        for (int i=0;i<arr.length;i++) {
            System.out.println(arr[i]);
        }

        for (int i=0;i<arr.length;i++) { //배열 요소 합 구하기
            total += arr[i];
        }

        System.out.println(total);

        double[] dArr = new double[5];
        int count = 0;
        dArr[0] = 1.1; count++;
        dArr[1] = 2.1; count++;
        dArr[2] = 3.1; count++;

        double mtotal = 1;
        for (int i=0;i<count;i++) { //count를 통해 직접 초기화 한 값만 곱
            mtotal *= dArr[i];
            System.out.println(dArr[i]);
        }
        System.out.println(mtotal);

    }
}

2차원 배열

int[][] arr = new int [2][3]; //2행x3열 = 6개 요소
package array;

public class TwoDimension {
    public static void main(String[] args) {

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

        System.out.println(arr.length); //2차원 배열에서 length는 행의 개수
        System.out.println(arr[0].length); //0번째 행의 길이
        System.out.println(arr[1].length);

        //행을 기준으로 열을 돌린다.(2중 for문)

        for (int i=0; i<arr.length; i++) { //행 for문
            for (int j=0; j<arr[i].length; j++) { //열 for문
                System.out.print(arr[i][j]+" ");
            }
            System.out.println();
        }
    }
}

타입 추론, var

지역 변수 타입 추론 Local variable type inference (java 10 이상) : 지역변수에 한하여 대입되는 값을 보고 컴파일러가 변수형을 추론하는 기능.

  • 지역 변수에 한정된다.
  • 선언과 동시에 초기화가 필요하다.
package variable;

public class BooleanTest {
    public static void main(String[] args)  {
        var iVar = 10;
        var sVar = "String";

        System.out.println(iVar);
        System.out.println(cVar);
    }
}
Comments