JAVA

혼공자2.변수와 타입, 자동&강제타입변환, 입출력, System.in.read단점 및 해결책

나는나는용 2023. 2. 20. 18:48
728x90

2. 변수와 타입

2-1. 변수

값을 저장할 수 있는 메모리의 특정 번지에 붙이는 이름.
변수 선언 ➡ 변수에 값 지정 ➡ 메모리에 값 저장
두가지 값을 동시에 저장 불가.

변수 선언

'저장할 데이터 타입', '변수 이름' 결정.
콤마를 이용하여 한번에 선언 가능(ex. int x,y;)
타입 = 자료형
정수형: int
실수형: double
변수 이름 명명 규칙
• 첫 글자는 '문자','$','_' 중 하나.
• 영어 대소문자 구분.
• 첫 문자는 영어 소문자로 시작하나, 다른 단어가 붙을 경우 첫 문자를 대문자로.(ex. maxSpeed)
•문자 수(길이) 제한 없음.
•자바 예약어는 사용 불가.

+)예약어
이미 해당 프로그래밍 언어에서 의미를 갖고 사용되고 있는 단어.

값 저장

대입연산자 =을 사용하여 값 저장.
변수에 값이 저장되지 않으면 변수가 생성(!= 선언)되지 않음.
변수 초기화: 변수에 최초로 값이 저장될 때 변수가 생성되는 것.
초기값: 변수 초기화를 할 때 저장한 값.

아래의 예제에서는 초기화되지 않은 변수 value를 사용하여 컴파일 에러 발생

변수 사용

출력문이나 연산식 내부에서 변수에 저장된 값을 출력하거나 연산할 때 사용.


변수는 또 다른 변수에 대입하여 값을 복사할 수 있음.
아래 예제는 이 특징을 이용하여 두 값을 교환

변수 사용 범위

변수는 중괄호 블록 내에서 선언되고, 선언된 위치로부터 자신이 속한 블록 내부에서만 사용 가능.
로컬 변수: 메소드 블록 내에서 선언/사용되고, 메소드 실행 종료시 메모리에서 자동 삭제됨.

아래 예제의 v2는 v2가 선언된 if블록 내부에서만 사용 가능하므로 에러 발생


변수 선언 주의 사항

변수가 어떤 범위에서 사용될 것인지 생각 ➡ 선언 위치 결정
메소드 블록 전체에서 사용하고 싶다면 메소드 블록 첫머리에 선언.
특정 블록 내부에서만 사용된다면 해당 블록 내에 선언.

2-2. 기본 타입

정수: byte(1), char(2), short(2), int(4), long(8)
실수: float, double
논리: boolean

정수

+) 리터럴: 소스코드에서 프로그래머에 의해 직접 입력된 값.

정수리터럴

  • 2진수: 0b / 0B 로 시작
  • 8진수: 0 으로 시작
  • 10진수: 소수점 없음
  • 16진수: 0x / 0X 로 시작

다양한 정수 리터럴을 int타입 변수에 저장하여 10진수로 출력

package sec02.exam01;
public class IntegerLiteralExample {
	public static void main(String[] args) {
		int var1=0b1011;
		int var2=0206;
		int var3=365;
		int var4=0XB3;
		System.out.println("var1:"+var1);	//2진수
		System.out.println("var2:"+var2);	//8진수
		System.out.println("var3:"+var3);	//10진수
		System.out.println("var4:"+var4);	//16진수
	}
}

실행 결과


byte타입 변수에 허용 범위 초과한 값 대입했을 경우, 컴파일 에러

package sec02.exam02;
public class ByteExample {
	public static void main(String[] args) {
		byte var1=-128;
		byte var2=-30;
		byte var3=0;
		byte var4=30;
		byte var5=127;
		byte var6=128;	//컴파일 에러
		System.out.println(var1);
		System.out.println(var2);
		System.out.println(var3);
		System.out.println(var4);
		System.out.println(var5);
	}
}

long 타입은 수치가 큰 데이터를 다루는 프로그램에서 주로 사용

long balance=3000000000000l;
long bal=30;	//int타입의 허용 범위 이내라면 l붙이지 않아도 됨.

char '문자'
유니코드(정수)로 변환되어 저장됨.

