본문 바로가기

Study/Java

Chapter02. 변수(Variable)

728x90

GTH 블로그 작성 전 다짐

책에 내용을 그대로 적는 것이 아닌 내용을 이해한 후 요약하여 주관적 생각과 함께 기록할 것입니다.

읽고 도움이 되신다면 감사드리며, 부족한 부분이 있다면 댓글을 통해 피드백 주시면 감사하겠습니다.

1. 변수와 상수

중요한 프로그래밍 능력중의 하나가 '값(data)를 잘 다루는 것'

 

1.1 변수란?

변수(variable)란, 단 하나의 값을 저장할 수 있는 메모리 공간.

하나의 변수에 단 하나의 값만 저장할 수 있음, 새로운 값 저장하면 기존의 값은 사라짐.

 

1.2 변수의 선언과 초기화

  int        age;
변수타입 변수이름

'변수타입' -> 변수의 값이 어떤 타입(type)인지를 지정하는 것이다.

Java는 정수형, 실수형, 문자형 등 다양한 타입을 제공한다.

'변수이름' -> 변수에 붙힌 이름, 이를 이용해 저장공간(변수)에 값을 저장하고, 저장된 값을 읽어올 수 있음.

                  그래서 같은 이름의 변수가 여러 개 존재해서는 안된다. 서로 구별되어야 한다.

 그래서 변수를 선언하면, 메모리의 빈 공간에 'int(변수타입)'에 알맞은 크기(4byte)의 저장공간이 확보되고, 이 저장공간은 '변수이름'을 통해 사용할 수 있다.

 

- 변수의 초기화 : 변수를 사용하기 전에 처음으로 값을 저장하는 것

변수는 '초기화(initialization)' 해야 사용할 수 있다.

그 이유는 메모리는 여러 프로그램이 공유하는 자원이라서, 전에 다른 프로그램에 의해 저장된 값(garbage value, 쓰레기값)이 남아 있을 수 있기 때문이다.

package ch01;

public class test {

	public static void main(String[] args) {
		int a;
		System.out.println(a);
	}

}

그래서 이런식으로 선언하면 eclipse에서는 변수 a에 빨간줄로 에러 메세지를 알려준다.

The local variable a may not have been initialized // 지역 변수가 초기화되지 않았을 수 있습니다.

여기서 지역변수란 '프로그램 내 변수가 선언된 영역만 접근 가능한 영역으로 취하는 변수'이다.

 

변수에 값을 저장할 때는 대입 연산자'='를 이용한다.

int age = 25; // 변수 age를 선언하고 25로 초기화 한다.
int : 정수형 자료형
age : 변수이름
= : 대입연산자
25 : 변수의 저장된 값
; : 문장을 마칠 때 찍는 세미콜론

 오른쪽의 값을 왼쪽(변수)에 저장하라는 뜻이다. 그래서 대입연산자 왼쪽에는 반드시 변수가 와야 한다.

 

(변수 선언, 대입 연산자 사용예제)

package ch01;

public class test {
	
	int global_int; // main 메소드 밖에서 선언된 이 변수가 전역변수(객체변수)이다.
	static int global_static_int; // 앞에 static이 붙어있는 이 변수는 전역변수(클래스변수)이다. 

	public static void main(String[] args) {
		int age = 25; // int형 변수 age에 25 대입
		int year = 2022; // int형 변수 year에 2022 대입
		//main 메소드 안에서 선언된 이 변수들이 지역변수(Local variables)이다.
		
		System.out.println(age);
		System.out.println(year);		
	}

}

 

public class MSG {

여기서 전역변수(객체변수=인스턴스변수)란? 

클래스 영역에서 선언되어, 객체가 생성 될 때마다 만들어지고 생성되었을 때만 호출하여 사용가능함.

package ch01;

public class test {
	
	int a; // 객체 변수 = 인스턴스 변수

