[자바의정석] Chap.02 변수 Variable

maroo·2023년 2월 12일
0

JavaGS

목록 보기
1/3

1. 변수와 상수

1.1 변수란?

프로그래밍 언어에서의 변수란 값을 저장할 수 있는 메모리 공간을 말한다. 하나의 변수에 단 하나의 값만 저장할 수 있으므로, 새로운 값을 저장하면 기존의 값은 사라진다.

1.2 변수의 선언과 변수의 초기화

변수타입 변수이름;
int age;
String name;

변수를 선언하면, 메모리의 빈 공간에 변수타입에 알맞은 크기의 저장공간이 확보되고, 앞으로 이 저장공간은 변수 이름을 통해 사용할 수 있게 된다.

변수를 선언하면 변수를 사용할 수 있지만, 그 전에 반드시 초기화를 해야한다. 메모리는 여러 프로그램이 공유하는 자원이므로 전에 다른 프로그램에 의해 저장된 알 수 없는 값이 남아있을 수 있기 때문이다.

int age = 25; // 변수를 age로 선언하고 25로 초기화한다

같은 타입의 변수는 콤마(,)를 구분자로 한 줄에 선언하기도 한다.

int a = 1, b = 2, c = 3;

지역변수(메서드 내에서 선언되며 메서드 내에서만 사용가능)는 사용되기 전에 초기화를 반드시 해야하지만, 클래스변수(static을 붙여 모든 인스턴스가 공통된 값을 공유하는 변수)와 인스턴스 변수(인스턴스 별로 다른 값을 가져야할 때는 인스턴스 변수로 선언)는 초기화를 생략할 수도 있다.

지역변수, 클래스변수, 인스턴스변수 인스턴스 변수 인스턴스 변수는 인스턴스가 생성될 때 생성됩니다. 그렇기 때문에 인스턴스 변수의 값을 읽어오거나 저장하려면 인스턴스를 먼저 생성해야합니다. 인스턴스 별로 다른 값을 가질 수 있으므로, 각각의 인스턴스마다 고유의 값을 가져야할 때는 인스턴스 변수로 선언합니다.

클래스 변수
클래스 변수는 인스턴스 변수에 static만 붙여주면 됩니다. 인스턴스 변수는 각각 고유한 값을 가지지만 클래스 변수는 모든 인스턴스가 공통된 값을 공유하게 됩니다. 한 클래스의 모든 인스턴스들이 공통적인 값을 가져야할 때 클래스 변수로 선언합니다. 클래스가 로딩될 때 생성되어(그러므로 메모리에 딱 한번만 올라갑니다.) 종료 될 때 까지 유지되는 클래스 변수는 public 을 붙이면 같은 프로그램 내에서 어디서든 접근할 수 있는 전역 변수가 됩니다. 또한 인스턴스 변수의 접근법과 다르게 인스턴스를 생성하지 않고 클래스이름.클래스변수명 을 통해서 접근할 수 있습니다.

지역 변수
메서드 내에서 선언되며 메서드 내에서만 사용할 수 있는 변수입니다. 메서드가 실행될 때 메모리를 할당 받으며 메서드가 끝나면 소멸되어 사용할 수 없게 됩니다.

출처 https://itmining.tistory.com/20

예제 /ch2/VarEx1.java

두 변수의 값 교환하기

변수 x, y가 있을 때 두 변수에 담긴 값을 서로 바꾸려면 변수를 하나 더 선언해서 임시 저장소로 사용하면 된다.

예제 /ch2/VarEx2.java

1.3 변수의 명명 규칙

'변수의 이름'처럼 프로그래밍에 사용되는 모든 이름을 '식별자identifier' 라고 하며, 식별자는 같은 영역 내에서 서로 구분될 수 있어야한다.

식별자를 만들때의 규칙

  1. 대소문자 구분되며 길이는 제한 없음
  2. 예약어(프로그래밍언어의 구문에 사용되는 단어)는 사용하면 안 된다
  3. 숫자로 시작해서는 안된다.
  4. 특수문자는 '_ 언더바' 와 '$' 만 사용한다.

자바 프로그래머들의 암묵적인 규칙

  1. 클래스 이름의 첫글자는 항상 대문자로 한다.
  2. 여러 단어로 이루어진 이름은 단어의 첫글자를 대문자로 한다.
  3. 상수의 이름은 모두 대문자로 하고, 여러단어의 경우 '_ 언더바'로 구분한다.
  • 클래스 이름은 영문자로 하자. 변수 이름은 짧을수록 좋고 주석으로 변수 정보를 주자

