모든 프로그래밍 언어에서는 연산자라는 것이 있다. 그리고 그러한 연산자에는 우선순위로 연산을 하도록 우선순위가 매겨져 있다. 자바도 마찬가지로서, 그러한 연산 우선순위가 있는데, 그 우선순위대로 한번 짚고 넘어가 보자.

1. 최우선 연산자
class Exam05_01{
    public static void main(String[] args) {
       System.out.println("");
    }
}
위의 코드에서는 최우선 연산자 3개가 쓰였다. 두번째 줄에, (). ()안에 든 연산을 먼저 해야 된다는 것은 지나가던 개도 비웃으니, 패스, 다음으로 볼 연산자는 []. 이는 배열 연산자로, 배열 부분에서 건드릴테니, 이것도 패스. 다음은, 3번째 줄에 있는 System.out.println(""); 에서 .(마침표) 처럼 되어 있는 연산자 . 이 바로 3번째 최우선 연산자이다. 이것들은 연산시, 모든 연산자에 앞서, 제일 먼저 실행되는 연산자들이다.

2. 단항 연산자
2-(1) 논리부정연산자 및 비트 부정연산자
1//    class Exam05_02 {
2//        public static void main(String[] args) {
3//           boolean bool = false;
4//           System.out.println("A = " + bool);
5//           System.out.println("B = " + !bool);
6//
7//           boolean bool2 = 5 > 3;          // 이런 방법으로 논리형 값을 저장, 사용할 수 있다.
8//           System.out.println("C = " + bool2);
9//           System.out.println("D = " + !bool2);
10//          //   System.out.println("F = " + !5)      // 에러 부분
11//
12//           System.out.println("F = " + ~(4));
13//           System.out.println("G = " + ~(~(4));
14//        }
15//    }
위 코드에서는 논리 부정연산자(!)비트 부정연산자(~)가 쓰였다.

먼 저 3~10라인까지 살펴보면, 논리형 false 를 bool 이라는 변수에 넣어, 출력하게 만든 것이 4번째 라인이고, 그 bool 이라는 변수에다가 ! 를 넣은 것이 5번째 라인이다. 7번째 라인에서는 5 > 3 이라는 것을 이용하여, true 라는 값을 bool2 의 저장, 이용되어지고 있다.

자바에서의 !는 오직 논리 연산자를 부정하는 경우에 사용할수 있으며 10번째 라인에서 보는 것처럼, 일반 상수나 혹은 기타 다른 변수에 넣어서 사용할 경우에는 에러가 발생하게 된다.

5번째 라인에서 보는 것처럼 논리 부정 연산자는 이후에 나올 산술 연산자보다는 우선 순위가 높아, 우선 연산이 된다. 즉, bool 값을 먼저 부정해주고, 그렇다음, 문자열 "B = " 과 결함되는 것이다.

이렇듯 논리 연산자를 부정하기 때문에, false 로 저장된 것을 true 로 바꿔주거나, true 로 저장되어 있는 것을 false 로 바꿔주는 것이 ! 이다. 고로 A = false, B = true, C = true, D = false 로 출력이 된다.

12번째 라인과 13번째 라인은 비트 부정 연산자 ~ 를 설명하고 있다. 비트 부정 연산자는 연산할 값을 0과 1로 구성된 2진 비트로 바꿔준 다음, 해당 비트를 부정 해주는 것이다.

위의 12번째 라인을 보자면,

4는 1 바이트인 8비트로 표현을 해서,
0000 0100
이라는 2진 비트가 된다. 이러한 2진 비트에서, 비트 부정 연산자 ~ 이 붙게 되면, 각 비트를 부정하게 되어, 결국엔 다음과 같은 2진 비트가 된다.
1111 1011
이는 -5가 되며(최상위 비트는 부호비트) 12번째 라인의 출력은 -5가 된다. 이는 공식으로도 나타낼수가 있는데,
연산할 수 * (-1) -1
위 의 12번째 라인을 대입하면, 4 * (-1) -1 이 되고, 이는 정확히 -5가 된다. 13번째 라인도 똑같은 방식으로 하면 된다. ~를 한번 적용해서 -5가 되고, 여기서 다시한번 ~를 적용하면, (-5) * (-1) -1 이 되어 4라는 연산하기 전의 값이 출력된다. 즉, ~ 두번을 사용하면, 본래의 값으로 되돌아 오게 된다.


2-(2) 부호연산자

다음은 부호 연산자로, 이는 + / - 를 가리킨다. 이는 뒤에 나올 산술 연산자와는 다른데, 이는 단지, 숫자의 음수나 양수를 구분해주는 역할을 해줄뿐이지만, 연산 우선순위에서는 꽤나 높은데 자리하고 있다.


2-(3) 증감 전위 연산자
1//    class Exam05_03{
2//        public static void main(String[] args) {
3//           int x = 100;
4//           int y = ++x;          // 전위형
5//  
6//           System.out.println("X = " + x);
7//           System.out.println("Y = " + y);
8//
9//           int z = x++;          // 후위형
10//           System.out.println("Z = " + z);
11//        }
12//    }

위에 코드에서는 ++ 이라는 형태의 연산자가 사용되었는데, 이는 증감 전위 연산자라는 것이다. 이는 사용된 변수 자신에게 1을 증가하라는 이야기이며, 똑같이, -- 를 사용할수도 있는데, 이 연산자는, 변수 앞에 붙느냐, 뒤에 붙느냐에 따라 결과가 완전 달라진다.

