자바의 정석 2장 (1) 변수 (2) 변수의 타입

YeongJun Son·2023년 4월 6일
0

자바의 정석

목록 보기
2/2

1. 변수

1.1 변수란?

변수 개념

값을 저장할 수 있는 메모리 상의 공간 → “단 하나의 값”

1.2 변수의 선언과 초기화

변수의 초기화

  • int age; — 변수 타입과 변수 이름
  • 초기화(initialization) 메모리는 여러 프로그램이 공유하는 자원이므로 전에 다른 프로그램에 의해 저장된 ‘알 수 없는 값(쓰레기값, garbage value)’이 남아있을 수 있기 때문
  • 대입 연산자 ‘=’을 사용 지역 변수는 사용되기 전에 초기화를 반드시 해야하지만, 클래스 변수와 인스턴스 변수는 초기화 생략 가능
  • 초기화는 변수를 사용하기 전에 처음으로 값을 저장하는 것

두 변수의 값 교환하기

int x = 10;
int y = 20;
int tmp;
  • tmp를 임시 저장소로 사용

1.3 변수의 명명규칙

식별자

  • 식별자(identifier): 프로그래밍에서 사용하는 모든 이름 → 서로 구분될 수 있어야 함

  • 명명 규칙

    1. 대소문자가 구분되며, 길이에 제한이 없다

    2. 예약어를 사용해서는 안 된다 (구문 사용 단어)

    3. 숫자로 시작해서는 안 된다

    4. 특수문자는 ‘_’와 ‘$’만을 허용한다.

  • 코딩 컨벤션

    1. 클래스 이름의 첫 글자는 항상 대문자로 한다

      → 변수와 메서드의 이름 첫 글자는 항상 소문자로 한다

    2. 여러 단어로 이루어진 이름은 단어의 첫 글자를 대문자로 한다

      ex) lastIndexOf, StringBuffer

    3. 상수의 이름은 모두 대문자로 한다. 여러 단어로 이루어진 경우 ‘_’로 구분한다

      ex) PI, MAX_NUMBER

  • ‘의미 있는 이름’ ← 변수의 선언문에 주석으로 정보를 주는 것도 좋다

2. 변수의 타입

자료형

  • 자료형(data type): 값이 저장될 크기와 저장형식을 정의 → 문자형, 정수형, 실수형, …

기본형과 참조형

  • 기본형 변수: 실제 값(data)을 저장 ↔ 참조형 변수: 값이 저장된 주소(memory address)를 값으로 가짐
  • 자바는 참조형 변수 간의 연산을 할 수 없으므로 연산에 사용 되는 건 모두 기본형 변수
    1. 기본형: 논리형, 문자형, 정수형, 실수형
    2. 참조형: 나머지 타입
  • 새로운 클래스 — 새로운 참조형 (변수의 타입으로 클래스 이름 사용)
    → 참조형 변수는 null 또는 객체의 주소를 값으로 가짐
    → 참조형은 항상 ‘객체의 주소’를 저장하므로 ‘type’ (> ‘data type’)

2.1 기본형(primitive type)

논리형, 문자형, 정수형, 실수형

  • int → CPU가 가장 효율적으로 처리할 수 있는 타입
  • byte, short → 효율적인 실행보다 메모리 절약

기본 자료형의 종류와 크기

Fig 1. Java 기본 자료형의 값 범위 및 크기

각 타입의 변수가 저장할 수 있는 값의 범위

  • 정수형의 경우, ‘-2^(n-1) ~ 2^(n-1)-1’ (n은 비트수)를 범위로 가짐
  • 실수형은 정수형과 저장형식이 달라 같은 크기라도 훨씬 큰 값을 표현 가능 → 그러나 오차가 발생할 수 있음 (정밀도가 높을수록 오차범위 줄어듦) → float: 정밀도 7자리, double: 정밀도 15자리 → 10진수로 정밀도 X 자리의 수를 오차 없이 저장할 수 있다

2.2 상수와 리터럴 (constant and literal)

상수

  • 상수(constant): 한 번 값을 저장하면 다른 값으로 변경할 수 없음 + 선언과 동시에 초기화

