JAVA LV 1-2

변수의 타입

Posted by Gihoon on March 10, 2023

- 변수의 타입

우리가 주로 사용하는 값의 종류는 크게 ‘문자와 숫자’로 나눌 수 있으며, 숫자는 다시 ‘정수와 실수’로 나눌 수 있다.

이러한 값의 종류에 따라 값이 저장될 공간의 크기와 저장형식을 정의한 것이 자료형 이다. 자료현에는 문자형 (char), 정수형 (byte, short, int, long), 실수형 (float, double) 등이 있으며, 변수를 선언할 때는 저장하려는 값의 특성을 고려하여 가장 알맞은 자료형을 변수의 타입으로 선택하여야한다. 자료형은 크게 ‘기본형’과 ‘참조형’ 두 가지로 나눌수 있는데, 기본형 변수는 실제 값을 저장하는 반면, 참조형 변수는 어떤 값이 저장되어 있는 주소를 값으로 갖는다. 자바는 c언어와 달리 참조형 변수간의 연산을 할수 없으므로 실제 연산에 사용되는 것은 기본형 변수이다.

기본형 - 논리형, 문자형, 정수형, 실수형 계산을 위한 실제 값을 저장한다. (모두 8개)

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

참조형 변수를 선언할 때는 변수의 타입으로 클래스의 이름을 사용하므로 클래스의 이름이 참조변수의 타입이 된다. 그래서 새로운 클래스를 작성한다는 것은 새로운 참조형을 추가하는 셈이다. 다음으로 참조 변수를 선언하는 방법이다. 기본형 변수와 같이 변수이름 앞에 타입을 적어주는데 참조 변수의 타입은 클래스의 이름이다. 클래스이름 변수이름; // 변수의 타입이 기본형이 아닌것들은 모두 참조변수이다.

다음은 Date 크래스 탕비의 참조변수 today 를 선언한 것이다. 참조변수는 null 또는 객체의 주소를 값으로 갖으며 참조변수의 초기화 다음과 같다. Date today = new Date();// Date객체를 생성해서, 그 주소를 today에 저장.

-기본형( primitive type)

math

문자형인 char는 문자를 내부적으로 정수로 저장하기 때문에 정수형과 별반 다르지 않으며, 정수형 또는 실수형과 연산도 가능하다. 반면에 boolean은 다른 기본형과의 연산이 불가능하다. 즉, boolean을 제외한 나머지 7개의 기본형은 서로 연산과 변환이 가능하다.

정수는 가장 많이 사용되므로 타입을 4가지나 제공한다. 각 타입마다 저장할 수 있는 값의 범위가 다르므로 저장할 값의 범위에 맞는 타입을 선택하면 되지만, 일반적으로 int를 많이 사용한다. 왜냐하면, int는 cpu가 가장 효율적으로 처리할 수 있는 타입이다. 메모리를 아끼고 싶다면 byte, short을 선택하자.

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

‘상수’는 변수와 마찬가지로 값을 저장할 수 있는 공간이지만 변수와 달리 한번 값을 저장하면 다른 값으로 변경할 수 없다. 상수를 선언하는 방법은 변수와 동일하며, 단지 변수의 타입앞에 키워드 ‘final’을 붙여주기만 하면 된다.

ex) final int MAX_SPEED = 10; // 상수 MAX_SPEED 를 선언 AND 초기화

그리고 상수는 반드시 선언과 동시에 초기화해야 하며 그 후부터는 상수의 값을 변경하는 것이 허용되지 않는다.

상수의 이름은 모두 대문자로 하는것이 암묵적인 관례이며, 여러 단어일때는 _로 구분한다.

원래 12,123,3.14, ‘A’와 같은 값들이 ‘상수’인데 프로그래밍에서는 상수를 값을 한번 저장하면 변경할 수 없는 저장공간으로 정의하였기 떄문에 이와 구분하기 위해 상수를 다른이름으로 불러야만 했다. 따라서 상수 대신 리터럴이라는 용어를 사용한다.

  • 변수 : 하나의 값을 저장하기 위한 공간
  • 상수 : 값을 한번만 저장할 수 있는 공간
  • 리터럴: 그 자체로 값을 의미하는것