	public static void main(String[] args) {
		test ob = new test(); //객체를 생성해야 사용가능
		ob.a = 100;
		System.out.println(ob.a);
	}
}

여기서 객체(Object)란?

물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신과 다른 것을 식별가능한 것을 의미한다.

 

@그럼 왜 객체 변수를 사용하기 위해 main 메소드에서 객체를 생성해야 됩니까?

 자바의 규칙이라고 생각합니다. 객체는 독립적인 저장공간을 갖는데, 서로 다른 값을 가질 수 있는 특징을 갖고 있습니다. 그래서 고유한 상태를 유지해야하는 경우 1. 인스턴스 변수로 선언하고 2. 객체를 생성하여 사용합니다.

 

여기서 전역변수(클래스변수)란? 다른 클래스에서도 호출이 가능한 변수이다.

객체를 따로 생성하지 않아도 사용 가능, 근데 사용하지 않는걸 권장!!(왜 why? 프로그램 실행 속도에 악영향)

package ch01;

public class test {
	
	static int a; // 클래스 변수(static)

	public static void main(String[] args) {
		a = 100;
		System.out.println(a);
		
	}

}// 클래스 변수 소멸

}

 

1.3 변수의 명명규칙

1. '변수의 이름' 프로그래밍에서 사용하는 모든 이름을 '식별자(identifier)' 라고 한다.

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

 

- 식별자 만들 때 규칙(암기)

 - 대소문자가 구분되고 길이에 제한이 없다.

 - 예약어를 사용해서는 안 된다.

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

 - 특수문자는 '_'와 '&'만을 허용한다.

 

@예약어가 뭡니까?

'keyword' 또는 'reserved word'라고 하는데, 이미 사용되어 사용할 수 없는 변수명 이라고 생각하면 됩니다.

for, if, goto, this 등 문법이나 특정 요소에 사용되고 있는 단어들로 변수명으로는 사용할 수 없습니다.

 

- 변수명 만들 때 자바 프로그래머들에게 권장하는 규칙

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

public class Test{ }

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

int dataTypeList;

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

final int MAX_NUMBER

 

@상수가 뭡니까?

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

2. 변수의 타입

값(data) 종류는 크게 '문자''숫자'로 나눌 수 있다.

여기서 숫자는 '정수와 실수'로 나눌 수 있다.

값의 분류

data의 종류 type에 따라 값이 저장될 공간의 크기와 저장형식을 정의한 것이 자료형(data type)이다.

자료형에는 문자형(char), 정수형(byte, short, int, long) , 실수형(float, double) 등이 있고, 변수를 선언할 때는 저장하려는 값의 특성을 고려하여 가장 알맞은 자료형을 변수의 타입으로 선택하면 된다.

 

기본형과 참조형

기본형의 변수는 실제 값(data)을 저장한다.

 - 논리형(boolean), 문자형(char), 정수형(byte, short, int, long), 실수형(float, double)

 - 계산을 위한 실제 값을 저장.

 

참조형 변수는 저장되어 있는 주소(memory address)를 값으로 갖는다.

 - 객체의 주소를 저장한다. 8개의 기본형을 제외한 나머지 타입.

 - 참조변수는 null 또는 객체의 주소를 값으로 갖는다.

Data today = new Date(); // Data객체를 생성해서, 그 주소를 today에 저장.

다음은 Data 클래스 타입의 참조변수 today를 선언하고 초기화한 예시.

today를 통해서 생성된 객체를 사용할 수 있게 된다.

 

@JVM 32bit가 아니라 64 bit라면 참조형 변수의 크기는 8 byte가 된다.

 

2.1 기본형(primitive type)

논리형 boolean(1byte)
true와 false 중 하나를 값으로 갖으며, 조건식과 논리적 계산에 사용된다.
문자형 char(2byte)
문자를 저장하는데 사용되며, 변수에 하나의 문자만 저장할 수 있다.
정수형 byte(1byte), short(2byte), int(4byte), long(8byte)
정수를 저장하는데 사용되며, 주로 int가 사용된다. byte는 이진 데이터를 다룰 때 사용되며, short는 C언어와의 호환을 위해서 추가되었다.
실수형 float(4byte), double(8byte)
실수를 저장하는데 사용되며, 주로 double이 사용된다.

