Programming Language/Java

[Java] 04. 변수

lumana 2024. 3. 12. 22:16

변수


  • 단 하나의 값을 저장할 수 잇는 메모리 공간

  • 지역변수는 사용되기 전에 초기화를 반드시 해야 함

  • 클래스변수와 인스턴스변수는 초기화를 생략할 수 있다

변수의 명명규칙

  • 변수의 이름처럼 프로그래밍에서 사용되는 모든 이름을 '식별자(identifier)'라고 함

  • 식별자는 같은 영역 내에서 서로 구분(식별)될 수 있어야 한다.

  • 식별자를 만들 때는 다음과 같은 규칙을 지켜야 함

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

    • 예약어(a.k.a. keyword, reserved word)를 사용해서는 안 된다(ex. true는 불가능, True는 가능)

      • 클래스나 변수, 메서드의 이름으로 예약어를 사용할 수 없다
    • 숫자로 시작해서는 안 된다

    • 특수문자는 '_'와 '$' 만을 허용한다

  • 프로그래머들에게 권장하는 암묵적인 규칙(not mandatory)

    • 클래스 이름의 첫 글자는 항상 대문자로

    • 여러 단어로 이루어진 이름은 단어의 첫 글자를 대문자로

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

    • 용도를 알기 쉽게 '의미있는 이름'으로

변수의 타입

  • 자료형은 크게 '기본형'과 '참조형' 두 가지로 나뉨

  • 기본형 변수는 실제 값(data)를 저장

  • 참조형 변수는 '어떤 값이 저장되어 있는 주소'를 값으로 갖는다

  • 자바는 C와 달리 참조형 변수 간의 연산이 불가능

참조형 변수

  • 참조형 변수를 선언할 대는 변수의 타입으로 클래스의 이름을 사용하므로, 클래스의 이름이 참조변수의 타입이 된다.

    • 새로운 클래스를 작성한다는 것은 새로운 참조형을 추가하는 셈이다.
    클래스이름 변수이름; // 변수의 타입이 클래스 이름인 것들은 모두 참조변수
    • 변수이름 앞에 타입을 적어 참조변수를 선언한다
    Date today = new Date(); // Date 객체를 생성해서, 그 주소를 today에 저장
    • 객체를 생성하는 연산자 new의 결과는 생성된 객체의 주소임

    • 이 주소가 today 참조변수에 저장됨

기본형

  • 논리형 : boolean(1byte, C++에선 bool)

  • 문자형 ; char(2byte)

  • 정수형 : byte(1byte), short(2byte), int(4byte), long(8byte)

  • 실수형 : float(4byte), double(8byte)

    • float의 정밀도 : 7자리

    • double의 정밀도 : 15자리

상수와 리터럴

상수

  • 상수(constant)는 변수와 마찬가지로 '값을 저장할 수 있는 공간'이지만, 변수와 달리 한 번 갓을 저장하면 다른 값으로 변경할 수 없음

  • 변수의 타입 앞에 키워드 'final'을 붙여 줌으로써 상수를 선언한다

final int MAX_SPEED = 10; // 상수 MAX_SPEED의 선언
  • 상수는 반드시 선언과 동시에 초기화 해야 함

리터럴

  • 원래 12, 13, 123, 'A'와 같이 자체로 값을 의미하는 것이 '상수'인데, 프로그래밍에서 상수를 위와 같이 정의함

    • 이를 구분하기 위해 리터럴이라는 용어를 사용한다
  • 리터럴에도 타입이 존재하고, 리터럴에 접미사를 붙여서 타입을 구별한다

    • 정수형의 경우, long 타입의 리터럴에 접미서 'l' 또는 'L'을 붙이고, 접미사가 없으면 int 타입 리터럴이다

    • 16진수의 경우 접두사 '0x' 또는 '0X'을, 8진수의 경우 '0'을 붙인다. (2진수는 0b, .....)

    • JDK1.7부터 정수형 리터럴의 중간에 구분자'_'를 넣을 수 있게 되서 큰 수자를 편하게 읽을 수 있다.

    • 실수형에서 float 타입의 리터럴에는 접미사 'f' 또는 'F'를 붙이고, double탕입의 리터럴에는 접미사 'd' 또는 'D'를 붙인다.

    • double이 기본 자료형이기 때문에 접미사d를 생략하면 double타입 리터럴이다

    float pi = 3.14; // 에러
    double rate = 1.618; // 가능(접미사 d를 생략한 case)
  • 리터럴에 소수점이나 10의제곱을 나타내는 기호 E 또는 e, 그리고 f, F, d, D를 포함하고 있으면 실수형 리터럴로 간주한다.

타입의 불일치

  • 타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용된다
int i = 'A'; // 가능
long l = 123; // 가능
double d = 3.14f; // 가능
  • 리터럴의 값이 변수의 타입의 범위를 넘어서거나, 리터럴의 타입이 변수의 타이보다 저장범위가 넓으면 컴파일 에러 발생
