JAVA/이론 정리 및 예제

[JAVA/자바] #1_2 변수 - 상수, 형변환, 오버플로우 / 예제

chaewon 2021. 9. 3. 13:46

상수

한 번만 저장할 수 있는 공간으로 초기화 이후 다른 데이터(값)을 대입할 수 없다.

상수선언

final int AGE;            // 상수선언시 변수명은 반드시 대문자로

 

오버플로우

127 + 1 을 하면 범위를 초과한 128이 되고 허용된 범위 이상의 비트를 침범하게 되는데

이를 오버플로우라고 한다.

 

127(범위의 최대 값)에 +1을 하면 범위의 최소 값으로 돌아와야 한다.

ex) 127 + 1 = -128

     127 + 3 = -126

    -> 0111111 (127) + 1

        0000000 (carry 1 발생) // carry가 발생하면 부호 비트가 바뀐다.

        1000000

          

 

형변환

같은 자료형 끼리만 대입(계산) 가능

계산의 결과도 같은 종류의 값이 나와야 함

    => 원칙이 지켜지지 않은 경우에 형변환이 필요하다.

 

자동형변환 (묵시적 형변환)

  • 값이 작은 곳(int) -> 큰 곳(long)으로 이동할 때
  • 정수형 -> 실수형으로 형변환 할 때
    • byte -> short -> int -> float -> double
  • char -> short 로는 자동형변환 하지 못 한다. (범위가 달라서)
    • char -> int로 자동형변환이 일어난다.
    • byte _ int = int
    • short + int = int
    • byte + byte = int        // 예외적인 상황
    • short + short = int      // int 미만의 것들은 어떤 연산을 하더라도 결과 값은 항상 int형이 된다.
    • byte + short = int       // 참고) E 오버플로우테스트 class의 bnum = (byte)(bnum+1); 구문
  • boolean은 형변환에서 제외된다.

강제형변환 (명시적 형변환)

  • casting 연산자 -> (자료형)(값)
  • 값이 long(큰 곳) -> int(작은 곳)으로 이동할 때 데이터 손실 발생
    • 데이터 손실이 발생하지 않을 수도 있다.
      • 10 <- 10.0 (데이터 손실 X)
      • 10 <- 10.5 (0.5만큼의 데이터 손실 발생)

 


예제

D_상수테스트

package com.kh.variable;

public class D_상수테스트 {
        public void testFinal() {
                //상수 테스트
                int age;
                final int AGE;      //AGE라는 상수를 선언
                
                age = 20;
                AGE = 20;
                
                System.out.println("age : " + age);
                System.out.println("AGE : " + AGE);
                
                age = 30;          //AGE = 30;  /  에러발생 -> 상수값 변경 불가
                
                System.out.println("age : " + age);
                System.out.println("AGE : " + AGE);         
                
                System.out.println("Math.PI : " + Math.PI);
        }        
        public static void main(String[] args) {
                /*D_상수테스트 test = new D_상수테스트();
                test.testFinal();*/                
                new D_상수테스트().testFinal();      //같은의미
        }
}

 

E_오버플로우 테스트

package com.kh.variable;

public class E_오버플로우테스트 {

        public void printVarSize() {
                //기본 자료형의 사이즈 테스트
                //눈으로만 확인하는 용도임
                System.out.println("byte의 크기 : " + Byte.BYTES + "byte");                            //.BYTES(상수) 자료형 사이즈를 출력할 수 있다.
                System.out.println("short의 크기 : " + Short.BYTES + "byte");
                System.out.println("int의 크기 : " + Integer.BYTES + "byte");
                System.out.println("long의 크기 : " + Long.BYTES + "byte");

                System.out.println("float의 크기 : " + Float.BYTES + "byte");
                System.out.println("double의 크기 : " + Double.BYTES + "byte");

                System.out.println("char의 크기 : " + Character.BYTES + 
                                                                  "byte");
                //boolean은 클래스를 제공하지 않아 사이즈 출력할 수 있다
                //paring - Integer : int에 관한 내용들이 담겨있다
        }
        public void testOverFlow() { 
                //byte bnum = 128;  
                //에러, 범위를 벗어났음 / 127이 넘어가는 수는 byte 리터럴이 될 수 없다.
                byte bnum = 127;
                bnum = (byte)(bnum + 1);                                                               //byte + int로 인식 -> 결과값은 무조건 int(형변환필요) / 서로 형태가                            같아야 대입이 되기 때문에 형변환을 해준다.(byte 자료형으로 바꿈)
                        
                System.out.println("bnum : " + bnum);
        }
        public void calc() {
                int num1 = 1000000;
                int num2 = 700000;
                
                //에러가 발생하지는 않지만 예상되는 결과값이 나오지 않기 때문에 주의
                /*int multi = num1 * num2;
                
                System.out.println("계산결과 : " + multi);                                              //범위가 21억을 넘어 오버플로우 발생*/
                
                //해결방법
                //=> 오버플로우를 고려하여 더 큰 자료형을 사용한다.
                //int -> long으로 바꾸어도 되지만 num1,num2를 int로 정의한다고  가정
                long multi = (long)num1 * (long)num2;                                                 //이미 계산한 결과(오버플로우)가 multi에 대입되기 때문에 형변환을 해준다                          (한쪽만 형변환을 해주어도 다른쪽도 강제 형변환이 된다)
                
                System.out.println("계산결과 : " + multi);
        }
        public static void main(String[] args) {
                E_오버플로우테스트 test = new E_오버플로우테스트();                                         //new E_오버플로우테스트().printVarSize();
                //test.printVarSize();
                //test.testOverFlow();
                test.calc();
        }
}

 

