1. 스코프, 형변환
1) 지역변수와 스코프
- 지역변수: 특정 지역에서 사용할 수 있는 변수
package scope;
public class Scope1 {
public static void main(String[] args) {
int m = 10;
if(true) {
int x = 20;
System.out.println("if m = " + m);
System.out.println("if x = " + x);
}
System.out.println("main x = " + m);
}
}
- main() 메서드의 코드 블록 안에서 선언
- main 메서드가 종료될때까지 생존.
- if() 블록 안에서 선언되었고 if문이 종료될때까지 생존
- if문 이후에 접근하게 되면 cannot find symbol 이라는 변수 이름을 찾을 수 없다는 컴파일 오류 발생
(1) 예시: for문을 활용한 스코프
package scope;
public class Scope2 {
public static void main(String[] args) {
int m = 10;
for(int i=0; i<2; i++) {
System.out.println("for m = " + m);
System.out.println("for i = " + i);
}
}
}
2) 스코프 존재 이유
package scope;
public class Scope3_1 {
public static void main(String[] args) {
int m = 10;
int temp = 0;
if(m > 0) {
temp = m * 2;
System.out.println("temp = " + temp);
}
System.out.println("m = " + m);
}
}
- 현재 전역변수에 m, temp가 존재함.
- temp는 if문에 위치해야 메모리 관리에 적절함.
- 하지만, 현재 코드를 보면 temp는 전역변수 main 메서드 안에 위치되어 있어 비효율적인 메모리 사용
- 그리고 코드 복잡성이 증가된다. if문이 종료되면 이후에 코딩할때 m과 temp를 신경써야 한다.
- 위 문제점들을 보완한 코드는 다음과 같다.
package scope;
public class Scope3_2 {
public static void main(String[] args) {
int m = 10;
if(m > 0) {
int temp = m * 2;
System.out.println("temp = " + temp);
}
System.out.println("m = " + m);
}
}
- if문이 아니더라도 for문과 while문에서도 스코프를 적용할 수 있다.
package loop;
public class While2_3 {
public static void main(String[] args) {
int sum = 0;
int i = 1;
int endNum = 10;
while (i <= endNum) {
sum = sum + i;
System.out.println("i=" + i + ", sum=" + sum);
i++;
}
}
}
- while문은 i의 스코프가 main메서드 전체가 된다.
package loop;
public class For2 {
public static void main(String[] args) {
int sum = 0;
int endNum = 3;
for(int i=1; i<=endNum; i++) {
sum = sum + i;
System.out.println("i=" + i + ", sum=" + sum);
}
}
}
- for문은 i의 스코프가 for문 안에 위치되어있다.
- 따라서, 변수 i와 같이 for문 안에서만 사용할 수 있는 카운터변수가 존재한다면 for문을 사용해서 스코프 범위를 줄인다.
스코프 정리
- 변수는 범위를 한정해서 사용하자.
- 좋은 프로그램은 적절한 제약이 있는 프로그램이다.
2. 형변환
1) 자동 형변환
(1) 형변환
int < long < double
- int보다는 long . long보다는 double
- 큰 범위에서 작은 범위는 소수점을 버리거나 오버플로우 발생
doubleValue = intValue;
doubleValue = (double) intValue;
doubleValue = (double) 10;
doubleValue = 10.0;
package casting;
public class Casting1 {
public static void main(String[] args) {
int intValue = 10;
long longValue;
double doubleValue;
longValue = intValue;
System.out.println("longValue = " + longValue);
doubleValue = intValue;
System.out.println("doubleValue = " + doubleValue);
doubleValue = 20L;
System.out.println("doubleValue2 = " + doubleValue);
}
}
2) 명시적 형변환
package casting;
public class Casting2 {
public static void main(String[] args) {
double doubleValue = 1.5;
int intValue = 0;
intValue = (int) doubleValue;
System.out.println(intValue);
}
}
(1) 형변환(캐스팅)
- 개발자가 직접 감수하고도 값을 대입하고자 할때 타입을 강제로 변경
1) 형변환 과정
intValue = (int) doubleValue;
intValue = (int) 2.5;
intValue = 2;
(2) 형변환과 오버플로우
- 형변환할때 만약 작은 숫자가 표현할 수 있는 범위를 넘어선다면 오버플로우 발생.
package casting;
public class Casting3 {
public static void main(String[] args) {
long maxIntValue = 2147483647;
long maxIntOver = 2147483648L;
int intValue = 0;
intValue = (int) maxIntValue;
System.out.println("maxIntValue casting = " + intValue);
intValue = (int) maxIntOver;
System.out.println("maxIntOver casting = " + intValue);
}
}
maxIntOver = 214783648L;
intValue = (int) maxIntOver;
intValue = (int) 214783648L;
intValue = -214783648;
- 기존 범위를 벗어나면 오버플로우가 발생하여 처음 값부터 다시 시작.
- 이 경우 int형에서 long형으로 다시 변환해주면 문제 해결됨.
3) 계산과 형변환
package casting;
public class Casting4 {
public static void main(String[] args) {
int div1 = 3 / 2;
System.out.println("div1 = " + div1);
double div2 = 3 / 2;
System.out.println("div2 = " + div2);
double div3 = 3.0 / 2;
System.out.println("div3 = " + div3);
double div4 = (double) 3 / 2;
System.out.println("div4 = " + div4);
int a = 3;
int b = 2;
double result = (double) a / b;
System.out.println("result = " + result);
}
}
- 같은 타입끼리의 연산은 같은 타입의 결과만
- 서로 다른 타입의 계산은 큰 범위로 자동 형변환