앞에 붙는 경우는 전위형이라고 해서, 자기 자신에게 1을 먼저 증가(-- 일경우 감소)시킨후, 연산을 시도하게 된다. 위에서 3번째 라인과 4번째 라인을 보면, 변수 x는 자기 자신에게 1을 증가시켜 101로 만든후, 변수 y에게 101을 집어 넣게 된다. 전위형은, 대입연산자인 = 보다 우선 연산이 되어, 앞에 설명한 일이 먼저 벌어지고 나서 대입하게 된다. 그래서 6번째 라인과 7번째 라인에서 출력되는 것은 101이 된다.

뒤에 붙는 경우는 후위형이라고 해서, 일단 연산을 시도하고, 자기 자신에게 1을 증가(-- 일경우 감소)시키게 된다. 위의 9번째인에서 변수 x에 들어있는 101을 z에다가 집어넣은후, x는 1 증가하여 102가 된다. 하지만, 10번째 라인의 출력은 101이 된다. 이 후위형은, 대입 연산자인 = 보다 우선순위가 떨어져서, 대입이 먼저되고, 연산이 되는 것이다.

여기서 중요한 점은, 증감 전위 연산자로 아무리 값을 증가시켜도, 처음 초기화시켰던 자료형의 범위를 벗어나지는 않는다. 위의 경우는, int 자료형을 사용하여 총 4바이트 크기의 값을 가지며, 범위 -2,147,483,648 ~ 2,147,483,647 를 넘지 않는다. 만약, 2,147,483,647 에서 1을 더 증가시키게 되면, -2,147,483,648 이 된다. 이에 관련된 설명은, "[JAVA] 기본자료형" 의 설명을 참고한다.


2-(4) 형변환 연산자

이는 지난번 "[JAVA] Promotion 변환과 Casting 변환" 에서 살펴본 것중, Casting 변환에 해당되는 연산자를 뜻한다.


2-(5) 타입 비교 연산자

instanceof 라는 연산자로 차후 설명


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 5-2, 동영상 강좌에 기초한 내용입니다.
:
1. 하나의 문자를 입력받아 그것의 Char 형 문자와 아스키 코드값을 표시하는 예제.
import java.io.*;

class Change {
    public static void main(String[] args) throws IOException{
       System.out.print("Type any Characters then Enter : ");
      
       int ch = System.in.read()         // 아스키 값을 입력받아, 아스키 값을 저장

       System.out.println( (char)ch + " = " + ch);         
            // 처음 ch 는 아스키 값의 해당되는 문자를 출력하기 위한 형변환
            // 두번쨰 ch 는 아스키 값을 그대로 출력하기 위한 것
    }
}

2. 한사람의 이름을 입력받고 국어, 영어, 수학 점수를 입력받아 총점과 평균을 구하는 프로그램.
import java.io.*;

class TotalScore{
    public static void main(String[] args) throws IOException {

       BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

       String name, kors, engs, maths = "";         // String 형의 초기화
       int kor, eng, math, total = 0;
       float avg = 0.0f;

       System.out.println("Input Your Information");
       System.out.print("What is Your Name? ");
       name = in.readLine();          // 이름의 문자열을 입력받아 저장
       System.out.print("What is Your Korean Score? ");
       kors = in.readLine();          // 숫자를 입력받지만, 실제로는, 숫자로된 문자열로 인식
       kor = Integer.parseInt(kors);          // Wrapper 클래스로, 숫자로된 문자열을 숫자로 변환
       System.out.print("What is Your English Score? ");
       engs = in.readLine();
       eng = Integer.parseInt(engs);
       System.out.print("What is Your Math Score? ");
       maths = in.readLine();
       math = Integer.parseInt(maths);

       total = kor + eng + math;
       avg = (float) total / 3;         // float 형으로 형변환

       System.out.println("");         // 일부로 한줄 내려주기 위해 사용
       System.out.println(name + "님의 성적은 다음과 같습니다.");
       System.out.println("총점 : " + total + "점");
       System.out.println("평균 : " + avg + "점");
    }
}
위의 소스코드를 다음과 같이 수정할 수 있다.


import java.io.*;

class TotalScore{
    public static void main(String[] args) throws IOException {

       BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

       String name = "";         // String 형의 초기화 ----------------------- 수정 ①
       int kor, eng, math, total = 0;
       float avg = 0.0f;

       System.out.println("Input Your Information");
       System.out.print("What is Your Name? ");
       name = in.readLine();          // 이름의 문자열을 입력받아 저장
       System.out.print("What is Your Korean Score? ");
       kor = Integer.parseInt(in.readLine());          // Wrapper 클래스로, 숫자로된 문자열을 숫자로 변환 ------------------------------------- 수정 ②, 이런식의 방법이 가능
       System.out.print("What is Your English Score? ");
       eng = Integer.parseInt(in.readLine()); // ------------------------- 수정 ③
       System.out.print("What is Your Math Score? ");
       math = Integer.parseInt(in.readLine()); // ------------------------ 수정 ④

       total = kor + eng + math;
       avg = (float) total / 3;         // float 형으로 형변환

       System.out.println("");         // 일부로 한줄 내려주기 위해 사용
       System.out.println(name + "님의 성적은 다음과 같습니다.");
       System.out.println("총점 : " + total + "점");
       System.out.println("평균 : " + avg + "점");
    }
}
:
1. 기본자료형의 String 클래스
: String 은 원래, 클래스 로서, 자료형처럼 사용할수 있게 만들어 놓아서, 문자열을, 저장, 사용할수 있도록 해주었다. 이러한 클래스 변수, String 은 얼마만큼의 데이터가 들어가 있든지 상관없이, 무조건 4byte 의 크기를 갖고 있으며, 문자열을 처리할수 있도록, 자료형처럼 사용되고 있다.