리터럴

  • 그 자체로 값을 의미하는 것 ← 변수에 값을 대입할 때, 대입하는 바로 그 값이 리터럴

상수가 필요한 이유

  • 리터럴에 ‘의미있는 이름’을 붙여서 코드의 이해와 수정을 쉽게 만든다

리터럴의 타입과 접미사

Fig 2. 타입 종류에 따른 리터럴과 접미사
  • 변수의 타입은 저장될 ‘값의 타입’에 의해 결정됨
  • JDK1.7부터 정수형 리터럴의 중간에 구분자 ‘_’를 넣을 수 있게 되어서 큰 숫자를 편하게 읽을 수 있게 됨
long big = 100_000_000_000L;
long hex = 0xFFFF_FFFF_FFFF_FFFL;
float pi = 3.14f; // float pi = 3.14; <- Error!
double rate = 1.618d;
  • 접두사 ‘0x’, ‘0X’: 16진수 / ‘0’: 8진수
  • 실수형 리터럴인데, 접미사가 없으면 double 타입 리터럴
  • 소수점이나 10의 제곱을 나타내는 기호 E 혹은 e, 접미사 f, F, d, D를 포함하면 실수형 리터럴
  • 잘 쓰이지는 않지만, 기호 p를 이용해 실수 리터럴을 16진 지수형태로 표현 가능 → p는 2의 제곱을 의미: p의 왼쪽에는 16진수, 오른쪽에는 10진 정수

타입의 불일치

int i = 'A';
long l = 123;
double d = 3.14f;

int i = 0x123456789; // 에러. int값 범위 넘음
float f = 3.14; // 에러. float 범위 < double 범위
  • 타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용됨 → 그러나 리터럴의 값이 변수의 타입을 넘어서간, 리터럴의 타입이 범위가 더 넓으면 에러 → byte와 short 타입은 리터럴 따로 존재 X: 범위 내에서 int 타입의 리터럴 사용
  • double 타입은 float 타입의 변수에 저장할 수 없음

문자 리터럴과 문자열 리터럴

String str = ""; // OK. 내용이 없는 빈 문자열
char   ch  = ''; // 에러. '' 안에 반드시 하나 필요
char   ch  = ' '; // OK. 공백 문자로 변수 초기화.
  • 문자 리터럴 = 문자 하나, 문자열 = 문자 둘 이상 → 문자열 리터럴은 “”안에 아무런 문자 넣지 않는 것 허용(empty string) → 반면, 문자 리터럴은 ‘’안에 하나의 문자가 있어야 함.
  • 원래 스트링은 클래스이므로 객체 생성 연산자 new를 사용해야 하지만, 특별히 위 표현 허용
  • 추가적으로, 스트링은 덧셈연산자를 이용해 문자열 결합 가능 (왼쪽 → 오른쪽 진행) 피연산자중 어느 한 쪽이 String 이면 나머지 한 쪽을 먼저 String으로 변환한 다음 두 String 결합 → 기본형 타입의 값을 문자열로 변환할 때는 아무런 내용도 없는 빈 문자열을 더하기

2.3 형식화된 출력 - printf()

println()과 printf()의 차이

  • println()은 사용하기엔 편하지만 변수의 값을 그대로 출력 → 값을 변환하지 않고는 출력 X ↔ printf()는 지시자(specifier)를 통해 변수의 값을 여러가지 형식으로 변환하여 출력 → 정수형 변수에 저장된 값을 십진수로 변형할 때는 %d를 사용 → 출력될 값과 지시자의 개수 및 순서는 일치해야 함
  • printf()는 줄바꿈을 하지 않는다 → 지시자 %n을 따로 넣어줘야 한다 (\n보다 안전)

printf()의 지시자

