[java] 2.변수
변수의 정의
프로그래밍 언어에서의 변수란, 값을 저장할 수 있는 메모리상의 공간을 말합니다.
변수는 다음과 같이 선언합니다.
int age;
위의 코드에서 int는 변수 타입이며, 어떤 타입인지를 지정하는 것입니다.
age는 변수 이름이며, 말 그대로 변수에 붙인 이름입니다.
변수를 선언하면, 메모리의 빈 공간에 변수타입에 알맞은 크기의 저장공간이 확보되고,
앞으로 이 저장공간은 변수이름을 통해 사용할 수 있게됩니다.
변수의 초기화는 다음과 같이 합니다.
int age=25; //age라는 변수에 25값을 할당
또 다음과 같이 초기화를 할 수 있습니다.
int age; //age 변수 선언
age=25; //25 값 할당
변수의 명명규칙
<변수의 명명규칙>
1. 대소문자가 구분되며 길이에 제한이 없다.
2. 예약어를 사용해서는 안 된다.
3. 숫자로 시작해서는 안 된다.
4. 특수문자는 '_'와 '$'만을 허용한다.
자바는 유니코드를 사용하기에 한글도 지원가능합니다~!
예약어는 키워드라고도 하는데, 프로그래밍언어의 구문에 사용되는 단어를 뜻합니다.
예약어에 대해서는 후에 천천히 알아보겠습니다.
그 외에 자바 프로그래머들에게 권장하는 규칙은 다음과 같습니다.
1. 클래스 이름의 첫 글자는 항상 대문자로 한다.
2. 여러 단어로 이루어진 이름은 단어의 첫글자를 대문자로 한다.
(단, 변수,메소드 이름은 처음 단어의 첫 글자를 소문자)
3. 상수의 이름은 모두 대문자로 한다. 여러 단어로 이루어진 경우 '_'로 구분한다.
4. 변수의 이름은 용도를 알기 쉽게 의미있는 이름으로 한다.
변수의 타입
우리가 주로 사용하는 값의 종류는 크게 문자와 숫자로 나눌 수 있으며,
숫자는 다시 정수와 실수로 나눌 수 있습니다.
이러한 값의 종류에 따라 값이 저장될 공간의 크기와 저장형식을 정의한 것이 자료형입니다.
자료형은 크게 기본형과 참조형 두 가지로 나눌 수 있습니다.
<기본형>
논리형(boolean), 문자형(char), 정수형(byte, short, int, long), 실수형(float,double)
계산을 위한 실제 값을 저장
<참조형>
객체의 주소를 저장한다. 8개의 기본형을 제외한 나머지 타입
참조형 변수를 선언할 때는 변수의 타입으로 클래스의 이름을 사용하므로 클래스의 이름이
참조변수의 타입이 됩니다.
클래스이름 변수이름;
//기본형이 아닌 것들은 모두 참조변수이다.
기본형
기본형에는 모두 8개의 타입(자료형)이 있으며, 크게 논리형, 문자형, 정수형, 실수형으로 구분됩니다.
논리형: boolean (true와 false 중 하나를 값으로 갖는다.)
문자형: char(문자를 저장하는데 사용)
정수형: byte, short, int, long (주로 int 사용)
실수형: float, double (주로 double 사용)
다음은 각 타입의 변수가 저장할 수 있는 값의 범위입니다.
만약 주어진 범위를 넘어서는 값을 저장하면 오버플로우(overflow),
0에 가까운 너무 작은 값을 저장하면 언더플로우(underflow)가 발생하여
원치 않는 값이 저장됩니다.
또한 C(아스키코드)와 다르게 java는 유니코드를 사용하기에 char형이 1바이트가 아닌 2바이트입니다.
상수와 리터럴
상수는 변수와 마찬가지로 값을 저장할 수 있는 공간이지만,
변수와 달리 한번 값을 저장하면 다른 값으로 변경할 수 없습니다.
상수를 선언하는 방법은 변수와 동일하며, 앞에 final만 붙여주면 됩니다.
final int MAX=10; //상수 MAX 선언
final int MAX;
MAX=10; //ok
MAX=20; //에러
상수를 사용하는 이유는 의미있는 이름을 붙여서 코드의 이해와 수정을 쉽게 만들기 위함입니다
원래 12, 123, 3.14, ‘A’와 같은 값들이 상수인데,
프로그래밍에서는 상수를 값을 한 번 저장하면 변경할 수 없는 저장공간으로 정의하였기에
이와 구분하기 위해 상수 대신에 리터럴이라는 용어를 사용합니다.
int age=25; //25가 정수 리터럴
char ch='a'; //a가 문자 리터럴
long타입 리터럴에는 접미사 L이 붙고, float형 리터럴에는 접미사 f가 붙습니다.
<타입의 불일치>
리터럴의 타입은 저장될 변수의 타입과 일치하는 것이 보통이지만,
타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용된다.
int i='A'; //OK
long l=123; //OK
double d=3.14f; //OK
하지만, 리터럴의 값이 변수의 타입의 범위를 넘어서거나,
리터럴의 타입이 변수의 타입보다 저장범위가 넓으면 컴파일 에러가 발생한다.
int i=Ox123456789; //에러 int 타입의 범위를 넘는 값을 저장
float f=3.14; //에러 float 타입보다 double 타입의 범위가 넓다.
//3.14는 3.14d에서 d가 생략된 형태로 double 형이다
<문자 리터럴과 문자열 리터럴>
문자 리터럴은 ' '로 감싸고(적어도 하나의 문자포함),
문자열 리터럴은 " "로 감싼다(내용이 없어도 된다).
String str=""; //OK 내용이 없는 빈 문자열
char ch=''; //에러, ''에는 적어도 하나의 문자 필요
char ch=' '; //OK 공백문자로 변수 ch 초기화
위에서 String은 문자열을 저장하는 문자열 타입으로 클래스 입니다.
원래 다음과 같이 선언해야하나
String name=new String("java"); //String 객체 생성
객체를 생성하는 new를 사용안하고도 String 객체를 생성할 수 있습니다.
String name="java";
덧셈 연산자를 이용하여 문자열을 결합할 수도 있습니다.
String name="ja"+"va"; //name은 java
기본형과 참조형의 구별 없이 어떤 타입의 변수도 문자열과 덧셈연산을 수행하면
그 결과가 문자열이 됩니다.
문자열+any type->문자열+문자열->문자열
any type+문자열->문자열+문자열->문자열
ex) System.out.println(7+7+""); //문자열 14 출력
정수 7과 정수 7을 더하면 정수 14가 되고 문자열 ""과 더해져서 문자열 14
System.out.println(""+7+7); //문자열 77 출력
문자열 ""과 정수 7이 더해져서 문자열 7이되고, 정수 7과 더해져서 문자열 77
형식화된 출력 printf()
일반적으로 자바에서는 화면에 문자열을 출력할 때 다음과 같이 println을 사용합니다.
System.out.println("java"); //자동 개행 이뤄짐
System.out.print("java"); // 개행이 이뤄지지 않음
println()은 사용하기엔 편하지만 변수의 값을 그대로 출력하므로,
값을 변환하지 않고는 다른 형식으로 출력할 수 없습니다.
같은 값이라도 다른 형식으로 출력하고 싶을 때가 있습니다.
예를 들어 소수점 둘째자리까지만 출력한다던가, 정수를 16진수나 8진수로 출력한다던가,
이럴 때는 printf()를 사용합니다. (C와 동일합니다.)
int num=100;
System.out.printf("num: %d ",num); //정수 100 출력
System.out.printf("num: %o",num); //8진법 144 출력
System.out.printf("num: %x",num); //16진법 64 출력
위의 사용된 %d, %o, %x를 지시자(서식문자)라고 하며, 변수를 지정된 형식으로 출력시켜주는 역할을 합니다.
다음은 자주 사용되는 지시자입니다.
%f : 부동 소수점 형식으로 출력
%e, %E : 지수 표현식의 형식으로 출력
%c : 문자로 출력
%s : 문자열로 출력
정수를 출력할 대 지시자 %d를 사용하는데, 출력될 값이 차지할 공간을 숫자로 지정할 수 있습니다.
int num=10;
//num=[ 10] 출력(다섯자리 확보 후 왼쪽부터 채운다.)
System.out.printf("num=[%5d]\n",num);
//num=[10 ] 출력(다섯자리 확보 후 오른쪽부터 채운다.)
System.out.printf("num=[%-5d]\n",num);
//num=[00010] 출력(다섯자리 확보 후 오른쪽부터 채우고 나머지는 0으로 채운다.)
지시자 %x와 %o에 #을 사용하면 접두사 0x와 0가 붙습니다.
그리고 %X는 16진수에 사용되는 접두사와 영문자를 대문자로 출력합니다.
int hex=-1;
System.out.printf("hex=%x\n",hex); //ffffffff 출력
System.out.printf("hex=%#x\n",hex); //0xffffffff 출력
System.out.printf("hex=%#X\n",hex); //0XFFFFFFFF 출력
10진수를 2진수로 출력해주는 지시자는 없기 때문에,
정수를 2진 문자열로 변환해주는 Integer.toBinaryString(int i)를 사용해야 합니다.
이 메서드는 정수를 2진수로 변환해서 문자열로 반환하므로 지시자 %s를 사용합니다.
//1100100 출력
System.out.printf("binNum=%s\n",Integer.toBinaryString(100));
그리고 C언어에서는 char 타입의 값을 지시자 %d로 출력할 수 있지만, 자바에서는 허용되지 않습니다.
따라서 int 타입으로 형변환을 해야만 %d로 출력할 수 있습니다.
char ch='A';
System.out.printf("%d",(int )ch); //int형으로 형변환 후 %d로 출력
실수형 값의 출력에 사용되는 지시자는 %f, %e, %g가 있는데, %f가 주로 쓰입니다.
%f는 기본적으로 소수점 아래 6자리까지만 출력하기 때문에 소수점 아래 7자리에서 반올림합니다.
따라서 원하는데로 소수점을 출력하고 싶으면 다음과 같이 합니다.
double num=1.123456789;
System.out.printf("%14.10f",num); // 1.2345678900 출력
//14자리 확보후 소수점 10자리 출력
화면에서 입력받기 - Scanner
지금까지 화면에 출력만 해봤는데요!
화면으로부터 입력을 받을 때는 Scanner 클래스를 이용합니다.
import java.util.*; //Scanner 클래스를 사용하기 위해 추가
Scanner sc=new Scanner(System.in); //Scanner 클래스의 객체를 생성
String input=sc.nextLine(); //입력받은 내용(문자열)을 input에 저장
int num=Integer.parseInt(input); //입력 받은 문자열을 int 타입으로 변환
//여기서 Integer 클래스의 parseInt 메소드는 입력받은 문자열을 정수형으로 변환해줍니다.
위의 예제에서 Scanner 클래스의 nextInt 메소드를 이용해 바로 정수를 입력받을 수도 있습니다.
int num=sc.nextInt();
다음은 Scanner 클래스 관련 예제입니다.
특수문자
다음은 ‘\n’ 개행과 같이 특수하게 사용되는 문자를 나타낸 것입니다.
형변환(Casting)
모든 변수와 리터럴에는 타입이 있다는 것을 배웠습니다.
프로그램을 작성하다 보면 같은 타입뿐만 아니라 서로 다른 타입간의 연산을 수행해야하는 경우도 있습니다.
이럴 때는 연산을 수행하기 전에 타입을 일치시켜야 하는데,
변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형변환이라고 합니다.
형변환의 방법은 아주 간단합니다.
(타입)피연산자
위에서 사용하는 괄호()는 캐스트 연산자, 형변환 연산자라고 합니다.
double d=85.4;
int score=(int)d; //double타입의 변수 d를 int타입으로 형변환 85저장
기본형에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능합니다.
하지만 기본형과 참조형간의 형변환은 불가능합니다~
참조형 형변환은 나중에(상속을 배운후) 설명하겠습니다.
그리고 실수형에서 정수형으로 형변환이 이뤄질 경우
소수점 이하 자리는 버려집니다.(반올림 x)
정수형에서 실수형으로 형변환이 이뤄질 경우
실수형의 정밀도의 제한으로 인한 오차가 발생할 수 있습니다.
오차를 최대한 줄이려면 int형을 double형으로 바꿔주는 것이 좋다.
//예
int i=91234567;
float f=(float)i; //91234568 저장(오차)
double d=(double)d; //91234567 저장
서로 다른 타입간의 대입이나 연산을 할 때,
형변환으로 타입을 일치시키는 것이 원칙입니다. 하지만 경우에 따라 편의상의 이유로
형변환을 생략할 수 있습니다. 그렇다고 해서 형변환이 이루어지지 않은 것은 아니고,
컴파일러가 생략된 형변환을 자동적으로 추가합니다.
이를 자동형변환이라고 합니다.
float f=1234; //형변환의 생략 float f=(float)1234; 와 같음
그러나 다음과 같이 변수가 저장할 수 있는 값의 범위보다 더 큰 값을 저장하려는 경우에
형 변환을 하면 에러가 발생합니다.
byte b=1000; //에러 byte의 범위(-128~127)
하지만 다음과 같이 명시적으로 형변환 해줬을 경우에는
형변환이 프로그래머의 실수가 아닌 의도적인 것으로 간주하고 컴파일러는 에러를 발생시키지 않습니다.
char ch=(char)1000; //명시적 형변환, 에러가 발생하지 않는다.
<자동형변환 규칙>
기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환 한다.