ex) int year(변수)=2014;(리터럴) final int MAX_VALUE(상수) = 100;(리터럴)

상수가 필요한 이유

1
2
3
4
5
int triangleArea = (20 * 10) / 2; // 삼각형의 면적을 구하는 공식

int rectangleArea = 20*10; // 사각형의 면적을 구하는 공식```

위의 코드는 삼각형과 사각형의 면적을 구해서 변수에 저장하지만 보다 복잡한 공식이라면 얘기가 달라질 것이다. 게다가 20과 10이 아닌 다른 값을 이용해서 결과를 얻고 싶다면 여러 곳을 수정해야한다.
1
2
3
4
5
6
7
8
9
10
final int WIDTH = 20;

final int HEIGHT = 10;

int triangleArea = (WIDTH \* HEIGHT)/2;

System.out.println(WIDTH);

System.out.println(triangleArea);

상수를 이용해서 기존의 코드를 변경한 것인데, 이전 코드에 비해 면적을 구하는 공식의 으미가 명확해졌고 다른 값으로 계산할 때에도 여러 곳을 수정할 필요없이 상수의 초기화만 다른 값으로 해주면 된다. 이처럼 상수는 리터럴에 ‘의미있는 이름’을 붙여서 코드의 이해와 수정을 쉽게 만든다.

리터럴의 타입과 접미사

변수에 타입이 있는 것 처럼 리터럴에도 타입이 있다. 변수의 타입은 저장될 ‘값의 타입’에 의해 결정되므로, 만일 리터럴에 타입이 없면 변수의 타입도 필요없을 것이다.

논리형 flase,true 없음
정수형 123, 0b0101,077,0xFF,100L L
실수형 3.14, 3.0e8, 1.4f f,d
문자형 ‘A’,’1’,’\n’ 없음
문자열 “ABC”, “123”, “A”

정수형과 실수형에는 여러 타입이 존재하므로, 리터럴에 접미사를 붙여서 타입을 구분한다. 정수형의 경우, long타입의 리터럴에 접미사 ‘l’ 또는 ‘L’을 붙이고, 접미사가 없으면 int 타입의 리터럴이다. byte와 short 타입의 리터럴은 별도로 존재하지 않으며 byte와 short타입의 변수에 값을 저장할 때는 int타입의 리터럴을 사용한다.

10진수 외에도 2,8,16 진수로 표현된 리터럴을 변수에 저장할 수 있으며, 16진수라는 것을 표시하기 위해 리터럴 앞에 접두사 ‘0x’ 또는 ‘0X’를 8진수에는 ‘0’ 을 붙인다.

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

그리고 정수형 리터럴의 중간에 구분자 ‘_‘을 넣음 으로써 큰 숫자를 편하게 읽을 수 있다.

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

1
2
3
float pi = 3.14f;

double rate = 1.618d;

실수형 리터럴에는 접미사를 붙여서 구분하며, float 타입 리터럴에는 ‘f’ 를, double 타입 리터럴에는 ‘d’를 붙인다. 정수형에서는 int가 기본 자료형인 것처럼 실수형에서는 double이 기본 자료형이라서 접미사 ‘d’는 생략이 가능하다. 따라서 실수형 리터럴인데, 접미사가 없다면 doublle타입 리터럴인 것이다.

1
2
3
float pi = 3.14; // 에러. float 타입 변수에 타입 리터럴 저장불가

double rate =1.618; // ok. 접미사 d 는 생략가능

위의 문장에서 3.14는 접미사가 붙지 않았으므로 float타입 리터럴이 아니라 double 타입 리터럴로 간주된다. 그래서 3.14가 float 타입의 범위에 대한 속한 값임에도 불구하고 컴파일 시에 에러가 발생한다. 에러를 피하려면 3.14f와 같이 접미사를 붙여야한다.

