혼공자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블록 내부에서만 사용 가능하므로 에러 발생
변수 선언 주의 사항
변수가 어떤 범위에서 사용될 것인지 생각 ➡ 선언 위치 결정 메소드 블록 전체에서 사용하고 싶다면 메소드 블록 첫머리에 선언. 특정 블록 내부에서만 사용된다면 해당 블록 내에 선언.
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진수
}
}
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 입력.
값의 허용 범위가큰 타입을허용 범위가작은 타입으로 나눠서저장. * 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);
}
}
실행결과
+연산에서의 문자열 자동 타입 변환
'+'의 역할
숫자+숫자: ➡ 덧셈 연산 ➡ 숫자
"문자열"+숫자: ➡ "문자열"+"숫자" ➡ 결합 연산 ➡"문자열숫자"
숫자+"문자열": ➡ "숫자"+"문자열" ➡ 결합 연산 ➡"숫자문자열"
+연산자가 연이어 나올 때, 앞에서부터 순차적으로 +연산 수행. 먼저 수행된 연산이 덧셈 연산: 덧셈 결과 갖고, 다음 +연산 수행. 먼저 수행된 연산이 결합 연산: 이후 +연산은 모두 결합 연산. +) 우선 계산하고 싶은 부분은 괄호()로 감싸준다.
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("종료");
}
}