2. Wrapper 라는 클래스
: 1번에서 String 은 클래스로서, 자료형처럼 사용할수가 있다고 이야기를 했다. 자료형은, String 외에도, Java 에서는 8가지가 기본 자료형으로 제공되는데, String 을 제외한 자료형들은, 모두 클래스가 아니다. 다들, 단순히, 기본 자료형일 뿐이며, 이는, 단순히 값을 저장하고, 연산자를 이용한 단순 연산만이 가능하도록 해놓은 것들이다. 이러한 제한적인 기능을 보강하기 위해 제공되는 것들이 바로 Wrapper 클래스로서, 소문자를 대문자로변환, 정수를 문자열로 변환 문자열을 정수로 변환등의 부가적인 처리를 할수 있도록 해주는 것이 Wrapper 클래스라고 이야기를 한다. 즉, String 이 클래스로의 역할과, 자료형으로의 역할을 모두 수행할 수 있는 것처럼, 다른 자료형 역시, 그러한 역할을 수행할 수 있도록, 기본 자료형 외에, Wrapper 클래스를 만들어 두면서, 자료형 외의 클래스 역할을 제공해주도록 하고 있다.

3. java.io.*;
: 자바의 입출력을 관리하는 패키지로서, 입출력과 관련된 클래스를 사용하기 위해 Import 를 시켜주어야 한다.

4. System.in.read()
: 이 메소드는 입력받는 형식이 아스키 타입으로, 값을 받아서, 변형시킬때는, 이점을 알아두어, 실수하지 않도록 한다.
:
앞에서, 우린 문자와 숫자의 키보드를 입력할때의 처리과정을 알아보았다. 다음은, 문자열이다.

System.in.read() 부분은, 하나의 문자만을 입력, 저장, 출력을 했다. 그렇다면, 여러개의 문자로 구성된 문자열은 어떻게 되는가?

첫번째 방법은, byte 형의 배열을 사용하는 방법이 있다.
1//   import java.io.*;
2//    class Exam04_06{
3//        public static void main(String[] args) throws IOException{
4//            byte[] by = new byte[10];
5//            System.out.print("Subject = ");
6//            System.in.read(by);
7//            System.out.println("So, Subject = " + new String(by));
8//        }
9//    }
4번째 라인에서 byte 형의 배열 ny 를 선언하고, 6번째 라인에서 입력 받은 것을, 배열 by 에 저장한후, 7번째 라인에서 출력한다. 이건 나중에 배열 부분에서 알아보기로 하고, 두번째 방법으로 들어가 본다.

두번째 방법은 다음 구문을 사용하는 것이다.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in))
이 구문을 사용한 코딩은 다음과 같다.
1//    import java.io.*;

2//    class Exam04_07 {
3//        public static void main(String[] args) throws IOException {
4//           BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

5//           String name = "";
6//           String age = "";

7//           System.out.print("Name = ");
8//           name = in.readLine();
9//           System.out.print("Age = ");
10//           age = in.readLine();

11//           System.out.println();
12//           System.out.println("Name = " + name);
13//           System.out.println("Age =" + age + " years old");
    }
}
4번째 라인에서 쓰인 구문은, 훗날 분석을 하기로 하고, 지금은, 단지, 구문 자체를 외우는게 나은 방법이다.

String 형의 변수를 선언, 초기화 시켜주고, 7번째 라인에서, 이름을 물으며, 입력을 받는다. 이 입력을 받아서 저장하는 역할을 하는게 8번째 라인이다.

in.readLine() 은, 문자열을 입력받아, 저장, 출력을 해주는데, 전에 배운, System.in.read() 와는 달리, .이 in.readLine() 은, 엔터키가 입력되기 전까지의 문자들을, 입력받아 저장시켜준다. 그래서, System.in.read() 에서 했던, 엔터키를 무력화시켜주는 기법이 여기서는 따로 필요가 없다.  또한 이 구문은, 위의 BufferedReader in 에서 가져와 in.readLine(); 으로 사용하고 있다. 만약 BufferedReader rys 라고 하면, rys.readLine() 이라고 바꿔줘야 할 것이다. 이를 이용하면, 앞에서 봤던 예제에서, 엔터키값을 없애기 위해 사용한 System.in.read() 를 사용안하고, 여기서 배운 내용으로, 코드를 수정, 보완할수가 있다.

하 지만 여기서도, 한가지 문제점이 발생한다. 바로, 여기서는 문자열만이 저장된다는 된다는 것인데, 숫자열을 하고 싶다면 어떻게 해야 하나. 물론, 위의 코딩대로 해도, 오류는 나오지 않는다. 다만, 이를 문자열로 저장하고, 문자로 인식하며, 쓸데없는 공간들을 낭비하는 문제가 따로 발생할뿐이다.

아무튼, 숫자열을 사용하고 싶다면?? 이때는 Wrapper 클래스라는 것을 사용한다.
1//    import java.io.*;

2//    class Exam04_08 {
3//        public static void main(String[] args) throws IOException {
4//           BufferedReader in = new BufferedReader(new InputStreamReader)(System.in));
      
5//           String imsi = "";
6//           byte a = 0;
7//           int b = 0;
8//           float c = 0.0f;
   
9//           System.out.println("Insert Numbers : ");
10//           imsi = in.readLine();

11//           a = Byte.parseByte(imsi);
12//           b = Integer.parseInt(imsi);
13//           c = Float.parseFloat(imsi);