리터럴의 접두사와 접미사는 대소문자는 구별하지 않으므로, 대문자와 소문자 중에서 어떤 것을 사용해도 상관없지만, 소문자 ‘l’의 경우 1과 헷갈리기 쉬우므로 ‘L’을 사용하는 것이 좋다.

리터럴에 소수점이나 10의 제곱을 나타내는 기호 E 또는 e, 그리고 접미사 f,F,d,D를 포함하고 있으면 실수형 리터럴로 간주된다.

참고로 잘 쓰이지는 않지만 기호 p를 이용해서 실수 리터럴을 16진 지수형태로 표현할 수 있다. p는 2의 제곱을 의미하며, p의 왼쪽에는 16진수를 적고 오른쪽에는 지수를 10진 정수로 듣는다. p는 대소문자 모두 가능하며 p가 포함된 리터럴은 실수형이다.

타입의 불일치

리터럴의 타입은 저장될 변수의 타입과 일치하는 것이 보통이지만, 타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용된다. 그러나 리터럴의 값이 변수의 타입의 범위를 넘어서거나, 리터럴의 타입이 변수의 타입보다 저장범위가 넓으면 컴파일 에러가 발생한다.

1
int i = 0x123456; float f =3.14; //에러

3.14는 3.14d에서 접미사가 생략된 것으로 double타입이다. 이 값을 float타입으로 표현할 수 있지만 , double타입의 리터럴이므로 float타입의 변수에 저장할 수는 없다. byte와 short 타입의 리터럴은 따로 존재하지 않으므로 int 타입의 리터럴을 사용한다. 단, short 타입의 변수가 저장할 수 있는 범위에 속한 것이어야한다.

각 타입의 저장범위만 알아도 충분히 판단 가능한 내용이다. 값의 크기에 상관없이 double 타입의 러터럴을 float 타입의 변수에 저장할 수 없다는 것만 주의하자.

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

‘A’와 같이 작은 따옴표로 문자 하나를 감싼 것을 ‘문자 리터럴’이라고 한다. 두 문자 이상은 큰 따옴표로 감싸야 하며 ‘문자열 리터럴’이라고 한다.

char타입의 변수는 단 하나의 문자만 저장 가능하고 여러 문자를 저장하기 위해서는 string 타입을 사용해야한다.

1
char ch = 'J' , String name = "Java";

문자열 리터럴은 ““안에 아무런 문자도 넣지 않는 것을 허용하며, 이를 빈 문자열 이라고 한다. 그러나 문자 리터럴은 반드시’‘안에 하나의 문자가 있어야 한다.

그리고 덧셈 연산자를 이용하여 문자열을 결합할 수 있다.

1
2
3
String name = "Ja" + "va";

String str = name + 8.0;

덧셈 연산자는 피여난자가 모두 숫자일 때는 두 수를 더하지만, 피연산자 중 어느 한쪽이 string 이면 나머지 한 쪽을 먼저 string 으로 변환한 다음 두 string을 결합한다. 기본형과 참조형의 구별없이 어떤 타입의 변수도 문자열과 덧셈연산을 수행하면 그 결과 문자열이 되는 것이다.

덧셈 연산자는 왼쪽에서 오른쪽의 방향으로 연산을 수행하므로 결합순서에 따라 결과가 달라진다.

형식화된 출력 - printf()

지금까지 화면에 출력할 때 println()을 써왔는데, println()은 사용하기엔 편하지만 변수의 값을 그대로 출력하므로 , 값을 변환하지 않고는 다른 형식으로 출력할 수 없다. 같은 값이라도 다른 형식으로 출력하고 싶을때가 있다. 예를 들면, 소수점 둘째자리 까지만 출력한다든가, 정수를 16진순나 8진수로 출력한다던가. 이럴때 printf() 를 사용하면 된다.