int curPos = 0; // 현재 위치(current position)
int lastPos = -1; // 마지막 위치(last position)

2. 변수의 타입

값(data)는 크게 문자와 숫자로 나눌 수 있다. 이런 데이터의 종류에 따라 값이 저장될 공간의 크기와 저장형식을 정의한 것이 자료형(data type)이고, 자료형에는 문자형(char), 정수형(byte, short, int, long), 실수형(float, double) 등이 있다.

기본형 변수 : 실제 값을 저장
참조형 변수 : 어떤 값이 저장되어 있는 주소를 값으로 가짐
-> 자바는 (C언어와 달리 참조형 변수 간 연산을 할 수 없으므로) 모두 기본형 변수이다.

참조 변수를 선언하는 방법

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

클래스이름 변수이름; // 변수 타입이 기본형이 아닌 것들은 모두 참조 변수이다.
Date today = new Date(); // Date 클래스 타입의 참조변수 today를 선언하고 초기화.

위의 객체를 생성하는 연산자 new의 결과는 생성된 객체의 주소이다. 이 주소가 대입연산자 '='에 의해서 참조 변수 today에 저장되는 것이다. 이제 today를 통해서 생성된 객체를 사용할 수 있게 된다.

2.1 기본형


출처: https://m.blog.naver.com/toplms78/70174710787

2.2 상수와 리터럴

상수

상수constant 는 변수와 마찬가지로 '값을 저장할 수 있는 공간'이지만, 변수와 달리 한번 값을 저장하면 다른 값으로 변경할 수 없다. 상수 선언은 변수와 동일하며, 변수타입 앞에 키워드 'final'을 붙여주기만 하면 된다. 상수는 반드시 선언과 동시에 초기화 해야하며, 그 후에는 변경은 허용되지 않는다. 상수는 모두 대문자로 쓰고 여러 단어인 경우 _ 언더바로 구분하는 것이 관례이다.

final int MAX_SPEED; // 초기화 안 해서 에러
final int MAX_VALUE = 100 ;
MAX_VALUE = 200; 상수 값은 변경할 수 없어서 에러

리터럴

위에서 100, 200 같은 값들이 리터럴. 그 자체로 값을 의미하는 것.

상수가 필요한 이유

int triArea = (20 * 10) / 2; // 삼각형 면적을 구하는 공식

final int WIDTH = 20;
final int HEIGHT = 10;
int triArea = (WIDTH * HEIGHT) / 2 ;

이전 코드에 비해 면적을 구하는 공식의 의미가 명확해졌고, 다른 값으로 계산할 때도 상수의 초기화만 다른 값으로 해주면 된다. 상수는 리터럴에 의미있는 이름을 붙여서 코드의 이해와 수정을 쉽게 만든다.

리터럴의 정수형의 경우 long타입에는 접미사 l 또는 L을 붙이고, 접미사가 없으면 int 타입이다. 16진수 앞에는 0x 또는 0X를 붙이고, 8진수 앞에는 0을 붙이고, 2진수 앞에는 0b를 붙인다.

int Num = 10; // 10진수 10
int hexNum = 0x10; // 8진수 10, 10진수로는 8
int binNum = 0b10;

실수형은 float에는 접미사 f 또는 F, double 타입에는 접미사 d 또는 D를 붙인다. int가 정수 기본자료형인 것처럼, 실수형에서는 double이 기본 자료형이라서 접미사 d가 생략 가능하다.

float pi = 3.14f;
float pi = 3.14; // 에러 (타입은 float인데 double로 리터럴 저장 불가)
double rate = 1.618d;
double rate = 1.618; // 에러 나지 않음 (d는 생략가능)

타입의 불일치

리터럴의 타입은 저장될 변수의 타입과 일치하는 것이 보통이지만, 타입이 달라도 저장 범위가 넓은 타입에 좁은 타입을 저장하는 것은 허용된다.

long a = 123; // OK. int 보다 long 타입의 범위가 넓다.

문자, 문자열 리터럴

char 타입의 변수는 단 하나의 문자이고 비어있으면 안 됨
string 타입은 여러 문자(문자열)이고 비어있어도 괜찮음

char chA = "A";
char chB = "BBB"; //에러
char chN = ""; // 에러. 비면 안됨

String stA = "Apple";
String stB = "B";
String stC = "";
String name = new String("Java"); // String이라는 객체를 생성

원래 String은 클래스이므로 아래와 같이 객체를 생성하는 연산자 new를 사용해야하지만, 특별히 위와 같은 표현도 허용한다.