14//           System.out.println("a = " + a);
15//           System.out.println("b = " + b);
16//           System.out.println("c = " + c);
    }
}
여 기서 11번째 라인서부터 13번째 라인까지가, Wrapper 클래스이다. 그래서 9번째 라인과 10번째 라인에서 문자열을 입력받은 후, 이 입력받은 값을, 숫자로 바꿔주는 역할을 하는게, 11번째 라인에서 13번째 라인까지의 Wrapper 클래스 이다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 4-3, 동영상 강좌에 기초한 내용입니다.
:
키보드를 통한 입력은 크게 두가지로 나눌수 있다.

1. 문자 및 숫자 입력
2. 문자열 입력

첫번재 문자 및 숫자 입력은, 또 3가지 형태로 나눌수 있다.

(1) 아스키 코드 값을 읽어내는 방법
(2) 숫자값을 읽어내는 방법
(3) 문자값을 읽어내는 방법

다음의 코드를 살펴보자.
1//    import java.io.*;

2//    class Exam04_05 {
3//        public static void main(String[] args) throws IOException {
4//           System.out.print("Insert Character: ");
5//           int a = System.in.read();             // 아스키 코드값으로 저장, 출력.
6//           //Char a = (char)System.in.read();    // 문자값을 그대로, 저장, 출력.
      
7//           System.out.println("a = '" + a + "'");

8//           System.in.read();             // 엔터중 \r을 무효화 시키는 부분
9//           System.in.read();             // 엔터중 \n을 무효화 시키는 부분

10//           System.out.print("Insert Number : ");
11//           int b = System.in.read() - 48;   // 숫자값을 저장할때, 혹은 '0' 을 대신 사용가능

12//           System.out.println("b = " + b);
    }
}
System.in.read() 는 기본적인 입력을 담당하는 메소드이다. 이 메소드를 사용하는 방법은 위에서 말한대로 3가지 방법이 존재하는데, 이 메소드는 1바이트만 입력이 가능한 메소드로, 이후, 지속적인 타이핑을 해도, 입력받아 저장하는 값은, 처음으로 타이핑을 한 글자만이 입력되고, 저장된다. 또한, 아스키 코드값을 읽어, 사용하는 메소드이다. 그리고, 이 값은, 키보드 하나에 매칭(엔터제외)된다. 즉, System.in.read() 는 키보드를 한번 타입할때마다 메소드 하나가 실행이 된다고 보면 된다는 것이다.(엔터제외)

먼저, 1번째라인부터, 7번째 라인까지 한 결과를 알아보는데, 여기서 6번째 라인은 주석 처리하여, 실행이 안되도록 막아놓는다. 물론, 기타, 8번째부터 12번째 라인, 역시 주석으로 막아놓는다.

이 첫번째 케이스에서는 타입한 키보드 값의 아스키 코드 값을 읽어, 저장, 출력한다.

사용자 삽입 이미지

r 을 입력받아, r의 아스키 코드 값은 114가 출력이 되었다. 만약, 여러문자를 입력하면?

사용자 삽입 이미지

이렇듯, 여러문자를 입력해도, 첫번째 입력된, r 만의 값을 저장, 출력한다. 그래서, 결과는 위와 똑같다. 숫자를 입력하게 되면 어떻게 될까?

사용자 삽입 이미지

숫자 5를 입력하면, 숫자 5에 해당하는 아스키 코드값을 읽어들여, 저장, 출력한다. 그 값이 바로 53.

System.in.read() 를 사용하면, 이렇듯, 아스키 코드값만을 읽어들여, 저장, 출력한다. 그러면, 만약, 받은 문자값을 그대로, 읽어들여, 출력하게 하고 싶다면???

위의 코딩부분으로 가서, 라인 1부터 7에서, 6의 주석을 풀어서, 사용가능하게 만들고, 라인 5에다가 주석을 붙여서, 사용가능하지 못하도록 만든다. 그외의 라인 8부터 12는 사용 못하도록 주석처리를 한다.

사용자 삽입 이미지

문 자값을 그대로 입력받아, 그대로 출력을 할때는, 위의 라인 6처럼, (char)System.in.read() 를 사용해 준다. 이는, System.in.read() 로 입력받은, 아스키 코드 값은 정수를, 문자형태로, 형변환을 시켜준 것이다. 이렇게 해줌으로써, 무사히, 문자값을 그대로 입력받아, 그대로 출력할수가 있게된다.

만약, 여기서, 숫자를 입력하게 된다면? 숫자 역시, 그대로 입력을 받아, 그대로 출력이 가능하다. 하지만, 여기서의 숫자는 엄밀히 말하면, 정수, 혹은 실수개념의 숫자가 아닌, 문자형태의 숫자로 컴퓨터가 인식하게 된다. 다시말해, 컴퓨터가, 문자로 판단한다는 것. 물론, 그게 숫자형태를 띄고 있다고 해도 말이다. 왜냐면, 코딩 부분을 보면, char 형태로 변수를 선언했으며, 형변환도, char 형태로 형변환을 했기 때문이다.

그러면, 순수한 형태의 숫자를 사용하려면 어떻게 해야 할까?

위의 코딩부분에서, 1, 2, 3, 10, 11, 12 라인만을 이용하면 된다. 다른 부분은 주석처리하자. 이것의 결과는 이렇게 나온다.

사용자 삽입 이미지

여 기서 핵심라인은 11번쨰 라인이다. System.in.read() 부분은 아스키 코드값을 다룬다고 했다. 여기서, 5의 아스키 코드값은, 위에서 보았듯이 53이다. 숫자 0의 아스키 코드값은 48이다. 고로, 입력받은 숫자의 아스키 코드값에서, 0의 아스키 코드값은 48을 빼면, 입력받은 숫자, 그대로 출력될 것이다. 예를 들어, 위의 예에서, 5를 입력하면, 아스키 코드값은, 53이 입력, 저장되고, 여기서, 0의 아스키 코드값인 48을 빼면, 5, 입력한 숫자 5가, 그대로 출력하게 되는 것이다.