printf()는 지시자(specifier)을 통해 변수의 값을 여러가지 형식으로 변환하여 출력하는 기능을 가지고 있는데 “지시자”는 값을 어떻게 출력할 것인지를 지정해주는 역할을 한다. 정수형 변수에 저장된 값을 10진 정수로 출력할 때는 지시자 ‘%d’를 사용하며, 변수의 값이 지정된 형식으로 변환해서 지시자 대신 넣는다. 예를 들어 int타입의 변수 age의 값이 14일때 printf()는 지시자 ‘%d’ 대신 14를 넣어서 출력한다.

만일 출력하려는 값이 2개라면 , 지시자도 2개를 사용해야하며 출력될 값과 지시자의 순서는 일치해야한다. 3개 이상도 가능하다.

1
2
3
4
5
6
7
8
9
system.out.printf("age;%d year:%d", age, year);

system.out.printf("age;%d year:%d", 14, 2017);

age:14 year:2017"이 화면에 출력된다.

println()과 달리 printf()는 출력후 줄바꿈을 하지 않는다. 줄바꿈을 하려면 지시자 '%n'을 따로 넣어줘야 한다.

system.out.printf("age;%d%n", age);

printf()의 지시자 중에서 자주 사용되는 것만 뽑아보면 다음과 같다.

% 형식
%b 불리언(boolean) 형식으로 출력
%d 10진 정수의 형식으로 출력
%o 8진 정수의 형식으로 출력
%x,%X 16진 정수의 형식으로 출력
%f 부동 소수점의 형식으로 출력
%e, %E 지수 표현식의 형식으로 출력
%c 문자로 출력
%s 문자열로 출력
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
byte b =1 ;

short s = 2;

char c = 'A';

​

int finger = 10;

long big = 100\_000\_000\_000L;

long hex = 0xFFFF\_FFFF\_FFFF\_FFFFL;

​

int octNum = 010;

int hexNum = 0x10;

int binNum = 0b10;

​

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);

System.out.printf("big=%d%n", big);

System.out.printf("hex=%#x%n", hex);

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);

​

}

실행결과

b=1

s=2

c=A, 65

finger=\[ 10\]

finger=\[10 \]

finger=\[00010\]

big=100000000000

hex=0xffffffffffffffff

octNum=10, 8

hexNum=10, 16

binNum=10, 2

​

정수의 값을 printf()로 출력하는 예제이다. 정수를 출력할 떄는 지시자 ‘%d’를 사용하는데 출력될 값이 차지할 공간을 숫자로 지정할 수 있다.

여러 값을 여러 줄로 간격 맞춰 출력할때 꼭 필요한 기능이다. 아래의 결과를 보면 ‘0’과 ‘-가 어떤 역할을 하는지 알 수 있다.

1
2
3
4
5
System.out.printf("finger=\[%5d\]%n", finger); // finger=\[ 10\]

System.out.printf("finger=\[%-5d\]%n", finger); //finger=\[10 \]

System.out.printf("finger=\[%05d\]%n", finger); //finger=\[00010\]

지시자 ‘%x’와 ‘%o’에 ‘#’을 사용하면 접두사 ‘0x’ 와 ‘0’dl rkrrkr qnxsmsek. rmflrh ‘%X’는 16진수에 사용되는 접두사와 영문자를 대문자로 출력한다.

1
2
3
4
5
System.out.printf("hex=%x%n", hex); // hex= ffffffffffffffff

System.out.printf("hex=%#x%n", hex);//hex=0xffffffffffffffff

System.out.printf("hex=%#X%n", hex);//hex=0xFFFFFFFFFFFFFFFF

10진수를 2진수로 출력해주는 지시자는 없기 떄문에, 정수를 2진 문자열로 변환해주는 Integer.toBinaryString(binNum) 을 사용해주어햐 한다. 이 메서드는 정수를 2진수로 변환해서 문자열로 반환하므로 %s를 사용했다.