다음은 여러 형태로 동일 문자를 나타내는 예제

package sec02.exam04;
public class CharExample {
	public static void main(String[] args) {
		char c1='A';	//직접 저장
		char c2=65;		//10진수로 저장
		char c3='\u0041';	//16진수로 저장
		int var1='A';		
		System.out.println(c1);
		System.out.println(c2);
		System.out.println(c3);
		System.out.println(var1);
	}
}

실행결과


String "문자열"
기본타입이 아닌 클래스 타입 (6장에서 계속)

package sec02.exam05;
public class StringExample {
	public static void main(String[] args) {
		String name="남인경";
		String job="학생";
		System.out.println(name);
		System.out.println(job);
	}
}

실행결과

이스케이프 문자 \
-문자열 식별기호로 쓰이는 문자를 그대로 사용하고 싶을 경우 사용함
-출력 제어용으로도 사용
--(ex. 탭: \t, 줄바꿈: \n, 캐리지리턴:\r, "출력:\", '출력: \', \출력: \\, 16진수 유니코드에 해당하는 문자 출력: \u16진수)

package sec02.exam06;
public class EscapeExample {
	public static void main(String[] args) {
		System.out.println("번호\t이름\t직업");
		System.out.print("행 단위 출력\n");
		System.out.print("행 단위 출력\n");
		System.out.println("우리는 \"개발자\" 입니다.");
		System.out.print("봄\\여름\\가을\\겨울");
	}
}

실행결과

실수

실수리터럴

  • float: 4바이트, 소수점 이하 7자리
  • double: 8바이트, 소수점 이하 15자리
    +) 기본적으로 double로 해석. 실수 리터럴을 float에 저장할 시 컴파일 에러가 발생하므로 뒤에 f나 F 입력.
package sec02.exam07;
public class FloatDoubleExample {
	public static void main(String[] args) {
		float var1=3.14; //컴파일 에러
		float var2=3.14f;
		double var3=3.14;
		//정밀도 테스트
		float var4=0.1234567890123456789f;
		double var5=0.1234567890123456789;
		System.out.println("var2: "+var2);
		System.out.println("var3: "+var3);
		System.out.println("var4: "+var4);
		System.out.println("var5: "+var5);
		//e사용
		double var6=3e6;
		float var7=3e6f;
		double var8=2e-3;
		System.out.println("var6: "+var6);
		System.out.println("var7: "+var7);
		System.out.println("var8: "+var8);
	}
}

실행결과

논리

논리 리터럴 (1바이트)
주로 두 가지 상태값에 따라 조건문과 제어문의 실행 흐름을 변경하는 데 사용

  • boolean
    true & false
package sec02.exam08;
public class BooleanExample {
	public static void main(String[] args) {
		boolean stop=true;
		if(stop) {
			System.out.println("중지합니다.");
		}
		else {
			System.out.println("시작합니다.");
		}
	}
}

실행결과

2-3. 타입 변환

데이터 타입을 다른 데이터 타입으로 변환하는 것.
타입 변환이 줄면 실행 성능 향상됨.

사용하는 이유:
두 변수 타입이 다른 경우에는 한쪽 변수값을 다른 쪽 변수에 복사 저장이 불가할 수 있음.

자동 타입 변환

값의 허용 범위가 작은 타입이 허용 범위가 큰 타입으로 저장될 때.

  • byte < short < int < long < float < double
    * byte ➡ int: 가능
    * 정수형 ➡ 실수형: 가능
    * char ➡ int: 가능 (유니코드 값이 저장됨.)
    **byte ➡ char: 불가능 (∵byte는 음수 포함하나 char는 양수만 표현)

    다양한 자동 타입 변환 예제
package sec03.exam01;
public class PromotionExample {
	public static void main(String[] args) {
		//byte를 int로
        byte byteValue=10;
		int intValue=byteValue;
		System.out.println("intValue: "+ intValue);
        //char를 int로
		char charValue='가';
		intValue=charValue;
		System.out.println("가의 유니코드: "+ intValue);
		//int를 long으로
        intValue=50;
		long longValue=intValue;
		System.out.println("longValue: "+ longValue);		
		//long을 float으로
        longValue=100;
		float floatValue=longValue;
		System.out.println("floatValue: "+ floatValue);
		//float을 double로
        floatValue=100.5f;
		double doubleValue=floatValue;
		System.out.println("doubleValue: "+ doubleValue);
	}
}

