중간고사 대비 java 2단원 정리

목차

자바 2단원 변수에 관한 내용이다.

1. 변수

프로그램은 변수를 통해 메모리의 특정 번지에 값을 저장하고 읽을 수 있다. 우리는 변수를 선언하고, 변수에 값을 저장하고, 변수에 저장된 값을 읽어서 사용할 수 있다. 이때 구체적인 메모리를 다루는 부분은 JVM이 담당한다.

1.1 변수의 선언과 초기화

변수 사용을 위해선 변수를 선언해야 한다. 변수를 선언하는 방법은 다음과 같다. 저장되는 값의 종류와 변수명을 프로그램에 알려 주는 것이다.

[타입] [변수명]
int age;
[타입] [변수명]
int age;
[타입] [변수명]
int age;
[타입] [변수명]
int age;

이때 자바에서 지역 변수의 경우 초기화 없이는 사용이 불가능하다. 반면 클래스 멤버 변수, static 변수는 초기화가 없어도 타입에 따라 기본값이 대입되는 경우가 있다. 당분간은 메소드 내의 지역 변수만 사용할 것이므로 이 경우 초기화 없이는 사용이 불가능하다.

package study;

public class Hello {
  public static void main(String[] args){
    int x;
    /* main 내의 지역변수 x는 아직 초기화가 안 되었으므로 아래 코드는 오류가 발생한다.
    The local variable x may not have been initialized 오류 발생
    */
    System.out.println(x);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int x;
    /* main 내의 지역변수 x는 아직 초기화가 안 되었으므로 아래 코드는 오류가 발생한다.
    The local variable x may not have been initialized 오류 발생
    */
    System.out.println(x);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int x;
    /* main 내의 지역변수 x는 아직 초기화가 안 되었으므로 아래 코드는 오류가 발생한다.
    The local variable x may not have been initialized 오류 발생
    */
    System.out.println(x);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int x;
    /* main 내의 지역변수 x는 아직 초기화가 안 되었으므로 아래 코드는 오류가 발생한다.
    The local variable x may not have been initialized 오류 발생
    */
    System.out.println(x);
  }
}

값을 대입해서 초기화해준 후에야 사용 가능해진다.

package study;

public class Hello {
  public static void main(String[] args){
    int x;
    /* x의 값을 초기화한다 */
    x=1;
    System.out.println(x);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int x;
    /* x의 값을 초기화한다 */
    x=1;
    System.out.println(x);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int x;
    /* x의 값을 초기화한다 */
    x=1;
    System.out.println(x);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int x;
    /* x의 값을 초기화한다 */
    x=1;
    System.out.println(x);
  }
}

1.2 변수 사용 범위

자바의 모든 변수는 중괄호 블럭 내에서 선언되고 사용된다. 이때 메소드 블럭 내에서 선언된 변수를 로컬 변수라고 부른다. 로컬 변수는 선언된 메서드 블럭 내에서만 사용할 수 있다. 블럭을 벗어나면 변수는 소멸된다.

이런 것은 다른 변수에 대해서도 마찬가지인데 java의 변수는 자신이 선언된 블럭 내에서만 사용할 수 있다. 예를 들어서 다음과 같은 코드는 x가 선언된 블럭 내에서만 사용할 수 있기 때문에 오류가 발생한다.

package study;

public class Hello {
  public static void main(String[] args){
    {int x;}
    /* 중괄호를 벗어나서는 x에 접근할 수 없기 때문에 오류 */
    x=1;
    System.out.println(x);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    {int x;}
    /* 중괄호를 벗어나서는 x에 접근할 수 없기 때문에 오류 */
    x=1;
    System.out.println(x);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    {int x;}
    /* 중괄호를 벗어나서는 x에 접근할 수 없기 때문에 오류 */
    x=1;
    System.out.println(x);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    {int x;}
    /* 중괄호를 벗어나서는 x에 접근할 수 없기 때문에 오류 */
    x=1;
    System.out.println(x);
  }
}

2. 기본 타입

자바에서는 기본 타입(primitive type)으로 다음과 같은 타입을 제공한다. 만약 표기할 수 있는 것 이상의 값을 입력하면 컴파일 에러가 된다.

  • 정수 타입
    • byte : 1바이트, -128~127
    • char : 2바이트, 0~65535
    • short : 2바이트, -32768~32767
    • int : 4바이트, -2147483648~2147483647
    • long : 8바이트, -9223372036854775808~9223372036854775807
  • 실수 타입
    • float : 4바이트, 1.4E-45~3.4028235E38
    • double : 8바이트, 4.9E-324~1.7976931348623157E308
  • 논리 타입
    • boolean