그래서, 코드란에, System.in.read() - 48; 이라고 코드를 적어놓았다. 이 방법말고도, 그대로 작은 따옴표 '' 를 사용해서 '0' 을 48 대신에 사용해도 된다. 작은 따옴표를 쓰면, 문자값을 그대로 쓰지만, 내부에서는, 문자값의 아스키 코드값을 읽어들이기 때문이다.

이번엔 좀더 응용을 해보자.

위의 코딩부분중, 5, 8, 9 라인을 모두 주석 처리하고, 나머지 부분은, 주석을 제거해서 실행을 시켜보자.

사용자 삽입 이미지

이렇게 이상한 값이 출력하게 된다. 왜 그런 것일까?

System.in.read() 라는 메소드는, 키보드 한번 타입할때마다, 하나가 실행된다고 했다. 위에 4번라인에서 입력을 받아, 6번 라인에서 저장하고, 그리고, 나서 출력을 해야 되는데, 다시 말하지만, System.in.read() 라는 메소드는, 키보드 한번 타입할때마다, 하나가 실행된다고 했다. 위에서, 키보드를 몇번 입력했는지를 곰곰히 생각해보면, 해답이 나온다.

위에서, "r" 이라는 키보드를 타입하고, 또, "엔터" 라는 키보드를 타입했다. 이렇게 총 두번 키보드를 타입했으며, 코드 안에는, System.in.read() 라는 메소드가 두번만 실행이 된다. 즉, 첫번째, System.in.read() 부분에는 "r"이 들어갔으며, 두번째, System.in.read() 라는 메소드에는 "엔터" 부분이 들어가서 실행이 된것이다. "엔터"의 아스키 코드값은, 13이며, 라인 11의 System.in.read() - 48 이라는 부분에 의해 13-48이 연산, -35가 출력이 되는 것이다.

이러한 현상을 없애기 위해서, 첫번째, System.in.read() 와 두번째, System.in.read() 사이에, 엔터값을 먹어주는 또하나의 System.in.read() 라는 값이 들어가야 하는데, 그렇게 해서, 라인 8의 주석을 해제 시켜서, 컴파일을 해보자.

사용자 삽입 이미지

근 데, 이상하게 또다른, 이상한 값이, 바로 출력된다. 위에서 잠깐 언급했었는데, 실제 엔터는, \r 과 \n 이라는 부분으로 이루어져있다. 그래서, 만약, 위에서 한대로, 라인 8의 주석만을 해제 시키면, 엔터를 구성하는 요소중, \r 부분만이 먹히게 되고, \n 부분의 아스키 값은, 그대로, 컴퓨터가 인식하여, 출력되게 되는 것이다.

고로, 라인 8과 라인 9의 주석을 모두 해제를 시킨후에 실행을 시키면, 제대로 실행되는 것을 보게 될것이다.

사용자 삽입 이미지


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 4-3, 동영상 강좌에 기초한 내용입니다.
:
예외 처리는 입출력시 벌어질, 예외 상황에 대비하는 방법으로, 안정성에 촛점을 맞춘 자바의 특성상 필요한 구문이다. 또한, 출력시에는, 자동으로 예외처리가 발생하기에 상관은 없지만, 입력시에는 자동이 아니기 때문에, 예외처리를 위한 구문을 적어줄 필요가 생긴다.
1// import java.io.*;

2// class Exam04_03 {
3//     public void aaa() throws IOException{
             입력부분 쏼라쏼라
4//     }

5//     public static void main(String[] args) throws IOException{
6//        aaa();
             입력부분 쏼라쏼라
    }
}
1번째 라인은, 예외처리를 위해 필요한 구문이다. 입출력 예외처리는 java.io 라는 팩키지 안에 들어있으므로, 이를 불러와야 사용이 가능하다.

3번째 라인은, 또다른 메소드를 정의한 내용인데, 만약이 이곳에 입력부분이 들어간다면, 예외처리를 써주어야 하고, 5번째 라인에 메인부분에서도 입력부분이 들어간다면, 둘다 예외처리 구문을 사용해 주어야 한다.

만약, 입력부분이 안들어간다면, 굳이 사용해줄 필요는 없지만, 입력된 메소드를 호출해주는 6번째 라인과 같은 경우에도, 메인 메소드에 예외처리를 해주어야 한다.

p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 4-2, 동영상 강좌에 기초한 내용입다다.
:
System 클래스에서 입출력과 관련된 필드부분은, 총 3가지로 나뉠수 있다.

사용자 삽입 이미지

err 는 에러 메시지 출력부분이고, in은 기본 입력을 받는 부분이며, out은 기본 출력을 하는 부분이다.

이 부분은, API 문서내에 java.lang 팩키지 안에 System 클래스 부분에서 확인할수가 있다. 이중, err과 out은 PrintStream 이라는 타입으로 되어 있는데, 마우스로, 저곳에 갖다 대보면, 저 타입이 어느 팩키지에 속해있는지 확인해볼수가 있다.

PrintStream 클래스는, java.io 라는 팩키지에 속해있다. 아무튼, 기본 출력, out에 관련된 메소드들은, 크게 4가지로 나누어 볼수가 있다.

Write 메소드, print 메소드, println 메소드, printf 메소드.

print 와 println 메소드의 차이는, 자동으로 한줄을 입력하느냐, 마느냐의 차이이니, 그 부분은 생략하기로 하고, 여기서 볼 부분은, write 와 println, printf 에 관해서이다.