실행결과

강제 타입 변환 (캐스팅)

값의 허용 범위가 큰 타입을 허용 범위가 작은 타입으로 나눠서 저장.
* int ➡ byte
* int ➡ char: 문자 출력
* 실수형 ➡ 정수형: 정수 부분만 저장됨.

다양한 강제 타입 변환 예제

package sec03.exam02;
public class CastingExample {
	public static void main(String[] args) {
		//int형을 char형으로
		int intValue=44032;
		char charValue=(char)intValue;
		System.out.println(charValue);
		//long형을 int형으로
		long longValue=500;
		intValue=(int)longValue;
		System.out.println(intValue);
		//double형을 int형으로
		double doubleValue=3.14;
		intValue=(int)doubleValue;
		System.out.println(intValue);
	}
}

실행결과

정수 연산에서의 자동 타입 변환

정수 타입 변수가 산술 연산식에서 피연산자로 사용될 때, int타입보다 작은 byte, short타입 변수들은 int형으로 자동 형변환되어 연산됨.

ex)
int result = (byte,char,short,int) 연산자 (byte,char,short,int)

  • byte타입 변수가 피연산자로 사용된 경우
 byte x=10;
 byte y=20;
 int result=x+y; 
 /* byte result=x+y */	
 //피연산자가 byte타입인 x,y이므로 연산 수행시 자동으로 x,y의 자료형은 int형이 됨.

+) 자바는 실행 성능 향상을 위해 컴파일 단계에서 연산을 수행함.

package sec03.exam03;
public class ByteOperationExample {
	public static void main(String[] args) {
		//피연산자가 변수가 아니므로 int타입으로 변환하지 않음.
		byte result1=10+20;
		System.out.println(result1);
		//피연산자가 byte 변수이므로 int타입으로 변환함.
		byte x=10;
		byte y=20;
		int result2=x+y;
		System.out.println(result2);
	}
}

실행결과


+) 정수 연산식에서 모든 변수가 int타입으로 변환되는 것은 아님. 두 피연산자 중 허용 범위가 큰 타입으로 변환됨.

ex)
long result = long 연산자 (byte,char,short,int)

package sec03.exam04;
public class LongOperationExample {
	public static void main(String[] args) {
		byte value1=10;
		int value2=100;
		long value3=1000L;
		long result=value1+value2+value3;
		System.out.println(result);
	}
}

실행결과

실수 연산에서의 자동 타입 변환

실수 타입 변수가 산술 연산식에서 피연산자로 사용될 때,
-두 피연산자가 동일 타입: 해당 타입으로 연산
-하나가 double: 다른 피연산자도 double로 자동 타입 변환되어 연산 결과는 double이 됨.
-int와 double: int가 double로 자동 타입 변환되어 연산.
--꼭 int로 연산해야할 시: double을 int로 강제 변환하여 연산.
+) 자바에서 정수 연산의 결과는 정수이므로, 실수형의 결과를 얻고 싶다면 피연산자들 중 최소한 하나를 실수형으로 강제 형변환을 해야함.

다음은 연산식에서의 자동 타입 변환을 다룬 예제

package sec03.exam05;
public class OperationsPromotionExample {
	public static void main(String[] args) {
		//byte들의 연산결과 int로
		byte byteValue1=10;
		byte byteValue2=20;
		//byte byteValue3=byteValue1+byteValue2;
		int intValue1=byteValue1+byteValue2;
		System.out.println(intValue1);
		//char들의 연산결과 int로
		char charValue1='A';
		char charValue2=1;
		//char charValue3=charValue1+charValue2;
		int intValue2=charValue1+charValue2;
		System.out.println("유니코드"+intValue2);
		System.out.println("출력문자"+(char)intValue2);
		//정수들의 나눗셈 결과는 정수
		int intValue3=10;
		int intValue4=intValue3/4;
		System.out.println(intValue4);
		//정수와 실수의 나눗셈 결과는 실수
		int intValue5=10;
		//int intValue6=10/4.0;		//정수10을 실수4.0으로 나눈 결과는 실수이므로
		double doubleValue=intValue5/4.0;
		System.out.println(doubleValue);
		//정수 하나를 실수로 타입변환하여 나머지 정수와 연산 결과 실수
		int x=1;
		int y=2;
		double result=(double)x/y;
		System.out.println(result);
		double result2=(double)(x/y);	// (x/y)가 먼저 연산된 뒤 실수화하여 0.0 출력
		System.out.println(result2);	
	}
}

