ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 02. 자바 기본 프로그래밍
    JAVA 2021. 1. 21. 10:45

    2-1 자바 프로그램의 구조

    • 클래스 만들기

    클래스를 만들고, 그 안에 변수, 상수, 함수(메소드) 등 모든 프로그램 요소를 작성한다. 클래스 바깥에 어떤 것도 작성해서는 안 된다.

    public class Hello{
    ...
    }

    public은 자바의 접근지정자(access specifier)로서 다른 모든 클래스에서 클래스 Hello를 자유롭게 사용할 수 있다는 선언이다

    • 주석문

    // -> 한 라인 주석문

    /* ~ */ -> 여러 라인 주석문

    • main() 메소드

    자바 프로그램은 main() 메소드부터 실행을 시작한다. main()은 반드시 public static void 타입으로 선언되어야 하며, 한 클래스에 2개 이상의 main()을 작성하면 안 된다.

    public static void main(String[] args){
    ...
    }
    • 메소드

    클래스의 멤버 함수를 자바에서는 메소드라고 부른다. 메소드 개수에는 제한이 없다.

    public static int sum(int n, int m){
    return n + m;
    }

    다음은 메소드 sum()을 호출하는 코드이다.

    int i = 20;
    s = sum(i, 10);
    • 변수 선언

    변수(variable)란 프로그램 실행 동안 데이터를 저장하는 공간이다.

    int i = 10;
    char a;

    메소드 내에 선언되어 사용되는 변수를 지역변수(local variable)라고 한다. 지역 변수는 메소드 내에서만 사용되며, 메소드의 실행이 끝나면 소멸된다.

    • 화면 출력

    System.out.println()이나 System.out.print()를 이용해서 데이터를 출력한다. println()은 출력 후 다음 행으로 이동하고, print()는 다음 줄로 넘어가지 않는다.

    System.out.println("Hello");
    System.out.print(2);

    2.2 식별자

    • 식별자

    식별자(identifier)란 클래스, 변수, 상수, 메소드 등에 붙이는 이름을 말한다.

    • 식별자 이름 규칙
    1. 특수문자, 공백은 식별자로 사용할 수 없으나 '_', '$'는 예외로 사용할 수 있다.
    2. 한글도 식별자로 사용 가능하다.
    3. 자바 언어의 키워드는 식별자로 사용할 수 없다.
    4. 식별자의 첫 번째 문자로 숫자 사용할 수 없다.
    5. 대소문자를 구별한다.
    6. 길이 제한이 없다.

    2.3 자바의 데이터 타입

    • 기본 타입(basic type) : 8개

      • boolean
      • char
      • byte
      • short
      • int
      • long
      • float
      • double
    • 레퍼런스 타입(reference type) : 1개

      • 배열에 대한 레퍼런스
      • 클래스에 대한 레퍼런스
      • 인터페이스에 대한 레퍼런스
    • 레퍼런스

    C/C++의 포인터와 비슷한 개념이다. 그러나 C/C++와 달리 실제 주소 값을 가지지 않는다. 지금은 다만 배열에 대한 주소 값 정도, 객체에 대한 주소 값 정도로 생각하고 넘어가자.

    • 문자열

    자바에서 문자열은 기본 타입에 속하지 않는다. JDK에서 제공하는 String 클래스를 이용한다.

    String toolName = "JDK";

    자바에서는 다음과 같이 문자열과 기본 타입의 + 연산이 실행되면, 기본 타입의 값이 문자열로 바뀌고 두 문자열이 연결된 새로운 문자열이 생성된다.

    System.out.println(toolName + "이 출시됨"); // "JDK이 출시됨" 출력
    • 변수와 선언

    변수는 데이터를 저장하는 공간이다. 변수를 선언하면 타입 크기의 메모리가 할당되며, 프로그램은 실행 중에 값을 쓰고 읽는 공간으로 사용한다. 선언과 동시에 초기화가 가능하며 변수를 선언한 후에는 다음과 같이 변수에 값을 저장하고 읽을 수 있다.

    • 리터럴(literal)

    리터럴이란 프로그램에 직접 표현한 값을 말한다. 정수, 실수, 문자, 논리, 문자열 타입 모두 리터럴이 있으며, 예를 들면 다음과 같다.

    34, 42.195, '%', true, "hello"
    • 정수 리터럴
    유형 설명 사례
    10진수 0으로 시작하지 않는 수 15 -> 10진수 15
    8진수 0으로 시작하는 수 015 -> 십진수 13
    16진수 0x로 시작하는 수 0x15 -> 십진수 21
    2진수 0b로 시작하는 수 0b0101 -> 십진수 5
    • 실수 리터럴

    소수점 형태나 지수(exponent) 형태로 실수를 표현한 값이다. 실수 리터럴은 double 타입으로 자동 처리되며, 변수와 함께 쓰면 다음과 같다.

    double d = 0.1234;
    double e = 1234E-4; // 1234E-4 = 1234 * 10^-4이므로 0.1234와 동일

    숫자 뒤에 f나 F를 붙이면 float, d나 D를 붙이면 double 타입으로 강제 변환할 수 있다.

    float f = 0.1234f;
    double w = .1234D;
    • 문자 리터럴

    단일 인용부호(' ')로 문자를 표현하거나 \u 다음에 문자의 유니코드 값을 사용하여 표현한다.

    'w', 'A', '글', \u0041
    1. null 리터럴

    null은 기본타입에 사용될 수 없고 객체 레퍼런스에 대입된다.

    int n = null; // 오류. 기본타입에 null 값 지정 불가능
    String str = null; // 정상
    1. 문자열(String) 리터럴

    문자열 리터럴은 이중 인용부호를 이용해 표현한다.

    1. Java 10부터 var 키워드를 사용하면 변수 타입 생략
    var price = 200; // int 타입으로 결정
    var name = "kitae"; // String 타입으로 결정
    var pi = 3.14; // double 타입으로 결정

    하지만, 변수 선언문에 초깃값이 주어지지 않으면 오류가 발생한다. 또한, var의 사용은 지역변수에만 한정된다.

    var name; // 컴파일 오류. 변수 name의 타입을 추론할 수 없음
    • 상수

    final 키워드를 사용해 상수를 만든다. 상수는 읽기 전용이라고 생각하면 편하다. 실행 중에 값을 바꿀 수 없다.

    final double PI = 3.141592;
    • 타입 변환

    변수나 상수 혹은 리터럴의 타입을 다른 타입으로 바꾸는 것을 말한다.

    • 자동 타입 변환

    치환문(=)이나 수식 내에서 타입이 일치하지 않을 때, 컴파일러는 오류 대신 작은 타입을 큰 타입으로 자동 변환한다.

    long m = 25; // 리터럴 25는 int 타입. 25가 long 타입으로 자동 변환
    double d = 3.14 * 10; // 실수 연산을 하기 위해 10이 10.0으로 자동 변환
    • 강제 타입 변환

    개발자가 강제로 타입 변환을 지시하는 경우이다.

    int n = 300;
    byte b = n; // 컴파일 오류. int 타입은 byte 타입으로 자동 변환 안 됨
    byte b = (byte)n; // n을 byte 타입으로 강제 변환. b = 44

    300은 byte 타입 (0-255 범위)의 범위보다 크기 때문에, 컴파일러가 자동 변환을 하게 되면, b에 300이 저장되지 않고 256을 뺀 나머지 (300 % 256 = 44) 값 44가 저장된다. 이처럼 큰 타입의 값을 작은 타입의 값으로 변환해야 할 때, 컴파일러는 자동 변환 대신 컴파일 오류를 발생시킨다. 하지만 강제 변환을 하면 데이터 손실이 발생한다.

    double d = 1.9;
    int n = (int)d; // 강제 타입 변환으로 n은 1이 됨

    1.9에서 소수점을 잘라버린 듯.

    2.4 자바에서 키 입력

    • System.in

    System.in은 키보드 장치를 직접 제어하고 키 입력을 받는 표준 입력 스트림 객체이다.

    키보드에서 치는 문자 -> System.in(바이트 표준 입력 스트림) -> 바이트 데이터 -> 자바 응용 프로그램(바이트 데이터를 문자로 변환)

    위의 과정처럼 문자를 바이트 데이터로 변환, 바이트 데이터를 다시 문자로 변환하는 과정이 번거롭다. 그래서 키보드에서 입력된 키를 문자나 정수, 실수, 문자열 등 사용자가 원하는 타입으로 변환해주는 Scanner 클래스를 사용한다.

    • Scanner를 이용한 키 입력
    1. Scanner 객체 생성
    Scanner  scanner = new Scanner(System.in);

    이 생성문을 통해

    키보드 문자 입력 -> System.in(바이트 표준 입력 스트림) -> 바이트 스트림 -> scanner(문자로 변환) -> 자바 응용프로그램

    이런 구조가 형성된다. 바이트들은 정수, 실수, 문자, 문자열 등 자바 응용프로그램이 원하는 타입으로 변환하여 리턴한다.

    즉 자바 응용프로그램에서 직접 하나하나 변환하지 않아도 되어 효율적이다.

    1. import문 사용
    import java.util.Scanner;

    java.util 패키지 않에 있는 Scanner를 이용하겠다는 뜻이다. 경로명을 지정해준 셈이다. import문이 없으면 자바 컴파일러가 Scanner 클래스의 코드가 어디에 있는지 알 수 없다.

    1. Scanner 클래스로 키 입력받기

    Scanner 클래스는 입력하는 키 값을 공백 문자 (' ', '\t', '\n') 기준으로 분리하여 토큰 단위로 읽는다.

    메소드 설명
    String next() 다음 토큰을 문자열로 리턴
    byte nextByte() 다음 토큰을 byte 타입으로 리턴
    short nextShort() 다음 토큰을 short 타입으로 리턴
    int nextInt() 다음 토큰을 int 타입으로 리턴
    long nextLong() 다음 토큰을 long 타입으로 리턴
    float nextFloat() 다음 토큰을 float 타입으로 리턴
    double nextDouble() 다음 토큰을 double 타입으로 리턴
    boolean nextBoolean() 다음 토큰을 boolean 타입으로 리턴
    String nextLine() '\n'을 포함하는 한 라인을 읽고 '\n'을 버린 나머지 문자열 리턴
    void close() Scanner의 사용 종료
    boolean hasNext() 현재 입력된 토큰이 있으면 true, 아니면 입력될 때까지 무한정 대기, 새로운 입력이 들어올 때 true 리턴, ctrl - z 키가 입력되면 입력 끝이므로 false 리턴
    • nextLine() -> 공백이 낀 문자열을 입력받는다.

      ​ -> Enter 키 입력을 기다리는 용도로 사용 가능. 빈 문자열("")을 리턴할 수 있다

    • next() -> 공백이 낀 문자열을 읽을 수 없다. 공백 이전의 문자열 하나만 리턴 ex) "Seoul Korea" -> Seoul 하나만 리턴

      ​ -> Enter 키를 계속 입력해도 다른 키가 입력될 때까지 기다린다. next()는 빈 문자열을 리턴 하지 않는다.

    1. Scanner 객체 닫기
    scanner.close();

    scanner 객체가 닫히면, System.in도 함께 닫힌다.

    2.5 연산

    a(피연산자) ==(연산자) n(피연산자)

    연산의 종류 연산자 연산의 종류 연산자
    증감 ++ -- 비트 & | ^ ~
    산술 + - * / % 논리 && || ! ^
    시프트 >> << >>> 조건 ? :
    비교 > < >= <= == != 대입 = *= /= += -= &= ^= |= <<= >>= >>>=
    • 증감 연산
    후위 연산자 내용 전위 연산자 내용
    a++ a를 1 증가하고 증가 전의 값 반환 ++a a를 1 증가하고 증가된 값 반환
    a-- a를 1감소하고 감소 전의 값 반환 --a a를 1 감소하고 감소된 값 반환
    • 논리 연산
    연산자 내용 예제 결과
    !a 반전 !(3<5) false
    a || b OR, 하나만 true여도 true (3>5)||(1==1) true
    a && b AND, a와b 모두 true인 경우에만 true (3<5)&&(1==1) true
    a ^ b XOR, a와 b가 서로 다를 때 true (둘 다 같을 경우 false) (3>5)^(1==1) true
    • 조건 연산자

    삼항 연산자라고도 한다

    condition ? opr2 : opr3

    condition이 true이면 opr2의 값이 되고, condition이 false이면 opr3의 값이 된다

    if(condition){
    opr2
    }else{
    opr3
    }

    과 같은 효과

    • 비트 연산

    비트 연산은 비트끼리 AND, OR, XOR, NOT 연산을 하는 비트 논리 연산과, 비트를 오른쪽이나 왼쪽으로 이동시키는 비트 시프트 연산이 있다.

    • 비트 개념

    2진수의 한 자리를 bit라고 부르며, 8개의 비트를 byte라고 한다.

    • 비트 논리 연산
    연산자 별칭 내용
    a & b AND 연산 두 비트 모두 1이면 1, 그렇지 않으면 0
    a | b OR 연산 두 비트 중 하나라도 1이면 1, 둘 다 0이면 0
    a ^ b XOR 연산 (같지 않으면) 두 비트가 다르면 1, 같으면 0
    ~ a NOT 연산 1을 0으로, 0을 1로 변환

    ex)

    byte flag; // 8개의 각 비트는 8개의 센서 값을 각각 가리킴
    ...
    if(flag & 0b0001000 = 0) System.out.print("온도는 0도 이하");
    else System.out.print("온도는 0도 이상");

    flag -> 7 6 5 4 3 2 1 0 & 0 0 0 1 0 0 0 -> 비트 3이 1인지 아닌지 판별하기 위함. 비트 3이 1이면 온도는 0도 이상, 비트 3이 0이면 온도는 0이하.

    • 비트 시프트 연산
    시프트 연산자 내용
    a >> b a의 각 비트를 오른쪽으로 b번 시프트한다. 최상위 비트의 빈자리는 시프트 전의 최상위 비트로 다시 채운다. 산술적 오른쪽 시프트라고 한다.
    a >>> b a의 각 비트를 오른쪽으로 b번 시프트한다. 최상위 비트의 빈자리는 항상 0으로 채운다. 논리적 오른쪽 시프트라고 한다.
    a << b a의 각 비트를 왼쪽으로 b번 시프트한다. 최하위 비트의 빈자리는 항상 0으로 채운다. 산술적 왼쪽 시프트라고 한다.

    a >> b -> 최상위 비트 이전 최상위 비트로 채운다.

    a >>> b, a << b -> 최상위, 최하위 비트는 0으로 채운다.

    시프트 연산자의 피연산자는 byte, short, int, long, char 타입만 가능하고, float, double, boolean은 사용할 수 없다.

    byte a = 5;
    byte b = (byte)(a << 2); // 0b00000101 -> 0b00010100 -> 20
    byte a = 20;
    byte b = (byte)(a >>> 2); // 0b00010100 -> 0b00000101 -> 5

    << 와 >>는 1비트 시프트할 때마다 나누기 2, 곱하기 2의 효과가 나타난다.

    • 비트 마이너스 표현

    ex) 0b00000001 -> 2 를 마이너스로 나타내고 싶다.

    -> 0b1 -> 최상위 비트를 1로 변환 -> 나머지 비트는 반전처리해준다. -> 0b11111110 -> -2

    2.6 조건문

    • 단순 if 문
    if(조건식){
    ... 실행 문장 // 조건식이 참인 경우
    }
    • if-else 문
    if(조건식){
    ... 실행 문장1
    }else{
    ... 실행 문장2
    }
    • 다중 if-else 문
    if(조건식1){
    실행 문장1; // 조건식1이 참인 경우
    }else if(조건식2){
    실행 문장2; // 조건식2이 참인 경우
    }...
    else{
    실행문장n; // 앞의 모든 조건이 거짓인 경우
    }
    • 중첩 if-else 문

    if 문이나 if-else 문, else 문의 실행 문장에 if 문이나 if-else 문을 내포할 수 있다.

    • 조건연산자 '?' ':'와 if-else 문으로 교체 가능하다
    i = a>b?a-b:b-a;
    
    if(a>b){
    i = a - b;
    }else{
    i = b - a;
    }
    • switch 문
    switch(식){
    
    case 값1:
    실행문장1;
    break;
    case 값2;
    실행문장2;
    break;
    ....
    default:
    실행문장n;
    }

    식을 먼저 계산하고 그 결과 값과 일치하는 case 문으로 분기한다. case 문의 실행 문장을 실행한 후 break를 만나면 switch 문을 벗어난다. 만일 어떤 case 문으로도 분기하지 못하는 경우 default 문으로 분기하여 실행문장 n을 실행한다.

    • switch 문 내의 break 문

    만일 case 문에 break 문이 없다면 break 문을 만날 때까지 아래의 case 문의 실행문장으로 계속 실행한다.

    char grade = 'A';
    switch(grade){
    case 'A':
    System.out.println("90~100점입니다.");
    case 'B':
    System.out.println("80~89점입니다.");
    break;
    case 'C':
    System.out.println("70~79점입니다.");
    break;
    }

    실행 결과

    90~100점입니다.
    80~89점입니다.

    case 문의 값은 정수 리터럴, 문자 리터럴, 문자열 리터럴만 허용한다.

    댓글

Designed by Tistory.