기본형의 종류

문자형 char

- 문자형인 char은 문자를 내부적으로 정수(유니코드)로 저장하기 떄문에 정수형과 별반 다르지 않다.

- 그래서 정수형 또는 실수형과도 연산이 가능하다.

@유니코드 : https://ko.wikipedia.org/wiki/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C

 

유니코드 - 위키백과, 우리 모두의 백과사전

유니의 음반에 대해서는 U;Nee Code 문서를 참고하십시오. 유니코드(영어: Unicode)는 전 세계의 모든 문자를 컴퓨터에서 일관되게 표현하고 다룰 수 있도록 설계된 산업 표준이다. 유니코드는 유니

ko.wikipedia.org

 

정수형 byte, short, int, long

- 일반적으로 int를 가장 많이 사용하는데 CPU가 가장 효율적으로 처리할 수 있는 타입이다.

- 효율적인 실행보다 메모리를 절약하려면, byte나 short을 선택하자.

 

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

자료형 저장 가능한 값의 범위 크기
bit byte
boolean false, ture 8 1
char '\u0000' ~ '\uffff' (0 ~ 2^16-1, 0 ~ 65535) 16 2
byte -128 ~ 127(-2^7 ~ 2^7-1) 8 1
short -32,768 ~ 32,767(-2^15 ~ 2^15-1) 16 2
int -2,147,483,648 ~ 2,147,483,647 (-2^31 ~ 2^31-1, 약 ±20억) 32 4
long -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807(-2^63 ~ 2^63  -1) 64 8
float 1.4E-45 ~ 3.4E38(1.4x10^-45 ~ 3.4x10^38) 32 4
double 4.9E-324 ~ 1.8E308(4.9x10^-324 ~ 1.8x10^-308) 64 8

기본형의 크기와 범위(참고)

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

상수(constant)란?

- 한번 값을 저장하면 다른 값으로 변경 할 수 없다. 

- 선언하는 방법은 변수와 동일한데, 타입 앞에 final을 붙여주기만 하면 된다.

final int MAX_SPEED = 10; // 상수 MAX_SPEED를 선언 & 초기화

- 상수의 이름은 모두 대문자로 하는 것이 암묵적인 관례이다.

- 여러 단어로 이루어져 있는 경우 '_'로 구분한다.

- 상수는 '의미있는 이름'을 붙여서 코드의 이해와 수정을 쉽게 만든다.

 

상수사용예제.

package ch01;

public class test {
	
	public static void main(String[] args) {
		
		final int WIDTH = 20; // 폭
		final int HEIGHT = 10; // 높이
		
		int triangleArea = (WIDTH * HEIGHT) / 2; //삼각형의 면적을 구하는 공식
		int rectangleArea = WIDTH * HEIGHT; //사각형의 면적을 구하는 공식
	
		System.out.println(triangleArea);
		System.out.println(rectangleArea);
	}
}

 

리터럴(literal)이란?

- 그 자체로 값을 의미하는 것

    변수   리터널
int year = 2014;
                상수       리터널
final int MAX_VALUE = 100;

 

리터럴의 타입과 접미사

@접미사란?

낱말의 끝에 붙어 의미를 첨가하여 다른 낱말을 이루는 말.

 

정수형의 경우, long타입의 리터럴에 접미사 'l' 또는 'L'을 붙힌다.

실수형의 경우, float타입의 리터럴에 접미사 'f'를 붙인다.

16진수인 경우 리터럴 앞에 접두사 '0x' 또는 '0X'를, 8진수인 경우에는 '0'을 붙인다.

 

타입의 불일치

타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용된다.

2.3 형식화된 출력 - printf()