실행결과

+연산에서의 문자열 자동 타입 변환

'+'의 역할

  • 숫자+숫자: ➡ 덧셈 연산 ➡ 숫자
  • "문자열"+숫자: ➡ "문자열"+"숫자" ➡ 결합 연산 ➡"문자열숫자"
  • 숫자+"문자열": ➡ "숫자"+"문자열" ➡ 결합 연산 ➡"숫자문자열"
  • +연산자가 연이어 나올 때, 앞에서부터 순차적으로 +연산 수행.
    먼저 수행된 연산이 덧셈 연산: 덧셈 결과 갖고, 다음 +연산 수행.
    먼저 수행된 연산이 결합 연산: 이후 +연산은 모두 결합 연산.
    +) 우선 계산하고 싶은 부분은 괄호()로 감싸준다.

다음은 문자열 결합 연산 예제

package sec03.exam06;
public class StringConcatExample {
	public static void main(String[] args) {
		//숫자 연산
		int value = 10 + 2 + 8;
		System.out.println("value: " + value);
		//문자열 결합 연산
		String str1 = 10 + 2 + "8";
		System.out.println("str1: " + str1);
		String str2 = 10 + "2" + 8;
		System.out.println("str2: " + str2);
		String str3 = "10" + 2 + 8;
		System.out.println("str3: " + str3);
		String str4 = "10" + (2 + 8);
		System.out.println("str4: " + str4);
	}
}

실행결과

문자열을 기본 타입으로 강제 타입 변환

String str = "10";
String str1 = "12.345";
String str2 = "true";
byte value = Byte.parseByte(str); 			//byte 
short value = Short.parseShort(str); 		//short
int value = Integer.parseInt(str);			//int
long value = Long.parseLong(str);			//long
float value = Float.parseFloat(str1);		//float
double value = Double.parseDouble(str1); 	//double
boolean value = Boolean.parseBoolean(str2); //boolean
//
/*숫자가 아닌 알파벳,특수문자,한글 등을 포함한 문자열
숫자 형식 예외 (NumberFormatException) 발생
String str3 = "1a";
int value = Integer.parseInt(str3);
*/
// 간단하게 기본 타입의 값을 문자열로 변경하는 경우 메소드 이용
String str=String.valueOf(3); // "3"

다음은 기본 타입과 문자열 간의 변환 예제

package sec03.exam07;
public class PrimitiveAndStringConversionExample {
	public static void main(String[] args) {
		//기본 타입으로 변경
		int value1= Integer.parseInt("10");			
		double value2 = Double.parseDouble("3.14"); 	
		boolean value3 = Boolean.parseBoolean("true");
		System.out.println("value1: "+value1);
		System.out.println("value2: "+value2);
		System.out.println("value3: "+value3);
		//메소드 이용하여 문자열로 변경
		String str1 = String.valueOf(10);
		String str2 = String.valueOf(3.14);
		String str3 = String.valueOf(true);
		System.out.println("str1: "+str1);
		System.out.println("str2: "+str2);
		System.out.println("str3: "+str3);
	}
}

실행결과

2-4. 변수와 시스템 입출력

표준 출력 장치: System.out.println();
표준 입력 장치: System.in.read();

모니터로 변수값 출력하기

메소드의 괄호 안에 리터럴을 넣으면 리터럴 출력, 변수를 넣으면 변수에 저장된 값 출력.

  • println(내용); : 괄호 안의 내용을 출력하고 행을 바꿔라.
  • print(내용); : 괄호 안의 내용을 출력하라.
  • printf("형식문자열", 값1, 값2...); : 괄호 안의 첫 번째 문자열 형식대로 내용을 출력하라.
    • 형식문자열
      %[argument_index$][flags][width][.precision]conversion(변환문자)에서 %와 conversion사이의 항목들은 생략이 가능하다.
      • conversion: d(정수), f(실수), s(문자열)
      • argument_index$ : 만약 포함될 값이 2개 이상일 경우에는 값의 순번을 알려줘야 한다.
        ex) System.out.printf("이름: %1$s, 나이:%2$d", "김자바", 25);
      • flags: 빈 자리를 채우는 방법.
        생략: 왼쪽이 공백으로 채워짐.
        -: 오른쪽이 공백으로 채워짐.
        0: 공백 대신 0으로 채워짐.
      • .precision: 소수 자릿수

