2021-12-06 수업내용

범고래·2021년 12월 6일
0

비트캠프 수업내용

목록 보기
9/20

(1) 스프링부트와 배열 파라미터

(2) 종류에 따른 변수의 사용 범위

class MyClass {
  int a=11; // 인스턴스 변수
  static int b=22; // 클래스 변수

  static void m1(int v1/*로컬변수=파라미터*/) {
    int v2; // 로컬 변수
    v2 =200;

    System.out.println(v1);
    System.out.println(v2);
  }
}

public class Exam0720 {



  public static void main(String[] args/*로컬변수=파라미터*/) {

    //1) 인스턴수 변수를 사용하는 방법
    MyClass obj1 = new MyClass(); // 클래스의 인스턴스를 생성할때 변수가 준비된다.(new 명령이 실행될 때 변수가 준비된다.)   
    System.out.println(obj1.a); // 인스턴스를 가리키는 레퍼런스를 통해 변수를 사용할 수 있다.
    // 결과 : 11
    
    //2) 클래스 변수를 사용하는 방법
    System.out.println(MyClass.b); // 클래스를 사용(로딩)하는 시점에 준비된다.
    // 결과 : 22

    //3) 로컬 변수는 사용하는 방법
    MyClass.m1(100); //메서드를 실행할 때 변수가 준비된다.
    // 결과 : 100 
    //       200

    // 메서드 호출이 끝나면, 그 메서드의 로컬 변수를 사용할 방법이 없다.
    //    v1 = 300; // 오류!
    //    // 메서드를 실행하는 동안, 그 메서드 안에서만 사용할 수 있다.
  }
}

(3) 로컬 변수와 블록

1)

public class Exam0820 {

  public static void main(String[] args) {

    int a = 100;

    {
      //      int a = 200; // 컴파일 오류!
      // 메서드 안에서는 변수 이름 중복 불가!
      // 안쪽 블록에서는 바깥 블록의 변수를 사용할 수 있다.
      a = 200;

      int b = 300;
      // 이 블록의 실행을 끝내는 순간 
      // 이 블록에서 선언된 모든 변수는 제거된다.
      // 그래서 b 변수는 제거된다.
    }
    System.out.println(a); // 200

    // 바깥 블록에서는 안쪽 블록의 변수를 사용할 수 없다.
    // 왜?
    // 안쪽 블록의 실행이 끝나면, 안쪽 블록에서 선언된 모든 변수들이
    // 자동으로 제거된다.
    //    System.out.println(b); // 컴파일 오류!

    {
      // 이전 블록에서 선언된 변수는 그 블록이 종료되는 순간 
      // 제거되기 때문에, 
      // 다음과 같이 같은 이름의 변수를 선언할 수 있다.
      int b = 400;
    }
  }
}

2)

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

    int a = 100;

    for (int i = 0; i < 10; i++) {
      // 바깥 블록에 선언된 변수와 같은 이름으로 변수를 만들 수 없다.
      //      int a; // 컴파일 오류!
      int b; // OK!
    }

    // 블록 안에 선언된 변수는 블록 실행을 마치면 제거된다.
    // 따라서 사용할 수 없다.
    //    System.out.println(i);// 컴파일 오류!
    //    System.out.println(b);// 컴파일 오류!

  }
}

3)

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

    int a = 100;

    switch (a) {
      case 1:
        //switch 바깥 블록에 같은 이름의 변수가 있다.
        //        int a; //컴파일 오류! 

        // case 문에서 선언한 변수는 switch 문에 소속된다.
        int b;
        {
          // 다음과 명확하게 블록 안에 선언하면
          // 이 블록의 변수가 된다.
         int c; 
        }
        break;
      case 2:
        // case는 다른 블록으로 취급되지 않는다.
        // 위쪽 case에서 선언한 변수는 switch 문에 소속된다.
        // 따라서 다음과 같이 아래쪽 case에서 
        // 같은 이름의 변수를 선언할 수 없다.
        //        int b; // 컴파일 오류!
        int c; // OK!

        break;

      case 3:
        for (int i = 0; i < 100; i++) {
          // for의 바깥 블럭인 switch 문에 이미 b 변수가 있다. 
          //          int b; // 컴파일 오류!
        }
        break;
      default:
    }
  }
}

(4) 값 저장과 메모리 크기

1)

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

    byte b = 100; //1byte
    short v1 =b;  //1byte -> 2byte

    short s = 100; // 2byte
    int v2 =s;  //2byte -> 4byte

    int i = 98765678; //4 byte
    long v3 =i;  //4byte -> 8byte

    long l = 98765678; //8 byte

    char c = 100; // 2byte(0 ~ 65535)
    //    short x1 = c; // char(0~65535) ==> short (-32768~32767), 값의 범위가 맞지 않아 컴파일 오류! 

  }
}