1// class Exam04_01{
2//     public static void main(String[] args){
3//         System.out.write(65); // 아스키 코드값에 해당되는 문자값을 출력
4//         System.out.flush();
5//         System.out.println();
6//
7//         byte[] by = new byte[]{'J', 'A', 'V', 'A'};
8//         System.out.write(by, 0, 4);
9//
10//         int a = 100;
11//         int b = 'A';
12//
13//         System.out.printf("a = %d 입니다. \n", a);
14//         System.out.printf("b = %c = %d \n", b, (int)b);
15//     }
16// }
위의 소스코드를 보자.

write 메소드의 사용법에는 두가지가 있다.
API 에서 확인을 해보면,

사용자 삽입 이미지

이렇게 되어 있는데, 아래 사용방법에서, int 가 사용되는 것은, 아스키 코드 값을 위한 것이다.

3 번째 라인에서 write 메소드가 쓰였다. 이 메소드는, 화면에 출력을 시켜주는 flush 기능이 자동으로 되는 것을 지원해주지 않고 있다. 그래서 화면에 출력시키기 위해서는, 4번째 라인에서처럼, flush 메소드를 사용하여, 출력을 시켜주었다.

이렇게 사용되어지면, write 라는 메소드는 상당히 불편한 메소드 임에 분명하다. 사용할때마다 flush 를 같이 사용해 주어야 하니까. 하지만, 나중에, 네트워크 부분에서는 자주 쓰이는 녀석이라니 일단은, 알아두자.

다음으로, 7번째와 8번째 라인이다. 이는 write 의 사용법중, 위에 사용방법에 해당되는 녀석인데, byte 형태의 배열과, 초기값, 그리고 길이등을 명시해주고 있다.

7번째 라인에서는 byte 배열 by 를 생성시켜주었고, 8번째 라인에서는 write 메소드를 사용하여 출력해주었다. byte 배열 by 에서, 0번째 값부터, 총 4개의 값을 출력하라는 의미가 바로 8번째 라인이다.

알겠지만, 배열에서는 첫번쨰 값이, 0번째, 두번째 값이, 1번째 등으로 말을 한다.

하여튼, 8번째 라인대로 사용하는데, 이는 write 메소드를 사용하는 두가지 방법에서 이상한 차이를 발견할수가 있다.

3- 4번째 라인에서 사용된 방법은, 자동 flush, 기능이 없어서, flush를 따로 부여해주었다. 하지만, 7-8번째 라인에서 사용된 방법은, 자동 flush 기능이 포함되어 있어서, 따로 flush 를 해줄 필요가 없이, 바로 사용할 수가 있다. 두가지 방법에 있어서의 차이가 이렇다.

13번째와 14번째 줄에서는 printf 라는 메소드가 사용이 되었는데, 이 메소드는, 자바 1.5부터 지원이 되는 사항으로, C를 개발하던 개발자들을 위해, C 문법을 빌려온 것이다. 이는, %d(정수), %c(문자), %s(문자열), %f(실수) 등을 이용하여 문자를 출력하는 방법이다. C를 개발했던 개발자들에게는 편할지, 몰라도, JAVA 입문자에게는 헷갈릴수도 있으니, 주의할 것.
1// class Exam04_02 {
2//     public static void main(String[] args) {
3//         int x = 12;
4//         int y = 24;
5//
6//         System.out.println("x = ", + x); // x = 12
7//         System.out.println(x + y); // 36
8//         System.out.println("a" + x + y); // a1224
9//         System.out.println(x + y + "a"); // 36a
10//        System.out.println(x + "a" + y); // 12a24
11//         System.out.println(x + "a" + y * 2); // 12a48
12//         System.out.println(x + "a" + y - 2); // 에러
13//         System.out.println('a' + x + y); // 133
14//         System.out.println(x + y + 'a'); // 133
15//         System.out.println('a' + 'b'); // 195
16//         System.out.println("" + 'a' + x); // a12
    }
}
이부분은, 여러방법으로 println 을 사용한 모습이다.

6번째라인부터, 16번째 라인까지 println 을 사용한 모습인데.

6번째 라인, 큰 따옴표 "" 를 사용하면, 이는 문자열이 되어버리며, 문자열과 연산자가 연산이 되면, 이는 그대로 문자열이 되면서, 단순 나열방식이 되어버려, x = 12 라는 단순 나열이 되어버린다.

7번째 라인, 큰 따옴표 "" 이 없는 상태에서는, 연산이 가능한 연산끼리 연산이 되어지는 경우인데, 이 경우는, 말 그대로 연산이 되어 36이라는 값이 출력된다.

8번째 라인, 연산은 앞에서부터 뒤로 실행이 되어지는데, 앞에 큰 따옴표 "" 과 x가 만나서, 문자열이 되어버리고, 다시 한번 문자열과 y가 만나, 그대로, 문자열이 되면서, 단순 나열 방식이 된다. 그래서 a1224 가 출력

9번째 라인, 역시, 앞에서부터 뒤로 실행이 되는데, 이번엔, 앞에 연산이 가능한 경우라서, 연산이 되고, 이후에는, 문자열이 되면서, 단순 나열방식이 된다. 고로, 36a 가 출력.

10번째 라인, 위와 같은 원리로, 12a24 라는 값이 출력한다.

11번째 라인, *부터 연산이 이루어진다. 그후, 앞에서부터 연산이 이뤄져, 값은 12a48 이 된다.

12번째 라인, 이곳에서 -는 연산 순위에 따라 가장 마지막에 연산이 이루어지는데, 앞에 계산되어진 부분은, 이미 문자열로 바뀌어버린 상태다. 거기서 -2를 하면, 컴퓨터가 번역을 할수가 없어서, 결국 에러를 일으키고 만다.