Fig 3. printf() 지시자
  • 정수를 출력할 때는 지시자 %d를 사용하는데, 출력될 값이 차지할 공간을 숫자로 지정 가능 → 간격 맞춰 출력할 때 필수
  • 정수 출력 예시
    1. ‘%5d’ → 5자리 차지, 우측 정렬, 나머지 빈 공간

    2. ‘%-5d’ → 5자리 차지, 좌측 정렬, 나머지 빈 공간

    3. ‘%0d’ → 5자리 차지, 우측 정렬, 나머지 0

    4. 지시자 ‘%x’와 ‘%o’에 ‘#’을 사용하면 접두사 ‘0x’와 ‘0’이 각각 붙는다

      → 그리고 ‘%X”는 16진수 사용 접두사와 영문자를 대문자로 출력한다

  • 10진수를 2진수로 출력해주는 지시자는 없기에, 정수를 2진 문자열로 변환해주는 ‘Integer.toBinarySTring(int i)’를 사용해야 한다 → 정수를 2진수로 변환해서 문자열로 반환하므로 지시자 ‘%s’를 사용
  • C언어에서는 char 타입의 값을 지시자 ‘%d’로 출력할 수 있지만, 자바에서는 허용되지 않는다
    System.out.printf("c=%c, %d %n", c, (int)c); // 형변환이 꼭 필요하다
    → int 타입으로 형변환해야만 ‘%d’로 출력할 수 있다.
  • %f는 기본적으로 소수점 아래 6자리까지만 출력. 따라서 소수점 아래 7자리에서 반올림.
    System.out.printf("d = %14.10f%n", d); 
    // 전체 14자리 중 소수점 아래 10자리, 소수점 아래 빈 자리는 모두 0, 정수의 빈자리는 공백
    System.out.printf("d = %014.10f%n", d); 
    // 전체 14자리 중 소수점 아래 10자리, 소수점 아래와 정수부 양쪽 빈자리를 모두 0으로 채움
    → 소수점 아래의 자리수를 지정할 수도 있다
  • 지시자 ‘%s’도 숫자를 추가하면 원하는 만큼의 출력 공간 확보 혹은 문자열 일부 출력 가능 ‘%’ : 포맷 문자열 시작 ‘.’ 왼쪽의 수: 필드의 최소 너비 지정 ‘.n’: 최대 문자열 길이 지정 (n=숫자) ‘s’: 문자열
    System.out.printf("[%s]%n",    url); // 문자열의 길이만큼 출력공간 확보
    System.out.printf("[%20s]%n",  url); // 최소 20글자 출력공간 확보. (우측 정렬)
    System.out.printf("[%-20s]%n", url); // 최소 20글자 출력공간 확보. (좌측 정렬)
    System.out.printf("[%.8s]%n",  url); // 왼쪽에서 8글자만 출력
    System.out.printf("[%8.8s]%n", url); // 오른쪽에서 8글자만 출력
    

2.4 화면에서 입력받기 - Scanner

Scanner 클래스 이용 전

  • 최신 방법은 JDK 1.6 부터 추가된 Console 클래스를 이용 → IDE에서 잘 동작하지 않으므로 Scanner 클래스 이용

Scanner 클래스 이용 과정

import java.util.*

Scanner scanner = new Scanner(System.in); // Scanner 클래스의 객체를 생성
String input = scanner.nextLine(); // 입력 받은 내용을 input에 저장
int num = Integer.parseInt(input); // 입력받은 내용을 input 타입의 값으로 변환

// 입력받은 문자열을 숫자로 변환하려면 Integer.parseInt() 이용 (string -> int)
// 입력받은 문자열을 정수로 변환하려면 Float.parseFloat() 이용 (string -> float)
  • 사실 스캐너 클래스에는 nextInt()나 nextFloat()와 같이 변환 없이 숫자로 바로 입력받을 수 있는 메서드도 있음
    import java.util.*;
    
    class ScannerEx {
    	public static void main(String[] args) {
    		Scanner scanner = new Scanner(System.in);
    
    		System.out.print("두자리 정수를 하나 입력해주세요.>");
    		String input = scanner.nextLine();
    		int num = Integer.parseInt(input); // 입력받은 문자열을 숫자로 변환
    
    		System.out.println("입력내용 :"+input);
    		System.out.printf("num=%d%n", num);
    		}
    }
    → 그러나 연속적으로 값을 입력 받아 사용하기에 까다롭다 → 모든 값을 nextLine()으로 입력받아 적절히 변환하는 게 낫다 → 숫자가 아닌 문자 또는 기호를 입력하면, 에러 발생 (공백 입력 주의!)
profile
제가 좋아하는 것은 도가 아니라 기입니다

0개의 댓글