2) 정수는 부동소수점 메모리에 저장할 수 있다.

  • 부동소수점 메모리의 유효자릿수를 넘어가는 정수를 저장할 경우 값이 짤린다.
  • 그럼에도 컴파일 오류가 발생하지 않는다.
public class Exam0911 {
  public static void main(String[] args) {

    byte b = 100; // 1byte
    short s = 32767; // 2byte(-32768 ~ 32767)
    int i = 98765678; // 4byte(약 -21억 ~ +21억)
    long l = 18_2345_3456_4567_5678L; // 8byte(약 -922경 ~ 922경)

    float f;
    double d;

    // 주의!
    // float의 자릿수가 넘어가는 정수를 저장하는 경우 짤릴 수 있다.
    // 그럼에도 불구하고 컴파일 오류가 발생하지 않는다.
    // 그래서 정수 값을 부동소수점 메모리에 저장할 때 조심해야한다
    //
    f = b; // byte(1) ==> float(4). 값을 그대로 저장.
    System.out.println(f);

    f = s; // short(2) ==> float(4). 값을 그대로 저장. 
    System.out.println(f);

    f = i; // int(4) ==> float(4). 
    // 유효자릿수를 넘는 정수는 짤린다.
    System.out.println(f);

    f = l; // long(8) ==> float(4)
    // 유효자릿수를 넘는 정수는 짤린다.
    System.out.println(f);

    d = i; // int(4) ==> double(8)
    // 유효자릿수 범위의 정수 값이므로 int(32비트) 값을 그대로 저장할 수 있다.
    System.out.println(d);       

    d = l; 
    // 유효 범위를 넘어가는 정수인 경우 짤린다.
    // 주의! 컴파일 오류가 발생하지 않는다.
    System.out.println(d);       
  }
}

// 정리!
// - 정수 메모리의 값(byte, short, char, int, long)을 부동소수점 메모리(float, double)에 저장할 때 주의해서 사용하라!
// - 유효자릿수를 넘어가는 정수 값인 경우 부동소수점 메모리에 저장될 때 짤릴 수 있다.
//   그럼에도 컴파일 오류가 발생하지 않기 때문에 개발자들이 놓치는 경우가 많다!

(5) 형변환

1) 부동소수점 변수 ==> 정수 변수

public class Exam0921 {
  public static void main(String[] args) {
    float f = 3.14f;
    double d = 9876.56789;

    // 부동소수점 메모리의 값을 정수 메모리에 저장할 수 없다.
    // 왜? 
    // - 정수 메모리는 소수점 이하의 값을 저장할 수 없기 때문에
    //   자바에서는 부동소수점 값을 정수 메모리에 저장하는 것을 
    //   문법에서 막는다!
    //    int i = f; // 컴파일 오류!
    //    long l = d; // 컴파일 오류!
  }
}

2) 명시적 형변환

  • 큰 메모리의 값을 작은 메모리로 변환 할 때 또는, 부동소수점을 정수로 변환 할 때 사용한다.
  • 문법 // 변수 = (바꾸고자하는타입) 변수 또는 값;
public class Exam0930 {
  public static void main(String[] args) {

    // 부동소수점 메모리의 값은 정수 메모리에 저장할 수 없다.
    // 그럼에도 저장하려 한다면, 명시적 형변환 문법을 사용해야 한다.

    // 명시적 형변환을 통해 부동소수점의 값을 정수 메모리에 저장할 때,
    // 소수점 이하의 값이 짤린다.

    // 값이 짤릴 수 있음을 알면서도 정수 메모리에 저장해야 할 때가 있다.
    // 또는 큰 메모리의 값을 작은 메모리에 저장해야 할 때가 있다.
    
    // 해결책?
    // - 컴파일러에게 강제로 값을 넣을 것을 명시하라!
    // - 이것을 "명시적 형변환(explicit type conversion)"이라 부른다.
    
    // float ==> int 
    float f = 3.14f;
    int i = (int)f;  // 소수점 이하가 제거된다.
    System.out.println(i); // 3

    // double ==> long
    double d = 9876.56789;
    long l = (long)d; // 소수점 이하가 제거된다.
    System.out.println(l); //9876
  }
}
public class Exam0940 {
  public static void main(String[] args) {

    byte b = 100;
    short s = 100;
    int i = 100;
    long l = 100;

    // 큰 메모리의 값을 작은 메모리에 저장하는 경우=> 컴파일 오류 발생
    // => 작은 메모리에 들어갈 수 있는 값인 경우에 형변환을 해야 한다.

    // 1) 큰 메모리의 값이 작은 메모리에 충분히 들어가는 경우
    // short ==> byte
    byte b2 = (byte)s; // 명시적 형변환
    System.out.println(b2); //100

    // int ==> byte
    b2 = (byte)i; // 명시적 형변환
    System.out.println(b2); //100

    // long ==> byte
    b2 = (byte)l; // 명시적 형변환
    System.out.println(b2); //100

    // 2) 큰 메모리의 값이 작은 메모리에 들어 갈 수 없는 경우
    // => 앞 쪽 바이트의 값이 짤려서 들어간다.
    int i2 = 0b0000_0000_0000_0000_0000_0001_0010_1100; // = 300(10진수)
    b2 = (byte) i2; // 
    System.out.println(b2); // 0b0010_1100 // 44

    l = 400_0000_0000L; // 0x00_00_00_09_50_2f_90_00
    i = (int)l; // 큰 메모리의 값이 작은 메모리에 들어가지 못하는 경우
    System.out.println(l); // 40000000000
    System.out.println(i); // 앞 쪽 바이트가 짤린다. // 1345294336
    System.out.println(0x502f9000); // 1345294336
  }
}
  • 큰 값을 작은 메모리에 넣는 것은 아무런 의미가 없다.

  • 다만, 큰 메모리의 값을 바이트 단위로 쪼개고 싶을 때 유용하다.