F_형변환 테스트

package com.kh.variable;

public class F_형변환테스트 {
        //(바꿀자료형)값 또는 (바꿀자료형)변수                                                     // casting연산자는 값에서만 이루어진다 (등호의 오른쪽)
        //casting연산자 : 값의 자료형을 바꿀 때 사용한다.
        //형변황 : 자동(묵시적)형변환, 강제(명시적)형변환이 있다.
        
        //컴퓨터에서의 값 처리 규칙 
        //1. 같은 자료형 끼리만 대입이 가능하다. 다른 자료형의 값을 대입할 시 형변환 필요
        //2. 같은 자료형 끼리만 계산할 수 있으며, 계산의 결과도 같은 자료형이다.
        //3. 기본적으로 정수형은 실수형으로 자동 형변환이 가능하지만,
        //          실수형은 정수형으로 강제 형변환을 해야 한다.
        //         10 -> 10.0 자동형변환 가능, 10.5 -> 10 강제형변환 필요
        
        public void rule1() {
                boolean flag = true;
                //boolean 자료형은 무조건 true, false만 들어간다(형변환 예외)
                //flag = (boolean)1;
                
                //자료형이 다르더라도 작은 크기의 변수 타입은 큰 변수 타입으로 저장할 수 있다.
                //=> 자동형변환
                //하지만 큰 변수 타입은 작은 변수 타입으로 자동 변환되지 않기 때문에 형변환을 명시해 주어야 한다.
                //=> 강제형변환
                //변경할 값 앞에 (변경할타입)을 지정해 주면 된다.
                
                //자동 형변환이 일어남 char -> int
                int num = 'A';        
                
                System.out.println("num : " + num);
                
                char ch = 97;            //ch에 97이 저장이 되면서 a라는 char타입이 된다.
                System.out.println("ch : " + ch);                                                     //ch는 char이기 때문에 문자로 출력
                
                //char ch2 = -97;                                                                     //문자는 음수를 저장할 수 없다.
                
                //int 자료형 변수의 값은 char 자료형에 대입하기 위해 강제 형변환을 해야 한다.
                char ch2 = (char)num;                                                                 //데이터 손실이 일어날 수도 있지만
                System.out.println("ch2 : " + ch2);
                
                //음수를 저장한 변수를 char로 강제 형변환을 하게 되면
                //char는 부호비트가 없기 때문에 문자로 인식하지 못한다.
                //물음표는 문자의 의미가 아닌 없는 문자라는 뜻이다.
                int num2 = -97;
                char ch3 = (char)num2;                                                                 //강제형변환을 하면 int타입의 음수값을 넣을 순 있다.
                System.out.println("ch3 : " + ch3);         // 출력 : ?  
        }
        public void rule2() {
                //다른 자료형끼리의 연산은 큰 자료형으로 자동 형변환 후 연산처리 된다.
                int inum = 10;
                long lnum = 100;
                
                //방법 1. 수행 결과를 int로 강제 형변환 한다.
                int isum = (int)(inum + lnum);                                                         //long + long = long 이기 때문에 int에 담지 못함  -> 강제형변환 필요
                
                System.out.println("isum : " + isum);
                
                //방법 2. long형 값을 int로 강제 형변환 한다.
                int isum2 = inum + (int)lnum;
                
                System.out.println("isum : " + isum2);
                
                //방법 3. long형 자료형으로 받는다.
                long sum = inum + lnum;
                
                System.out.println("sum : " + sum); 
                
                //하지만 예외적으로 byte와 short의 연산 결과는 무조건 int가 된다.
                byte bnum = 1;
                short snum = 2;
                
                //강제 형변환을 적용한 경우
                short sum2 = (short)(bnum + snum);                                                     //연산 결과가 int로 나오기 때문에 short로 형변환
                
                //혹은 실행 결과를 int형으로 저장해야 한다.
                int sum3 = bnum + snum;
        }
        public void rule3() {
                //정수는 실수로 자동 형변환이 된다.
                long lnum = 100;                        //8byte
                
                float fnum = lnum;                      //4byte
                System.out.println("fnum : " + fnum);
                
                //실수는 정수로 형변환 할 때 강제 형변환을 해 주어야 한다.
                double dnum = 10.5;
                
                //실수가 정수로 바뀔 때 소수점 이하를 절삭하기 때문에 데이터 손실이 일어난다.
                int inum = (int)dnum;
                
                System.out.println("inum : " + inum);
        }
        public void testDataloss() {
                //데이터 손실 테스트 
                int inum = 290;
                
                System.out.println("inum : " + inum);

                byte bnum = (byte)inum;
                
                System.out.println("bnum : " + bnum);
        }
        public static void main(String[] args) {
                F_형변환테스트 test = new F_형변환테스트();
                //test.rule1();
                //test.rule2();
                //test.rule3();
                test.testDataloss();
        }
}