덧셈 연산자 + 는 피연산자가 모두 숫자일 때는 두 수를 더하지만, 피연산자 중 어느 한 쪽이 string이면 나머지 한쪽을 먼저 string으로 변환한다음 두 string을 결합한다.

7 + 7 + "" -> 14 + "" -> "14" + "" -> "14"
"" + 7 + 7 -> "7" + 7 -> "7" + "7" -> "77"

예제 /ch2/StringEx.java

2.3 형식화된 출력

printf()는 '지시자specifier'를 통해 변수의 값을 여러 형식으로 변환하여 출력하는 기능을 가지고 있다. 지시자는 값을 어떻게 출력할 것인지를 지정해주는 역할을 한다. 예를 들어 int 타입의 변수 age의 값이 14일 때, printf는 지시자"%d" 대신 14를 넣어서 출력한다.

int octNum = 010; // 8진수로는 10, 10진수로는 8
System.out.printf("octNum=%o, %d, octNum, octNum);
실행결과 octNum = 10, 8

System.out.printf("octNum=%o, %d%n, octNum, octNum);
프린트 후 줄 바꿈을 하려면 %n 넣어주기

10진수를 2진수로 출력해주는 지시자는 없기 때문에, 정수를 2진 문자열로 변환해주는 'Integer.toBinaryString(int i)'를 사용해야한다.

int binNum = 3; // 10진수로는 3, 2진수로는 11
System.out.printf("binNum=%s%n", Integer.toBinaryString(binNum));
실행결과 11

2.4 화면에서 입력받기 - Scanner

자바에서 화면으로부터 입력받는 방법 Scanner 클래스 사용

import java.util.* ;
Scanner scanner = new Scanner(System.in); // Scanner 클래스의 객체를 생성
String input = scanner.nextLine(); // 입력받은 내용을 input에 저장
int num = Integer.parseInt(input); // 입력받은 내용을 Interger.parseInt 메서드를 이용해 문자열을 int타입의 정수로 변환한다.

nexInt()나 nextFloat()와 같은 메서드들을 통해 더 간단히 입력받을 수 있지만 이 메서드들은 연속적으로 값을 입력받아서 사용하기는 까다롭기 때문에 위의 nextline()으로 입력받아서 변환하는 것이 낫다.

int num = scanner.nextInt(); // 정수를 입력받아 변수에 저장

예제 /ch2/ScannerEx.java

3. 진법

3.1 10진법과 2진법

컴퓨터는 2진 체계이므로 2진법을 이해해야.

3.2 bit와 byte

한자리의 2진수를 비트라 하며, 1비트는 컴퓨터가 값을 저장할 수 있는 최소 단위다.
1비트 8개를 묶어 1바이트byte로 정의하여 데이터의 기본 단위로 사용한다.
word는 CPU가 한번에 처리할 수 있는 데이터의 크기로, CPU 성능에 따라 달라진다. 32비트 CPU에서는 1워드는 32비트(4바이트).

3.3 8진수와 16진수

3.4 정수의 진법 변환

3.5 소수점수의 진법 변환

3.6 음수의 2진 표현을 구하는 방법

(1) 음수의 절대값을 2진수로 변환
-5의 절대값인 5를 2진수로 변환한다. 0101
(2) (1)에서 구한 2진수의 1을 0으로, 0은 1로 바꾼다(1의 보수 구하기)
0101이 1010이 된다
(3) (2)의 결과에 1을 더한다 (2의 보수 구하기)
1010에 1을 더하면 1011이 되고 이것이 -5의 2진표현이다.

4. 기본형

4.1 논리형 boolean

true,false 중 하나를 저장할 수 있으며, 기본값은 false이다. 대답, 스위치 등의 논리 구현에 주로 사용된다.

4.2 문자형 char

단 하나의 문자만을 저장할 수 있다. 사실은 문자가 아닌 '문자의 유니코드(정수)'가 저장된다. 문자 A의 유니코드는 65이므로, 변수에는 65가 저장된다. println()은 변수의 타입이 정수형이면 10진수로 해석해 출력하고 문자형이면 저장된 숫자에 해당하는 유니코드 문자를 출력한다.

문자의 유니코드 알기

char ch = 'A'; -> A가 출력
char ch = 65;
short s = 65; -> 65가 출력
int code = (int)ch; //ch에 저장된 값을 int타입으로 변환하여 저장한다.

인코딩과 디코딩

문자를 저장할 떄는 인코딩을 해서 숫자로 변환해서 저장하고, 저장된 문자를 읽어올 때는 디코딩을 해서 숫자를 원래의 문자로 되돌려야 한다.

인코딩: 문자를 코드로 변환하는 것
디코딩: 코드를 문자로 변환하는 것

아스키(ASCII) 모드

정보교환을 위한 미국 표준 코드.
0~9, A~Z, a~z가 연속적으로 배치되어 있다.

유니코드

전세계의 모든 문자를 하나의 통일된 문자 집합으로 표현

4-3. 정수형

byte 1 < short 2 < int 4 < long 8

n비트로 표현할 수 있는 정수의 개수 : 2^n개
n비트로 표현할 수 있는 부호있는 정수의 범위: -2^(n-1)~2^(n-1)-1

정수형 변수를 선언할 때는 int 타입으로 하고, int의 범위를 넘어서는 수를 다뤄야할 떄는 long을 사용하면 된다.

오버 플로우

부호 없는 정수는 2진수로 0000이 될 때 오버 플로우가 발생하고,
부호 있는 정수는 부호비트가 0에서 1이 될 때 오버 플로우가 발생한다.
(최소값과 최대값을 이어놓았다고 생각하기)

short와 char의 크기는 모두 16bit 이므로, 표현할 수 있는 값의 개수 역시 2^16개로(65536개)

4-3 실수형 float, double

실수형은 정수형과 달리, 오버플로우가 발생하면 변수의 값은 무한대가 된다.
정수형에는 없는 언더플로우(실수형으로 표현할 수 없는 아주 작은 값, 최소값보다 작은값)이 있고, 이때 변수의 값은 0이 된다.

4 바이트의 정수 : 약 +-2*10^9
float 타입과 같은 실수형은 부호, 지수, 가수 세 부분(부동소수점수)으로 이루어져 있어서 큰 범위의 값을 저장할 수 있다.
오차가 발생할 수도 있어서, 정밀도도 중요한 요소이다.
7자리 이상의 정밀도가 필요하다면 변수의 타입을 double로 하기.

5. 형변환 (casting)

형변환 : 변수 또는 상수의 타입을 다른 타입으로 변환하는 것

5-2 형변환 방법

형변환 하고자하는 변수나 리터럴의 앞에 변환하고자 하는 타입을 괄호와 함께 붙여주기.

(타입) 피연산자

double d = 85.4;
int score = (int)d;

d는 여전히 85.4 출력, score는 85 출력

기본형에서 boolean 타입을 제외한 나머지는 서로 형변환 가능.
기본형과 참조형 간의 형변환은 불가능.

5-3 정수형 간의 형변환

큰 타입에서 작은 타입으로의 변환, int -> byte 로의 변환은 크기의 차이만큼 잘려나가서 값 손실이 발생할 수 있다.
작은 타입에서 큰 타입으로의 변환은 나머지 빈공간은 0또는 1로 채워진다. (음수일 때는 1로 채움)

5.4 실수형 간의 형변환

작은 타입float에서 큰 타입double으로 변환하는 경우, 빈공간을 0으로 채운다.
큰 타입에서 작은 타입으로 변환하는 경우, 지수는 double의 기저인 1023을 뺀 후 float의 기저인 127을 더하고, 가수는 double 의 가수 52자리 중 23자리만 저장되고 나머지는 버려진다.
float타입의 범위를 넘는 값을 형변환하면 +-무한대 또는 +-0

5.5 정수형과 실수형 간의 형변환

정수형을 실수형으로 변환

별 무리 없으나 실수형의 정밀도 제한으로 인한 오차 발생 가능
10진수로 8자리 이상의 값을 실수형으로 변환할 때는 double로 형변환해야함

실수형을 정수형으로 변환

실수형의 소수접 이하 값은 버려진다. (반올림 아님)

5.6 자동 형변환

형변환으로 타입 일치시키는 것이 원칙이지만, 편의상 이유로 형변환 생략도 가능.
저장할 수 있는 값의 범위보다 더 큰 값을 저장하는 형변환을 생략하면 에러 발생.

byte b = 1000; // 바이트 범위를 넘는 값이라 에러.
char ch = (char)1000; // 명시적 형변환. (의도적인 것으로 간주하고 컴파일 에러 발생x)

연산 과정에서 자동적으로 발생하는 형변환 = 산술변환

자동 형변환의 규칙

  • 기본의 값을 최대한 보존할 수 있는 타입으로 자동 형변환
  • boolean을 제외한 나머지 7개의 기본형은 서로 형변환이 가능
  • 기본형과 참조형은 서로 형변환 불가
  • 서로 다른 타입의 변수 간 연산은 형변환이 원칙이지만,
    값의 범위가 작은 타입에서 큰 타입으로의 형변환은 생략할 수 있다.

0개의 댓글