int i = 0x123456789; // 에러 (int 타입의 범위 초과)
float f = 3.14; // 에러 (float타입보다 double 타입의 범위가 넓음)
  • byte와 short타입의 리터럴은 따로 존재 X --> int 타입의 리터럴을 사용
byte b = 65; // 가능 (byte 타입에 저장 가능한 범위의 int타입 리터널)
short s = 0x1234; // 가능 (short 타입에 저장 가능한 범위의 int타입 리터널)

문자 / 문자열 리터럴

  • 문자열 리터럴은 ""안에 아무런 문자도 넣지 않는 것을 허용함

  • 문자 리터를은 반드시 ''안에 하나의 문자가 있어햐 한다

    • String은 클래스 이므로 String str = ";와 같은 표현이 불가능 할 것 같지만 이와 같은 표현도 허용한다
    String str = ""; // 가능
    String name = new String("Java"); // String 객체 생성
    • 덧셈 연사자를 이용하여 문자열을 결합할 수 있다
    String name = "Ja" + "Va";
    String str = name + 8.0;
    
    문자열 + any type -> 문자열 + 문자열 -> 문자열
    any type + 문자열 -> 문자열 + 문자열 -> 문자열

형식화된 출력 - printf()

  • System.out.printf()를 통해 원하는 형식에 맞춰 출력 가능 (c와 유사)

  • println()과 달리 출력 후 줄바꿈을 하지 않음

    • 지시자 %n(==\r\n) 또는 \n을 따로 넣어줘야 한다
  • 예제 코드

class PrintfEx1 {
    public static void main(String[] args) {
        byte b = 1;
        short s = 2;
        char c = 'A';

        int finger = 10;
        long big = 100_000_000_000L;    //long big = 100000000000L;
        long hex = 0xFFFF_FFFF_FFFF_FFFFL;

        int octNum = 010;                // 8진수 10, 10진수로는 8
        int hexNum = 0x10;                // 16진수 10, 10진수로는 16
        int binNum = 0b10;                // 2진수 10, 10진수로는 2

        System.out.printf("b=%d%n", b);
        System.out.printf("s=%d%n", s);
        System.out.printf("c=%c, %d%n", c, (int)c);
        System.out.printf("finger=[%5d]%n", finger);
        System.out.printf("finger=[%-5d]%n", finger);
        System.out.printf("finger=[%05d]%n", finger); // 남은 공간을 0으로 채워줌
        System.out.printf("big=%d%n", big);
        System.out.printf("hex=%#x%n", hex);    // '#'은 접두사 (16진수 0x, 8진수 0)
        System.out.printf("octNum=%o, %d%n", octNum, octNum);
        System.out.printf("hexNum=%x, %d%n", hexNum, hexNum);
        // 10진수를 2진수로 출력해주는 지시자가 없기 때문에 2진 문자열로 변경한 후 문자열로 출력해야 함
        System.out.printf("bigNum=%s, %d%n", Integer.toBinaryString(binNum), binNum);
    }
}

실행 결과

b=1
s=2
c=A, 65
finger=[   10]
finger=[10   ]
finger=[00010]
big=100000000000
hex=0xffffffffffffffff
octNum=10, 8
hexNum=10, 16
bigNum=10, 2
  • C에서는 char 타입의 값을 %d로 출력할 수 있지만, 자바에서는 허용되지 않는다. 형변환을 해줘야 함
  • 예제 코드
class PrintfEx2 {
    public static void main(String[] args) {
        String url = "www.codechobo.com";

        float f1 = .10f;    // 0.10, 1.0e-1
        float f2 = 1e1f;    // 10.0, 1.0e1, 1.0e+1
        float f3 = 3.14e3f;
        double d = 1.23456789;

        System.out.printf("f1=%f, %e, %g%n", f1, f1, f1);
        System.out.printf("f2=%f, %e, %g%n", f2, f2, f2);
        System.out.printf("f3=%f, %e, %g%n", f3, f3, f3);

        System.out.printf("d=%f%n", d);
        System.out.printf("d=%14.10f%n", d);    // 전체 14자리 중 소수점 10자리

        System.out.printf("[12345678901234567890]%n");
        System.out.printf("[%s]%n", url);
        System.out.printf("[%20s]%n", url);   // Default : 오른쪽 정렬
        System.out.printf("[%-20s]%n", url);    // 왼쪽 정렬
        System.out.printf("[%.8s]%n", url);        // 왼쪽에서 8글자만 출력
    }
}

실행 결과 

f1=0.100000, 1.000000e-01, 0.100000
f2=10.000000, 1.000000e+01, 10.0000
f3=3140.000000, 3.140000e+03, 3140.00
d=1.234568 // 마지막 자리 반올림! (%f는 기본적으로 소수점 이하 6자리까지 출력함)
d=  1.2345678900 // 14자리중 소수점 10자리
[12345678901234567890]
[www.codechobo.com]
[   www.codechobo.com]
[www.codechobo.com   ]
[www.code]

참조) Java의 정석 3rd edition(남궁성, 도우출판)