3) 명시적 형변환이 불가능한 경우

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

    // 1) 정수 메모리끼리 형변환이 가능하다.
    // 2) 부동소수점을 정수로 형변환이 가능한다.
    // 3) 형변환 없이 정수는 부동소수점 메모리에 저장할 수 있다.
    // 4) 숫자를 문자 코드로 형변환 가능한다.
    // 그 외에는 형변환 불가!

    // 예) 정수, 부동소수점 ==/==> boolean
    boolean bool;
    //    bool = (boolean) 1; // 컴파일 오류!

    // 예) 문자열 ==/==> 정수, 부동소수점, 문자, boolean
    //    boolean v1 = (boolean) "true"; // 컴파일 오류!
    //    char v2 = (char) "가"; // 컴파일 오류!
    //    int v3 = (int) "123"; // 컴파일 오류!
    //    float v4 = (int) "3.14f"; // 컴파일 오류!
  }
}
  • 다만, 특별한 메서드를 사용하면 가능하다.
public class Exam0951 {
  public static void main(String[] args) {

    byte b = Byte.valueOf("100");
    short s = Short.valueOf("32767");
    int i1 = Integer.valueOf("2122223333");
    int i2 = Integer.parseInt("2122223333");
    long l = Long.valueOf("9221112223333444444");
    float f1 = Float.valueOf("3.14f");
    float f2 = Float.parseFloat("3.14f");
    double d = Double.valueOf("987654321");
    boolean bool = Boolean.valueOf("true");
    char c = "가".charAt(0);

    // 전부 "" 씌웠으므로 문자열임

    System.out.println(b); // 100
    System.out.println(s); // 32767
    System.out.println(i1); // 2122223333
    System.out.println(i2); // 2122223333
    System.out.println(l); // 9221112223333444444
    System.out.println(f1); // 3.14
    System.out.println(f2); // 3.14
    System.out.println(d); // 9.87654321E8
    System.out.println(bool); // true
    System.out.println(c); // 가
  }
}

(5) 문자열을 primitive type (byte, short, int, long ... 등 8개) 으로 변환하는 방법

  • 웹브라우저가 보내는 값은 항상 문자열이고(Query String 등), 파일 업로드의 경우 바이너리 데이터이다.

  • 스프링부트에서는 문자열을 기존에 자바에서 제공하는 변환 기능에 더하여, 실전에서 유용한 변환기능을 더해 자동으로 변환해준다.

※Wrapper Class : 기본 타입의 데이터를 객체로 표현해야 할 때 사용하는 클래스.

(6) 이클립스와 스프링부트 - 실행되는 순서

1) 사용자가 이클립스를 실행한다.

2) 이클립스를 실행하면, 이클립스가 JVM을 실행시키고 JVM이 이클립스 IDE의 메인 클래스를 실행시킨다.

3) App.class(메인 클래스)를 실행하면, JVM이 App.class 실행 통해 스프링부트 실행시키고, 이게 톰캣 서버를 실행시킨다.

  • 이클립스와 스프링부트는 별개의 프로그램이므로, 각각 실행되는 JVM은 별개의 프로그램으로 생각하면 편하다.

(7) 이클립스와 스프링부트 - HTML 파일과, JAVA 파일이 실행되는 순서

profile
끝없는 대양에서의 항해를 위해

0개의 댓글