2.1 리터럴

2.1.1 정수 리터럴

프로그래머에 의해 직접 입력된 값을 리터럴이라고 부른다. 이때 정수는 여러 형태의 입력이 가능하다.

2진수는 0b, 0B로 시작한다. 예를 들어 0b1010은 10진수로 10을 의미한다. 만약 0b로 시작하는 리터럴인데 0,1이 아닌 다른 숫자가 들어 있을 경우 컴파일 에러이다.

8진수는 0으로 시작한다. 예를 들어 010은 10진수로 8을 의미한다. 만약 0으로 시작하는 리터럴인데 0~7이 아닌 다른 숫자가 들어 있을 경우 컴파일 에러이다.

16진수는 0x, 0X로 시작한다. 예를 들어 0x10은 10진수로 16을 의미한다. 만약 0x로 시작하는 리터럴인데 09, af, A~F가 아닌 다른 숫자가 들어 있을 경우 컴파일 에러이다.

10진수는 그냥 숫자를 입력하면 된다. 당연하지만 10은 10진수로 10을 의미한다.

또한 리터럴에는 언더바(_)를 사용할 수 있다. 이는 가독성을 높이기 위해 사용한다. 예를 들어 1_000_000은 100만을 의미한다.

이때 주의할 점은, 컴파일러는 정수 리터럴을 기본적으로 int로 인식한다는 것이다. 따라서 int타입 범위를 넘어서는 값의 리터럴을 변수에 대입하려고 하면 변수가 long 형이라도 에러가 발생한다. 만약 long 타입의 리터럴을 입력하고 싶다면 숫자 뒤에 L, l을 붙여야 한다. 예를 들어 10000000000L은 100억을 의미한다.

2.1.2 문자 리터럴