다음은 printf()메소드의 예제

package sec04.exam01;
public class PrintfExample {
	public static void main(String[] args) {
		int value=123;
		//정수
		System.out.printf("상품의 가격:%d원\n",value);
		System.out.printf("상품의 가격:%6d원\n",value);
		System.out.printf("상품의 가격:%-6d원\n",value);
		System.out.printf("상품의 가격:%06d원\n",value);
		//실수
		double area=3.14159*10*10;
		System.out.printf("반지름이 %d인 원의 넓이: %10.2f\n",10,area);
		//문자열
		String name="홍길동";
		String job="도적";
		System.out.printf("%6d | %-10s | %10s\n",1,name,job);
	}
}

실행결과

키보드에서 입력된 내용을 변수에 저장하기

키코드: 키보드에서 키 하나를 입력하면 프로그램이 읽을 수 있는 숫자.

int keyCode = System.in.read();	//읽은 키코드를 int변수 keyCode에 저장.

다음은 입력된 키코드를 변수에 저장하는 예제
"a와 enter를 입력했을 때" (System.in.read()의 키코드는 13, 10이므로 a한 문자만 입력해도 종결.)

package sec04.exam02;
public class KeyCodeExample {
	public static void main(String[] args) throws Exception{
		int keyCode;
		keyCode= System.in.read();
		System.out.println("keyCODE: "+ keyCode);
		keyCode=System.in.read();		//enter입력에 대해 먼저 캐리지리턴(13)
		System.out.println("keyCODE: "+ keyCode);
		keyCode=System.in.read();		//enter입력에 대한 라인 피드(10)
		System.out.println("keyCODE: "+ keyCode);
	}
}

실행결과


다음은 입력 키 개수 상관없이 모든 키코드를 읽는 예제

package sec04.exam03;
public class ContinueKeyCodeReadExample {
	public static void main(String[] args) throws Exception{
		int keyCode;
		while(true) {	//무한반복
			keyCode=System.in.read();
			System.out.println("keyCode: " + keyCode);
		}
	}
}

(무한 반복을 중지하려면 콘솔창의 빨간 버튼 클릭)
실행결과


다음은 사용자가 q를 입력하면 반복이 종료되는 예제

package sec04.exam04;
public class QStopExample {
	public static void main(String[] args) throws Exception {
		int keyCode;
		while(true) {
			keyCode=System.in.read();
			System.out.println("keyCode: " + keyCode);
			if(keyCode==113) {
				break;
			}
		}
		System.out.println("종료");
	}
}

실행결과

System.in.read()의 단점

:2개 이상의 키가 조합되면 읽을 수 없다. 키보드로부터 입력된 내용을 통 문자열로 읽지 못함
➡해결책: Scanner 클래스 사용.

//생성된(new)Scanner를 변수 scanner에 저장.
Scanner scanner=new Scanner(System.in);
//엔터키 이전까지 입력된 문자열을 읽어 inputData에 저장.
String inputData=scanner.nextLine();

다음은 키보드에서 입력된 내용을 문자열로 읽고 출력하는 예제

package sec04.exam05;
import java.util.Scanner;	//Scanner클래스는 java.util패키지에.
public class ScannerExample {
	public static void main(String[] args) throws Exception {
		Scanner scanner=new Scanner(System.in);
		String inputData;
		while(true) {
			inputData=scanner.nextLine();
			System.out.println("입력된 문자열: \""+inputData + "\"");
		    if(inputData.equals("q")) {	//문자열 동일 비교 메소드
		    	break;
		    }
		}
		System.out.println("종료");
	}
}

실행결과

  • 기본 타입의 값이 동일한지 비교할 때에는 == 사용.

문자열이 동일한지 비교할 때에는 equals() 메소드 사용.
문자열 비교

728x90