package ch02;

public 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  = 100000000000; 
		long hex = 0xFFFF_FFFF_FFFF_FFFFL; //L은 접두사
		
		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); //공간 5칸 확보 후 뒤에서부터 출력
		System.out.printf("finger=[%-5d]%n", finger);// 공간 5칸 확보 후 앞에서부터 출력 
		System.out.printf("finger=[%05d]%n", finger); //공간 5칸 확보후 남는 공간엔 0을 나머지공간에 값 출력
		System.out.printf("big=%d%n", big);
		System.out.printf("hex=%#x%n", hex); //#은 접두사 : 0x를 출력해줌.
		System.out.printf("octNum=%o, %d%n", octNum, octNum);
		System.out.printf("hexNum=%x, %d%n", hexNum, hexNum);
		System.out.printf("binNum=%s, %d%n", Integer.toBinaryString(binNum), binNum);
	}
}

출력결과.

package ch02;

public 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); // 전체자리.소수점아래자리f
		
		System.out.printf("[12345678901234567890]%n");
		System.out.printf("[%s]%n", url);
		System.out.printf("[%20s]%n", url);
		System.out.printf("[-20s]%n", url);
		System.out.printf("[%.8s]%n", url);

	}

}

출력결과.

2.4 화면에서 입력받기 - Scanner

package ch02;

import java.util.Scanner;

public class ScannerEx {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in); //Scanner 객체를 생성
		
		System.out.print("두자리 정수를 하나 입력해주세요.>");
		String input = scanner.nextLine();
		int num = Integer.parseInt(input); //입력받은 문자열을 숫자로 반환 이거 중요함.
		
		System.out.println("입력내용 : "+ input);
		System.out.printf("num = %d%n", num);
	}
}

출력결과.

3. 진법

3.1 10진법과 2진법

2진법은 0과 1로만 데이터를 표현.

- 컴퓨터는 전기가 흐르면 1, 흐르지 않으면 0, 만으로 동작하도록 설계

  즉 2진 체계로 설계되어있다, 2진법을 알아야 컴퓨터의 동작원리나 데이터 처리방식을 온전히 이해할 수 있다.

2진수 10진수
0 0
1 1
10 2
11 3
100 4
101 5
110 6
111 7
1000 8
1001 9
1010 10

3.2 비트(bit)와 바이트(byte)

한 자리의 2진수를 '비트(bit, binary digit)'라고 하며, 1 비트는 컴퓨터가 값을 저장할 수 있는 최소 단위이다.

그러나 1 비트는 너무 작은 단위이기 때문에 1비트 8개를 묶어서 '바이트(byte)'라는 단위로 정의하여 데이터의 기본단위로 사용한다.

 

이 외에도 '워드(word)'라는 단위가 있는데, '워드(word)'는 'CPU가 한 번에 처리할 수 있는 데이터의 크기'를 의미한다.

word의 크기는 CPU의 성능에 따라 달라지는데 => CPU에서 32비트에서 1워드는 32비트(4 바이트)이고, 64 비트 CPU에서는 64비트는 8바이트이다.

 

1 bit(2개) 2 bit (4개) 3 bit (8개) 4 bit (16개) 10 진수
0 00 000 0000 0
1 01 001 0001 1
  10 010 0010 2
  11 011 0011 3
    100 0100 4
    101 0101 5
    110 0110 6
    111 0111 7
      1000 8
      1001 9
      1010 10
      1011 11
      1100 12
      1101 13
      1110 14
      1111 15

3.3 8진법과 16진법

2진법은 오직 0과 1, 두개의 기호만으로 값을 표현하기 때문에, 길이가 길어진다는 단점이 있다.

그래서,,

8진수는 2진수 3자리를, 16진수는 2진수 4자리를 각각 한자리로 표현할 수 있어서 알아보기 쉽게 변환할 수 있다.

 