1
System.out.printf("binNum=%s, %d%n", Integer.toBinaryString(binNum), binNum);

그리고 c언어 에서는 char 타입의 값을 지시자 ‘%d’로 출력할 수 있지만, 자바에서는 허용 불가능하다.

아래와 같이 int타입으로 형변환 해야만 ‘%d’로 출력 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
System.out.printf("c=%c, %d %n",c , (int)c);

​

public static void main(String\[\] args) {

String url = "[www.codechobo.com"](http://www.codechobo.com%22);

​

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);

System.out.printf("\[%-20s\]%n", url); //            

System.out.printf("\[%.8s\]%n", url); //    ʿ    8   ڸ     

실수형 값의 출력에 사용되는 지시자는 ‘%f’,’%e’,’%g’가 있는데, ‘%f’가 주로 쓰이고 ‘%e’는 지수 형태로 출력할 떄 , ‘%g’는 값을 간략하게 표현할 때 사용한다.

‘%f’는 기본적으로 소수점 아래 6자리 까지만 출력함으로 소수점 아래 7자리에서 반올림한다. 다음과 같이 전체자리수와 아래의 소수점 아래의 수를 지정할 수 도 있다.

System.out.printf(“d=%20.7f%n”, d); // 전체 20자리중 소수점 아래 7자리 전체수의 빈자리는 공백으로 채우고 소수점 수의 빈자리는 0으로 채운다

소수점도 한자리를 차지한다.

지시자 ‘&s’에도 숫자를 추가하면 원하는 만큼의 출력공간을 확보하거나 문자열의 일부만 출력할 수 있다.

1
2
3
4
5
6
7
System.out.printf("\[%s\]%n", url);

System.out.printf("\[%20s\]%n", url);

System.out.printf("\[%-20s\]%n", url);

System.out.printf("\[%.8s\]%n", url);

지정된 숫자보다 문자열의 길이가 작으면 빈자리는 공백으로 출력되며 공백이 있는 경우 우측 끝에 문자열을 붙이고 ‘-‘을 붙이면 좌측 끝에 붙인다. 그리고 ‘.’을 붙이면 문자열의 일부만 출력할 수 있다.

- 화면에서 입력받기 - Scanner

화면으로부터 입력받는 방법에 대해서 배워보자. 먼저 Scanner클래스를 사용하려면, 아래의 한 문장을 추가해줘야 한다.

import java.util.*; // Scanner 클래스를 사용하기 위해 추가

그 다음엔 Scanner 객체를 생성한다.

Scanner scanner = new Scanner(System.in); // Scanner 클래스의 객체를 생성

그리고 nextLine() 이라는 메서드를 호출하면, 입력 대기 상태에 있다가 입력을 마치고 ‘엔터키’를 누르면 입력한 내용이 문자열로 반환된다.

1
2
3
String input = scanner.nextLine(); // 입력받은 내용을 input에 저장

int num = Integer.parseInt(input); // 입력받은 내용을 int타입의 값으로 변환

만일 입력받은 문자열을 숫자로 변환하려면 Integer.parseInt() 라는 메서드를 이용해여 문자열을 int타입의 정수로 반환한다

사실 Scanner 클래스에서 nextInt() 나 nextFloat()와 같이 변환없이 숫자로 바로 입력받을 수 있는 메서드들이 있고, 사용하게 되면 문자열을 숫자로 변환하는 수고는 하지 않아도 되지만 화면에서 연속적으로 값을 입력받아서 사용하기에 까다롭기 때문에 차라리 모든 값을 nextLine()으로 입력받아서 적절히 변환하는것이 더 낫다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.import java.util.\*; // Scanner       ϱ        ߰ 

​

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);

}

}

만일 숫자가 아닌 문자 또는 기호를 입력하면, 입력받은 문자열을 숫자로 변환하는 과정에서 에러가 발생하며 공백을 입력하지 않아야한다.