회고록 블로그

[공부 필기] Java 기본 공부하기 (4) 본문

2. 프로그래밍 언어 공부/Java

[공부 필기] Java 기본 공부하기 (4)

김간장 2021. 9. 1. 20:01

Java 공부 중에 개인적으로 필요한 내용들만 정리했다.

 

출처 : 윤성우 선생님, 윤성우의 열혈 Java 프로그래밍 강의, https://cafe.naver.com/cstudyjava

 

윤성우의 프로그래밍 스터디그룹 [C/... : 네이버 카페

윤성우의 스터디 공간입니다. C와 JAVA를 공부하시는 분들은 모두 들어오세요. ^^

cafe.naver.com

 


1. 상수

     ㄱ. 상수는 변수에게 상수의 성격을 부여해서 표현하거나, 사용자가 직접 값을 입력(*부가설명)해서 표현할 수 있음

     ㄴ. 정확하게 말하면 상수는 한번 값을 할당하면 그 값이 변하지 않는 변수

           (값에는 숫자, 문자 등이 들어갈 수 있음)

     ㄷ. 한번 할당되면 변경이 불가능하고, Java에서는 final 키워드를 이용해서 변수를 상수화시킴

     ㄹ. 상수의 이름은 '대문자'로 하는 것이 관례임

            (이름이 두 단어 이상이면 언더바로 연결함 e.g. MAX_SIZE 등)

     ㅁ. 선언과 동시에 초기화 하지 않을 수 있지만, 보편적으로 선언+초기화를 동시에 함

 

 

*부가설명

int num = 3 + 4;

3과 4는 메모리에 어딘가에 저장된 이후 CPU에 의해서 덧셈 연산이 되는데,

사용자는 이 3이라는 숫자가 저장된 메모리에 접근해서 변수처럼 값을 변경하거나 할 수 없음

(특정한 이름을 갖고 있어서 접근하거나 할 수 있는 것도 아니고, 메모리 어디에 이 값이 저장되어 있는지도 모름)

그렇기 때문에 여기에서의 3과 4는 상수라고 볼 수 있음.

정확하게는 '리터럴'이라고 함.

 

# 리터럴?

위키백과의 정의를 가져왔다.

"컴퓨터 과학 분야에서 리터럴(literal)이란 소스 코드의 고정된 값을 대표하는 용어다."

출처: https://ko.wikipedia.org/wiki/%EB%A6%AC%ED%84%B0%EB%9F%B4

 

나무위키 정의도 가져왔다.

"리터럴(literal)이란 소스 코드에서 특정한 자료형의 값을 직접 표현하는 방식을 말한다."

출처: https://namu.wiki/w/%EB%A6%AC%ED%84%B0%EB%9F%B4

 

즉, 아래와 같이 고정되어 있는 값들이다. 리터럴은 변수 초기화에 사용된다고 한다.

int num1 = 3; // 3은 리터럴
char ch1 = 'a'; // a는 리터럴
short num2 = 0xF // 0xF는 리터럴

System.out.println(3.012F+1.011F); // 3.012F와 1.011F는 리터럴

 

# 3, 'a', 0xF라는 리터럴은 데이터 타입을 선언하지 않았는데 메모리에 얼마만큼의 바이트로 저장될까.

→ 3은 정수형 리터럴이기 때문에 가장 기본적인 int형으로 저장된다. 따라서 메모리에서 4바이트를 차지한다.

→ 'a'는 기본 데이터형은 char로 저장되어 2바이트를 차지하고, 0xF도 마찬가지로 int형으로 저장된다. 

다만, int형을 넘어서는 값(e.g. 12345678912345678 등)을 주면 에러를 발생시킴

 


2. 이스케이프 시퀀스

     ㄱ. 백스페이스를 의미하는 문자는 '\b'(**부가설명)

 

 

**부가설명

문자를 다음과 같이 사용하면 알 수 없는 문자가 출력된다.

"Hel\blo"의 결과로 기대한 것은 "Helo" 였는데..

그 이유를 스택오버플로우에서 찾아왔다.

대충 해석해보자면.. IDE(여기에서는 eclipse를 사용함)는 \b를 자동적으로 무시하는데

그 이유는 IDE 라이브러리에 \b를 해석할(?) 라이브러리가 없기 때문이라고 한다.

결론적으로 IDE의 문제인 것이지, JAVA라는 프로그래밍 언어의 문제는 아니라는 이야기 같다.

실제로 cmd창에서 실행시키면 기대했던 결과가 출력되는 것을 알 수 있다.

출처: https://stackoverflow.com/questions/3328824/java-backspace-escape/3328871

 

Java backspace escape

I just tested the backspace escape as follows: System.out.println("Hello\b"); I expected to get the output: Hell But it was: "Hello" with a square block anyone knows how java handle this?

stackoverflow.com


3. 자동 형변환 vs 강제 형변환

     ㄱ. 형변환이 필요한 이유?

            → 연산(더하기, 빼기 등)을 할 때 피연산자의 자료형이 동일해야하기 때문

     ㄴ. 자동 형변환이 일어나는 경우

             → 자료형의 크기가 작은 값이 큰 값으로 바뀌어야 할 때

                  (바이트 수를 생각해보면 됨)

     ㄷ. 강제 형변환이 일어나는 경우

             → 자료형의 크기가 큰 값에서 작은 값으로 변경 해야할 때 사람이 직접 변환해줌

             → 소괄호 사용


4. 연산자

     ㄱ. 연산자의 우선순위표를 보며 코드를 작성하는 것도 좋지만,

           우선순위표에 의존하기보다 소괄호를 이용해주는 것도 좋음

     ㄴ. 나눗셈의 몫을 구하는 연산(/)과 나눗셈의 나머지를 구하는 연산(%)을 유의

     ㄷ. 복합 연산자 : a += b , a /= b , a %= b , a &= b , a <<= b 등

     ㄹ. 복합 대입 연산자를 사용하면 '형 변환이 필요 없다'

     ㅁ. 관계 연산자

            → 유의할 점!

                  일반적으로 7.0과 7은 다른 값이지만 아래의 코드는 true가 출력됨

                  그 이유는 형변환이 되기 때문 (***부가설명)

System.out.println(7.0 == 7); // 결과: true

     ㅂ. 논리 연산자(&&, ||, !) : 피연산자는 true/false가 올 수 있음

            → SCE(Short-Circuit Evaluation) 때문에 생기는 의도하지 않은 결과를 조심해야함

SCE 주의 [그림1]

[그림1]에서 num2의 값이 증가하지 않은 이유는 SCE 때문에 "++num1 == num3"이 실행된 후 뒤는 모두 생략됐기 때문

 

     ㅁ. 증감연산자(++)와 감소 연산자(--) 

           → ※참고사항 꼭 확인

 

 

***부가설명

Java에서 사실 7.0(실수형)과 7(정수형)은 값을 비교할 수 없다.

두 값을 비교하기 위해서는 먼저 '자료형'이 '일치'해야 하기 때문.

그렇기 때문에 Java는 두 개의 값을 비교하기 위해 형변환을 먼저한다.

 

그 결과, 아래의 코드 같은 경우 '7'이라는 정수(int형)가 자동 형변환이 되어 7.0이 돼버리고

System.out.println(7.0 == 7); // 결과: true

7.0과 자동 형변환이 된 7을 비교해서 'true'라는 결과를 출력하게 되는 것.

 

 

※ 참고사항

증감연산자와 감소연산자의 i++, ++i, i--, --i 는 "문장"의 끝을 기준으로 먼저 +/- 되느냐, 나중에 +/- 되느냐임

소괄호의 여부와 관계없음

 

좀 더 쉽게 말해서, 아래와 같은 코드가 있다고 가정.

int num = 1;
while ((num++) < 10) {
	if(num % 5 != 0) {
    	continue;
    }
	System.out.println(num);
}

소괄호가 있어서 num의 값이 1 증가된 후 숫자 10과 비교를 할 것 같아보이지만

num과 10을 먼저 비교한 후 num의 값이 1 증가되는게 맞음

따라서, 1과 10을 먼저 비교한 후 num의 값이 2가 되며, if문을 실행할 때는 num의 값이 2인 상태로 실행이 됨

 

또한, 위의 코드에서 num++과 ++num의 차이는 꽤나 크기 때문에 아래의 내용을 잘 기억해두어야 함


5. 비트 연산자

     ㄱ. 비트 연산은 정수에서 사용할 땐 의미가 있지만, 실수에서는 의미가 없음

           → 정수는 어떻게 비트로 배치되는지 비트열이 정확하게 예측 가능하기 때문

           → 실수는 지원하지도 않음 (그 이유는 #참고자료1에서 확인 가능)

     ㄴ. 비트 연산자는 &,  |, ^, ~, <<, >> 등이 있음

     ㄷ. 예시

...
public static void main(String[] args) {
    byte num = 0B101; // 10진수로는 5를 의미함

    // 2진수 101을 왼쪽으로 1칸 밀었을 때
    System.out.println(num << 1); // 결과: 10
    // 이유 : num은 00000101임 -> 왼쪽으로 1칸 시프트 -> 결과 00001010
    // 2진수 1010은 10진수로 10을 의미함

    System.out.println(num); //결과: 5
    // num에 저장된 값은 변하지 않음


    System.out.println(num <<= 1); // 결과: 10
    System.out.println(num); // 결과: 10
    // 'num <<= 1'는 'num = num << 1'인 것을 알 수 있음
}
...

※ 비트 쉬프트 연산자를 이용해서 곱셈과 나눗셈을 표현할 수도 있음

('<<' 연산자를 이용해서 비트를 왼쪽으로 1칸 이동시킬 때마다 값이 2배 증가하고

 '>>' 연산자를 이용해서 비트를 오른쪽으로 1칸 이동시킬 때마다 값이 2배 감소하기 때문)

 

사실 CPU에게 곱셈, 나눗셈은 (덧셈, 뺄셈과 보다 상대적으로) CPU 클럭을 많이 소모하는 연산이다보니 

CPU의 성능이 낮은 환경을 고려해서 곱셈을 직접 구현하기 위해 '비트 쉬프트 연산'을 사용하기도 함

 

 

#참고자료1.

https://kldp.org/node/4149

 

[질문] double형에서의 비트 연산.. | KLDP

글쓴이: 익명 사용자 / 작성시간: 월, 2002/11/04 - 1:09오전 *^^* 자바를 공부하다가 책에 있는 비트연산문제중에 막히는 부분이 있어서 질문 올립니다. double 변수를 선언하고 1234.5678과 같은 값으로

kldp.org

 

Comments