13 번째 라인, 작은 따옴표 ''를 사용한 'a'는 char z = 'a'; 라고 사용한 것과 똑같은 효과를 불러일으킨다. 고로, 이는 아스키 코드 값을 지닌 문자값인데, 여기서, 만약, 연산이 가능하면, 아스키 코드값으로 변형되어, 작동하고, 그렇지 않다면, 그냥 문자값으로 작동이 되어진다. 여기서는 연산이 가능하므로, a의 아스키 코드값 97로서 작동하여, 결과값은 133이 된다.

14번째 라인, 13번째 라인과 동일하다.

15번째 라인, 여기서도 연산이 가능해서, 97+98 이라는 연산이 이루어지고, 결과값은 195

16 번째 라인, 큰 따옴표 "" 는 비록 아무 내용이 없을 지라도, 이는 뒤에 내용을 문자열로 바꿔주겠다는 의미가 강한 것이라고 볼수 있다. 작은 따옴표 '' 로 둘러쌓인 'a;는, 이때는 앞에 문자열이 와서, 연산이 불가능 하므로, 그냥, a라는 값이 사용되어, 문자열이 되어버린다. 그렇게, 단순 나열 방식이 전개되어, 결과값은, a12가 되어버린다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 4-1, 동영상 강좌에 기초한 내용입다다.
:
class Exam_10
{
 public static void main(String[] args)
 {
  byte a_min = Byte.MIN_VALUE;
  byte a_max = Byte.MAX_VALUE;

  char b_min = Character.MIN_VALUE;
  char b_max = Character.MAX_VALUE;

  int c_min = Integer.MIN_VALUE;
  int c_max = Integer.MAX_VALUE;

  float d_min = Float.MIN_VALUE;
  float d_max = Float.MAX_VALUE;

  System.out.println(a_min + "~" + a_max + ", " + (int)b_min + "~" + (int)b_max + ", " + c_min + "~" + c_max + ", " + d_min + "~" + d_max);
  // char 에서 형변환을 안시켜주면, 단순, 아스키 코드값으로 인식해서, 엉뚱한 값이 출력.
  // 숫자로 인식시키기 위해, int 로 형변환
 }
}
위 의 코딩에서 출력부분에서 b_min 과 b_max 값은, Char 형으로 저장되었으며, 이는 꼭 형변환을 시켜주어야 한다. 만약 형변환을 안시켜주면, 저장된 값을 아스키 코드값으로 인식, 저장해서, 출력될때, 아스키 코드값에 해당되는 문자를 출력하여, 엉뚱한 값이 출력되게 된다.


class Exam_11
{
 static int x;      // 전역 변수일 경우, 0으로, char 형일경우, 널문자로 초기화
 public static void main(String[] args)
 {
  int y = 0;        // 지역 변수에서는, 꼭 초기화를 시켜주어야 됨, 초기화 안시켜주면 에러
 }
}
변 수값을 초기하는데, 전역 변수를 선언할 경우, 초기값이 0으로 자동 설정된다. 문자형인 char 일 경우엔, null 문자가 설정된다. 하지만, 지역변수에서는, 선언시, 꼭 초기화를 시켜주어야 하는데, 그렇지 않으면 에러가 발생하게 된다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 3-6, 동영상 강좌에 기초한 내용입다다.
:
Promotion
- 자동형 변환
- 작은 공간의 변수 값을 큰 공간의 변수로 이동

Casting
- 강제형 변환
- 큰 공간의 변수 값을 작은 공간의 변수로 이동
- 데이터 손실 고려
1/ class Exam_07 {
2/   public static void main(String[] args)  {
3/   int x = 256;
4/   long y = x;
5/   byte z = (byte)x;

6/   char a = 65;
7/   short b = (short)a;

8/   long c = 100L;
9/   float d = c; // promotion 변환

10/   float e = 10.24f;
11/   long f = (long)e; // casting 변환

12/   System.out.println(x);
13/   System.out.println(y);
14/   System.out.println(z);
15/   System.out.println(t);
 }
}
3번째 라인과 4번째 라인에서 자료형 변환이 일어나는데, 이 경우에는 작은 공간에서 큰 공간으로 이동하는 것이기에, 자동으로, 형변환이 일어나며, 아무것도 해주지 않아도 자동으로 변환된다. 이를 Promotion 변환이라 한다.

5 번째 라인에서는 큰 공간에서 작은 공간으로 이동하는 것이기에, 메모리 손실을 감수하면서, 강제로 형변환을 시켜줘야 한다. 이때 사용하는 기법은, 5번째 라인처럼 저장될 변수 앞에 변형 될 자료형태를 () 사용하여 붙여주면 된다. 이를 Casting 변환이라 한다.

6 번째 라인과 7번째 라인은 문자형을 사용하는 경우인데, char 와 short 은 똑같은 2byte 의 자료형이다. 똑같은 크기의 자료형이라 문제될것이 없어보이나, char 은 0부터 65535 까지이고, short 은 -32768부터 32767 까지로, 물론, 겹쳐지는 범위가 존재하나, 겹쳐지지 않는 범위 역시 존재하게 된다. 그러기에, 메모리 손실을 불러올수가 있게 되고, 이러한 연유로, 이때에는 Casting 변환을 사용하게 되는 것이다.

10번째 라인과 11번째 라인은 실수형과 정수형 자료형과의 관계를 보여주는데, 실수는 소수를 표현하고, 그래서 당연히, 정수보다 커서, 그들이 실제 저장할수 있는 범위, float 은 4바이트고, long은 8바이트고 하는 것으로는 따질수 없는 부분이 있으며, 이로 인해, 무조건 실수가 정수보다 크다고 봐야 한다. 그래서 long 을 float 으로 변환시킬때는 promotion 변환이 발생하고, 역으로, float 을 long 으로 변환시킬때는 Casting 변환이 일어나게 된다.