2진수 8진수 2진수 16진수
000 0 0000 0
001 1 0001 1
010 2 0010 2
011 3 0011 3
100 4 0100 4
101 5 0101 5
110 6 0110 6
111 7 0111 7
    1000 8
    1001 9
    1010 A
    1011 B
    1100 C
    1101 D
    1110 E
    1111 F

 

3.4 정수의 진법 변환

10진수를 n진수로 변환

ㅋㅋㅋㅋㅋㅋㅋㅋ 진수 변환과정.

46(10진수)를 2진수로 변환하면 101110(2)가 된다.

8진수 변환

816(10진수)를 8진수로 변환하면 1460(8)가 된다.

16진수 변환

1615(10진수)를 16진수로 변환하면 64F(16)가 된다.

16진수는 10부터 15까지 알파벳 A ~ F로 표현한다.

10 A
11 B
12 C
13 D
14 E
15 F

 

n진수를 10진수로 변환

101110(2)을 변환한다면.

2^5 2^4 2^3 2^2 2^1 2^0
32 16 8 4 2 1
1 0 1 1 1 0

32 + 8 + 4 + 2 = 46(10)

 

1460(8)을 변환한다면.

8^3 8^2 8^1 8^0
512 64 8 1
1 4 6 0

512 + (64*4) + (8*6) + 0 = 816(10)

 

64F(16)을 변환한다면.

16^2 16^1 16^0
256 16 1
6 4 F

256 * 6 + 16 * 4 + 15 = 1615(10)

3.5 실수의 진법 변환

* 10진 소수점수를 2진 소수점수로 변환하는 방법

 

10진수 0.625을 2진수로..

1. 10진 소수에 2를 곱한다.

0.625 * 2 = 1.25

2. 위의 결과에서 소수부만 가져다가 다시 2를 곱한다.

0.625 * 2 = 1.25
0.25 * 2 = 0.5

3. 1과 2의 과정을 소수부가 0이 될 때까지 반복한다.

0.625 * 2 = 1.25
0.25 * 2 = 0.5
0.5 * 2 = 1.0

4. 정수부만을 위에서 아래로 순서대로 적고 '0.'을 붙이면 된다.

0.101(2) 완성~

 

* 2진 소수점수를 10진 소수점수로 변환하는 방법

  2^-1 2^-2 2^-3
  0.5 0.25 0.125
0. 1 0 1

0.125 + 0.5 = 0.625(10)

3.6 음수의 2진 표현 - 2의 보수법

n비트의 2진수로 표현할 수 있는 값이 개수는 모두 2^n개이다.

따라서 4비트의 2진수로는 2^4(=16)개의 값을 표현할 수 있다. 이 값을 모두 '부호없는 정수(0과 양수)'의 표현에 사용하면 아래와 같이 '0부터 15까지의 정수'를 나타낼 수 있다.

# 2진수 부호없는 10진수
1 0000 최소값 -> 0
2 0001 1
3 0010 2
4 0011 3
5 0100 4
6 0101 5
7 0110 6
8 0111 7
9 1000 8
10 1001 9
11 1010 10
12 1011 11
13 1100 12
14 1101 13
15 1110 14
16 1111 15

그러면 4비트의 2진수로 부호있는 정수. 즉 양수(+)와 음수(-)를 표현하려면 어떻게 해야하나?

4비트 2진수의 절반인 8개는 0으로 시작하고, 나머지 절만을 1로 시작하니깐,

1로 시작하는 2진수를 음수 표현에 사용하자.

'왼쪽의 첫 번째 비트가(MSG)가 0이면 양수, 1이면 음수이므로 첫 번째 비트만으로 값의 부호를 알 수 있게 된다.

 

 

 

 

 

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

Java04_연산자  (0) 2022.05.14
Java03_자료형과변수  (0) 2022.05.14
Java02_입출력  (0) 2022.05.14
Java01_기본문법  (0) 2022.05.14
Chapter01. 자바를 시작하기 전에  (0) 2022.04.26