문자 리터럴은 작은 따옴표(')로 묶어서 표현한다. 예를 들어 'A'는 문자 A를 의미한다. 이때 문자 리터럴은 2바이트의 유니코드로 저장된다. 따라서 문자 리터럴은 065535(02^16-1)의 범위를 가진다.

유니코드는 정수이므로 char도 정수 타입이고 따라서 정수 리터럴을 대입할 수 있다. 예를 들어 65는 'A'를 의미한다. 44032는 '가'를 의미한다.

이때 문자 리터럴은 유니코드로 변환되기 때문에 다른 정수 타입에도 저장할 수 있다. 물론 변수 타입에 따라 출력값은 다르게 나온다.

package study;

public class Hello {
  public static void main(String[] args){
    int x='가';
    char y='가';
    /* x의 값을 초기화한다 */
    System.out.println(x); //44032 출력
    System.out.println(y); //가 출력
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int x='가';
    char y='가';
    /* x의 값을 초기화한다 */
    System.out.println(x); //44032 출력
    System.out.println(y); //가 출력
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int x='가';
    char y='가';
    /* x의 값을 초기화한다 */
    System.out.println(x); //44032 출력
    System.out.println(y); //가 출력
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int x='가';
    char y='가';
    /* x의 값을 초기화한다 */
    System.out.println(x); //44032 출력
    System.out.println(y); //가 출력
  }
}

2.2 String type

그런데 문자를 저장하는 char 타입으로는 단어 하나도 표현할 수 없다. 문자 하나만 저장할 수 있으니까. 이럴 때 등장하는 게 String 타입이다. 기본 타입은 아니지만 자주 사용하므로 여기서 다룬다. 물론 문자열 타입의 다양한 기능에 대해서는 후에 다루게 될 것이다..타입 소개만 하고 넘어간다.

String은 문자열을 저장하는 타입이다. 문자열 리터럴은 큰 따옴표(")로 묶어서 표현한다. 예를 들어 "Hello"는 문자열 Hello를 의미한다. 작은따옴표는 문자 리터럴을 표현할 때 사용하는데 헷갈리지 않게 주의하자.

package study;

public class Hello {
  public static void main(String[] args){
    String word="저는 마녀입니다.";
    System.out.println(word);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    String word="저는 마녀입니다.";
    System.out.println(word);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    String word="저는 마녀입니다.";
    System.out.println(word);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    String word="저는 마녀입니다.";
    System.out.println(word);
  }
}

2.3 실수 타입

자바에서는 float, double 2가지의 실수 타입을 제공한다. float은 4바이트, double은 8바이트이다. float은 소수점 7자리까지, double은 소수점 15자리까지 표현할 수 있다. 메모리에 실제로 저장될 때는 IEEE 754 표준에 따라 저장된다. 이 표준에 대해서는 컴퓨터시스템 등의 과목에서 다루게 된다.

또한 실수 리터럴은 기본적으로 double 타입이다. 따라서 실수 리터럴은 double 타입에 저장해야 한다. float 타입의 실수 리터럴을 사용하고 싶다면 뒤에 f를 붙여서 표현한다. 예를 들어 3.14는 double 타입의 실수 리터럴이고 3.14f는 float 타입의 실수 리터럴이다.

또는 5e2 처럼 지수와 가수로 표현된 10진수 실수도 사용할 수 있다. 이 경우 5e2는 5 * 10^2 = 500을 의미한다.

2.4 논리 타입

참, 거짓을 뜻하는 boolean 타입도 자바에서 기본 타입으로 제공한다. 1byte 크기의 메모리를 사용하며 true, false 두 가지 값만 가질 수 있다. boolean 타입의 변수는 주로 if문, while문, for문 등에서 조건식으로 사용된다.

3. 타입 변환

자바에서는 다른 타입의 값을 저장할 때 타입 변환이 필요하다. 예를 들어 int 타입의 값을 long 타입의 변수에 저장하려면 int 타입의 값을 long 타입으로 변환해야 한다. 이러한 타입 변환은 자동으로 이루어지기도 하고, 명시적으로 이루어지기도 한다.

3.1 자동 타입 변환

자동 타입 변환은 작은 크기의 타입을 큰 크기의 타입에 저장할 때 일어난다. 예를 들어 int 타입의 값을 long 타입의 변수에 저장하면 자동으로 int 타입의 값이 long 타입으로 변환된다. int 타입이 가질 수 있는 모든 값을 long 변수에 담을 수 있기 때문에 문제가 없다.

자동 타입 변환은 다음과 같은 규칙을 따른다.

  • byte, short, char 타입은 int 타입으로 변환된다.
  • int 타입은 long 타입으로 변환된다.
  • long 타입은 float 타입으로 변환된다.
  • float 타입은 double 타입으로 변환된다.

특히 정수 타입이 실수 타입으로 저장될 경우 무조건 자동 타입 변환이 일어난다. 또한 주의할 점이 char보다 허용 범위가 작은 byte 타입은 char 타입으로 자동 변환될 수 없다. char타입은 음수를 포함하지 않는 정수 타입이기 때문이다.(byte는 -128~127까지 표현 가능)

3.2 강제 타입 변환

큰 크기의 타입을 작은 크기의 타입에 저장하려면 강제 타입 변환이 필요하다. 강제 타입 변환은 다음과 같이 작성한다.

[작은 허용 범위 타입 변수]=([작은 허용 범위 타입]) [큰 허용 범위 타입 변수] 형식으로 쓴다.
byte b=(byte)a;
[작은 허용 범위 타입 변수]=([작은 허용 범위 타입]) [큰 허용 범위 타입 변수] 형식으로 쓴다.
byte b=(byte)a;
[작은 허용 범위 타입 변수]=([작은 허용 범위 타입]) [큰 허용 범위 타입 변수] 형식으로 쓴다.
byte b=(byte)a;
[작은 허용 범위 타입 변수]=([작은 허용 범위 타입]) [큰 허용 범위 타입 변수] 형식으로 쓴다.
byte b=(byte)a;

실수 타입을 정수 타입으로 변환할 때는 소수점 이하의 값이 잘린다. 예를 들어 double 타입의 값을 int 타입의 변수에 저장하면 소수점 이하의 값이 잘려서 저장된다.

3.3 연산에서의 자동 타입 변환

정수 타입 변수가 산술 연산자의 피연산자로 쓰이면 int보다 작은 범위를 갖는 byte, short 타입 변수는 int 타입으로 자동 변환된다. 따라서 다음과 같은 코드는 에러가 발생한다.

package study;

public class Hello {
  public static void main(String[] args){
    byte a=10, b=20;
    /* a+b 는 int형으로 자동 변환되어 계산되기 때문에
    이를 byte형에 대입하려 하면 에러 발생 */
    byte c=a+b;
    System.out.println(c);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    byte a=10, b=20;
    /* a+b 는 int형으로 자동 변환되어 계산되기 때문에
    이를 byte형에 대입하려 하면 에러 발생 */
    byte c=a+b;
    System.out.println(c);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    byte a=10, b=20;
    /* a+b 는 int형으로 자동 변환되어 계산되기 때문에
    이를 byte형에 대입하려 하면 에러 발생 */
    byte c=a+b;
    System.out.println(c);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    byte a=10, b=20;
    /* a+b 는 int형으로 자동 변환되어 계산되기 때문에
    이를 byte형에 대입하려 하면 에러 발생 */
    byte c=a+b;
    System.out.println(c);
  }
}

단, 정수형 변수끼리의 연산이라고 무조건 int타입으로 변환되는 건 아니다. 두 피연산자 중 허용범위가 큰 쪽으로 변환되어 연산을 수행한다. 예를 들어 long타입이 피연산자로 사용되면 두 피연산자 모두 long으로 변환되어 연산이 수행된다.

이는 자동 타입 변환에서의 관계와 동일하다. 실수끼리의 연산, 실수와 정수 사이 연산에서도 같다. 피연산자가 각각 float, double타입이면 다른 피연산자도 double로 자동 타입 변환되고 int와 double간 연산에서도 double로 둘 다 변환된다.

3.4 연산에서의 강제 타입 변환

정수끼리의 나눗셈을 하는데 이 결과가 실수형으로 나오게 하고 싶을 수 있다. 예를 들어서 1을 2로 나눈 결과값은 0.5가 맞다. 하지만 피연산자가 둘 다 int형이면 0이 나온다.

package study;

public class Hello {
  public static void main(String[] args){
    int a=1, b=2;
    System.out.println(a/b);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int a=1, b=2;
    System.out.println(a/b);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int a=1, b=2;
    System.out.println(a/b);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int a=1, b=2;
    System.out.println(a/b);
  }
}

이를 해결하기 위해 강제 타입 변환을 사용한다. 두 피연산자 중 적어도 하나를 double로 변환하면 결과값도 double이 된다.

package study;

public class Hello {
  public static void main(String[] args){
    int a=1, b=2;
    System.out.println((double)a/b);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int a=1, b=2;
    System.out.println((double)a/b);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int a=1, b=2;
    System.out.println((double)a/b);
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int a=1, b=2;
    System.out.println((double)a/b);
  }
}

3.5 문자열 자동 타입 변환

문자열과 다른 타입의 변수를 + 연산자로 연결하면 문자열로 변환된다. 이를 문자열 자동 타입 변환이라고 한다.

package study;

public class Hello {
  public static void main(String[] args){
    int a=123;
    String word="witch";
    System.out.println(a+word); //123witch 출력
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int a=123;
    String word="witch";
    System.out.println(a+word); //123witch 출력
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int a=123;
    String word="witch";
    System.out.println(a+word); //123witch 출력
  }
}
package study;

public class Hello {
  public static void main(String[] args){
    int a=123;
    String word="witch";
    System.out.println(a+word); //123witch 출력
  }
}

단 이런 자동 타입 변환은 두 피연산자에 대해서만 적용되기 때문에 연산 순서가 중요하다. 자바의 덧셈은 왼쪽에서 오른쪽으로 진행된다. 따라서 123+456+"witch" 와 같은 연산식의 경우 123+456이 먼저 수행된 후 579witch가 된다. 반대로 "witch"+123+456의 경우 witch123456이 된다. 만약 특정 부분을 먼저 연산하고 싶은 경우 괄호를 쓰자.

3.6 문자열을 기본 타입으로 변환

문자열을 기본 타입으로 변환하는 것을 문자열을 기본 타입으로 파싱한다고 한다. 문자열을 기본 타입으로 변환하는 방법은 각각의 기본 타입에 해당하는 클래스의 parseXXX() 메소드를 사용하면 된다. 예를 들어서 정수형 문자열을 int형으로 변환하고 싶으면 Integer.parseInt() 메소드를 사용하면 된다.

  • Byte.parseByte() : 정수형 문자열을 byte형으로 변환
  • Short.parseShort() : 정수형 문자열을 short형으로 변환
  • Integer.parseInt() : 정수형 문자열을 int형으로 변환
  • Long.parseLong() : 정수형 문자열을 long형으로 변환
  • Float.parseFloat() : 실수형 문자열을 float형으로 변환
  • Double.parseDouble() : 실수형 문자열을 double형으로 변환
  • Boolean.parseBoolean() : 논리형 문자열("true", "false")을 boolean형으로 변환

만약 문자열이 기본 타입으로 변환할 수 없는 문자열(예를 들어 "abc"는 기본 타입으로 변환할 수 없다. 16진수형태인 "0xabc"와 같은 것도 안된다)이라면 NumberFormatException이 발생한다.

반대로 기본 타입의 값을 String형으로 변경하고 싶을 땐 String.valueOf() 메소드를 사용하면 된다.

참고

변수의 초기화 관련 https://stackoverflow.com/questions/19131336/default-values-and-initialization-in-java


```

```