단, boolean 형태의 논리 자료형은 어떠한 형변환도 할수가 없는데, 그 이유는, 논리 자료형이 갖는 값이 true 와 false 단, 두가지의 형태이기에, 그 이외에 비트는 사용을 안하고, 그로 인해 발생할수 있는 문제점들을 방지하고자, 아예 형변환 자체를 막아놓게 되었다.

p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 3-5, 동영상 강좌에 기초한 내용입다다.
:

byte : 1byte (-128~127)
short : 2byte (-32768~32767)
char : 2byte (0~65535)
int : 4byte (-2147483648~2147483647)
long : 8byte (-922경~922경)

1/ class DataStyle{
2/   public static void main(String[] args) {
3/     byte a = 127;
4/     a++;

5/     short b = -32768;
6/     int c = 2147483647;
7/     long d = 123098148390127389L;  // L을 붙여서, int형과 구분해준다.

8/     char e = 65;
9/     char f = 'a';
10/   char g = '\u0041'; // 16진수표현, '\'사용
11/   float h = 12.34f;      // f를 붙이지 않으면, double 형으로 판단
12/   double i = 12.34;
  }
}
자료형은 담을 수 있는 공간은 정해져 있다. 3번째 라인과, 4번째 라인에서 byte 는 -128~127 까지의 영역을 저장할수 있는데, 만약 이 공간의 크기가 넘어가면, 컴파일 에러가 나오며, 실행이 에러가 된다.

하지만, 4번째 라인처럼 연산자를 사용하여, 공간의 크기를 넘어갔을 경우, 자료형태의 안에서 결국 돌고 돌아, byte 범위내의 첫 숫자인 -128이 a에 저장이 되어 출력된다.

byte 는 총 8비트로 구성이 되어 있으며, 이를 2진수로 표현하면 이렇게 된다.

1/ 0000 0000 : 0
2/ 0000 0001 : 1
3/ 0000 0010 : 2
4/ ....
5/ 0111 1111 : 127
6/ 1000 0000 : 128
7/ 1000 0001 : 129
8/ ....
9/ 1111 1111 : 255

하지만, 이런 식으로 표현할 경우, 문제가 발생한다. 바로 음수를 표현할 방법이 사라지게 된다. 그래서 고안한 방법이, 최상위 비트를 부호 비트로 놔두는 방법이다. 고로, 최상위 비트가 0이면 양수, 1이면 음수로 표현함으로써, 음수를 표현하는 방법을 생각해 낸 것이다.

이를 다시 2진수로 표현하면 이렇게 된다.

1/ 0000 0000 : 0
2/ 0000 0001 : 1
3/ 0000 0010 : 2
4/ ....
5/ 0111 1111 : 127
6/ 1000 0000 : -128
7/ 1000 0001 : -127
8/ ....
9/ 1111 1111 : -1

6 번째 라인 이후부터는, 음수가 되어가는 것을 볼수가 있는데, 6번째 라인에서, 1000 0001 은 최상위 비트가 1이므로 음수를 나타내서 -128인 상태에서 최하위 비트가 1이므로, -128+1 이 되어, -127이 되어버렸다. 이런 식으로 하면, 마지막 9번째 라인에서는 -128+127이 되어 -1이 되게 된다.

이렇게 보면, 결국 자료형은 돌고 돈다는 이야기인데, 다시 코딩 부분으로 돌아가, 3번째 라인에서 127을 입력시키고, 4번째 라인에서 1을 증가시켰다. 위의 byte 의 새로운 2진수 표현 방법을 적용시키면, 127 에서 1을 더하면, 128이 아닌, 음수인 -128이 된다. 그래서 나중에 a 를 출력하면, -128이 출력된다.

코딩 부분에서 7번째 라인을 보면 long 형태의 자료형을 사용한 것을 볼수가 있는데, 만약 long 형태의 자료형을 선언하고, 큰 범위의 숫자를 입력하면, 컴퓨터는 이를 그냥 int 형으로 인식하여 컴파일 에러를 발생시킨다. 이를 위해 long 형을 사용시엔, 항상 입력한 값뒤에 대문자 L 자를 삽입하며, 소문자 l 을 사용해도 가능하나, 숫자 1과 소문자 l을 구별하기 위해, 대문자 L을 좀더 사용한다.

8번째 라인부터 10번째 라인까지는 문자형 char 에 관한 부분으로 단순히 숫자를 입력하면, 아스키 코드값 저장하여 출력시, 저장된 아스키 코드값의 해당 글자가 출력된다. 작은 따옴표를 이용한 문자를 저장할 경우엔, 오직 한문자만이 저장 가능하며, 이 역시 저장된 글자가 바로 출력이 된다. 하지만, 실제, 컴퓨터는 아스키 코드값으로 기억, 저장하고 있다.

11번째 라인과 12번째 라인은 실수형을 담고 있는데, float 자료형을 사용시, 저장 값에 f를 사용안하면, double 자료형으로 인식, 에러를 일으키게 된다.


p.s 위의 글들은, 김승현 강사님열혈강의 Java Programming 의 Round 3-4, 동영상 강좌에 기초한 내용입다다.
:

BLOG main image
아무거나 공부하자!!! by Young79

공지사항

카테고리

분류 전체보기 (79)
Programing (29)
English (31)
Graphic (4)
Saying on T"We"tter (15)

최근에 올라온 글

최근에 달린 댓글

글 보관함

달력

«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Total :
Today : Yesterday :