2장 연습문제

2021. 11. 3. 19:17자바/명품자바프로그래밍 연습문제

2021.11.03~

예제 2-1

/*
* 소스 파일 : Hello.java
*/
public class Hello {
	
	public static int sum(int n, int m) {
		return n + m;
	}
	
	//main() 메소드에서 실행 시작
	public static void main(String[] args) {
		int i = 20;
		int s;
		char a;
		
		s = sum(i, 10);  //메소드 호출
		a = '?';
		System.out.println(a);
		System.out.println("Hello");
		System.out.println(s);
	}
}

*클래스 만들기

자바 프로그램의 작성에 있어 가장 기본적이면서도 중요한 것은, 클래스를 만들고, 그 안에 변수, 상수, 함수(메소드) 등 모든 프로그램 요소를 작성한다는 점이다. 클래스 바깥에 어떤 것도 작성해서는 안 된다. 다음은 클래스 Hello를 선언하는 코드이다.

 class 키워드로 클래스 이름을 선언하고 '{'와 '}' 사이에 필드(변수) 메소드(함수) 코드를 작성한다. public은 자바의 접근지정자(accss specifier)로서 다른 클래스에서 클래스 Hello를 자유롭게 사용할 수 있다는 선언이다.

 

*주석문

주석문은 프로그램의 실행에 영향을 끼치지 않으며, 프로그램에 대한 설명이나 특이사항 등을 자유롭게 기록하기 위해 사용한다. 주석문은 다음 두 가지 방법으로 만들 수 있다.

//한라인 주석, 행이 끝날 때까지 주석으로 처리

/*

여러 라인 수족으로 /* */로 구성

*/

 

*main() 메소드

자바 프로그램은 다음과 같은 형식의 main()메소드에서부터 실행을 시작한다. public static void main(String[] args) { }

main()은 반드시 public, static,void 타입으로 선언되어야 하며, 한 클래스에 2개 이상의 main()을 작성하면 안 된다. 자바 응용프로그램이 여러 클래스로 이루어지는 경우, 실행을 시작할 클래스에만 main()을 두면 되므로, 모든 클래스가 main()을 가지지는 않는다. 

(String[] args는 실행하면서 인수로 받아오는 것들을 처리하기 위한 매개변수 형식임)

 

*메소드

클래스의 멤버 함수를 자바에서는 메소드라고 부른다. 메소드의 이름은 개발자가 지정하며, 메소드 개수에는 제한이 없다. 메소드 작성이나 호출 방법은 기본적으로 c/c++의 함수와 같다. 다음은 메소드 sum()을 작성한 사례이다.

public static int sum(int n, int m) {  //매개변수 n,m

   return n+m;

}

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

int i = 20;

s = sum(i, 10);

이 코드는 변수 i의  값 20과 정수 10을 sum()의 매개변수 n,m에 각각 전달한다. sum()은 n과 m 값을 더하여 30을 리턴한다. 

 

*변수 선언

변수(variable)란 프로그램 실행 동안 데이터를 저장하는 공간으로 개발자가 이름을 붙이고 다음과 같이 선언한다.

int i;  char a;

메소드 내에 선언되어 사용되는 변수를 지역변수(local variable)라고 한다. 지역 변수는 메소드 내에서만 사용되며, 메소드의 실행이 끝나면 소멸된다. 다음과 같이 선언하면 선언과 동시에 값을 초기화할 수 있다.

int i=20;

 

*문장

자바에서 모든 문장은 다음과 같이 ';'로 끝나야 한다.

자바 컴파일러는 ';'를 문장의 끝으로 인식하므로 한 문장이 반드시 한 줄에 작성될 필요는 없다. 다음과 같이 작성해도 정상적인 문장으로 인식된다.

s = sum(i,

         20);

주석문 끝에는 ';'를 붙일 필요가 없다.

 

*화면 출력

정수,문자,문자열 등 프로그램에서 사용하는 데이터를 화면에 출력하기 위해 System.out,println()이나 System.out.print()를 이용하면 된다. System.out.println()은 출력 후 다음 행으로 이동하지만, print()는 다음 줄로 넘어가지 않는다. 화면에 출력하는 코드 사례는 다음과 같다.

 

2-2

*식별자 이름 규칙

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

 

특수문자,공백 사용 불가 (단, '_'나 '$' 사용 가능)

true,false,null,if,while,class 등 자바 키워드 등 사용 불가

첫번째 문자로 숫자 사용 불가

//식별자로 사용할 수 있는 예
int name;
char student_ID;  //'_' 사용 가능
void $func() {}  //'$' 사용 가능
class Monster3 {} //숫자 사용 가능
int whatYourNameMyNameIsKitae; //길이 제한 없음
int barChart;  //대소문자 구분. barChart와 barchart는 다른 이름
int barchart;
int 가격; //한글 식별자 사용 가능
		
        
//식별자로 사용할 수 없는 예
int 3Chapter; //첫 번째 문자로 숫자 사용 불가
class if {} //자바의 예약아 if 사용 불가
char false; //자바의 예약어 false 사용 불가
void null() {} //자바의 예약어 null 사용 불가
class %calc {} //특수문자 '%' 사용 불가

 

예제 2-2

//상수 PI를 선언하고 원의 면적을 구하는 프로그램을 작성하기

public class Test1 {
	public static void main(String[] args) {
		final double PI = 3.14;
		
		//원의 반지름
		double radius = 10.0;
		//원의 면적 계산
		double circleArea = radius*radius*PI;
		
		//원의 면적을 화면에 출력한다.
		System.out.println("원의 면적 = " + circleArea);
	}
}

 

2-3

*자바의 데이터 타입

데이터 타입이란 자바에서 다룰 수 있는 데이터의 종류


//기본 타입 : 8개
boolean, char, byte, short, int, long, float, double
//레퍼런스 타입
    -배열에 대한 레퍼런스 : 배열에 대한 주소 값
    -클래스(class)에 대한 레퍼런스 : 객체에 대한 주소 값
    -인터페이스(interface)에 대한 레퍼런스

//문자열 저장 방법

String s = new String("문자열");
String s2 = "문자열";
String s3 = "추가문자";
String s4 = s3;

 

 

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

 - 34, 42.195, '%', true, "hello"

//정수&실수,문자,문자열,논리 리터럴

정수&실수 리터럴 : 값 그 자체

문자 리터럴 : ' '(따옴표 1개짜리)

문자열 리터럴 : " "(따옴표 2개짜리)

논리 리터럴 : true, false로 표현

 

-정수 리터럴은 int 타입으로 자동 컴파일된다. 만일 long 타입으로 지정하려면 숫자 뒤에 L 또는 l을 붙이면 된다. 예를 들면 다음과 같다.

long g = 24L;   //24L은 24l과 동일

 

-실수 리터럴은 소수점 형태나 지수 형태로 다음과 같이 실수를 표현한 값이다.

실수 리터럴은 double 타입으로 자동 처리되며, 변수와 함께 쓰면 다음과 같다.

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

float f = 0.1234f;

double w = .1234D;

 

-문자 리터럴은 단일 인용부호(' ')로 문자를 표현하거나 \u 다음에 문자의 유니코드 값을 사용하여 표현한다. 예를 들면 다음과 같다.

'w', 'A', '가', '*', '3', '글', \u0041

문자 리터럴을 변수와 함께 쓰면 다음과 같다.

char a = 'A';

char b = '글';

char c = \u0041;  //문자 'A'의 유니코드 값(0041) 사용

char d = \uae00;  //문자 '글'의 유니코드 값 (ae00) 사용

 

-특수문자 리터럴도 있다. 백슬래시(\) 다음에 특수 기호를 붙여서 표현한다. 특수 문자를 이스케이프 시퀀스(escape sequence)라고도 하며 그 종류는 다음과 같다.

 

-논리 리터럴과 boolean 타입

논리 리터럴은 true, false 두 개밖에 없으며, boolean 타입의 변수에 직접 치환하거나 조건문에 사용한다. true와 false의 사용 예는 다음과 같다.

 

*기본 타입 이외의 리터럴

자바에서 기본 타입 리터럴 외에 자주 사용되는 다음 2가지 리터럴이 있다.

1)null 리터럴 : null은 기본 타입에 사용될 수 없고 객체 레퍼런스에 대입된다. 어떤 것도 참조하지 않는 null 값 표현할 때 사용

  ex) int n = null;   //오류. 기본 타입에 null 값을 지정할 수 없다.

       String str = null;  //정상

2)문자열(String) 리터럴 : 문자렬 리터럴은 "Hello"와 같이 이중 인용부호로(="  ") 표현하며, 간단히 문자열이라고도 한다

  ex) "Good", "Morning", "자바", "3.19", "26", "a"

 자바에서 문자열 리터럴을 포함하여 모든 문자열은  String 클래스의 객체이다. 그러므로 문자열 리터럴은 다음과 같이 String 객체에 저장한다.

  ex) String str = "Good";

 

*상수 만드는 법

: 변수 선언 시 final 키워드를 사용.

상수는 변수와 달리 실행 중에 값이 바꿀 수 없다.

ex) final double  PI = 3.141592;

   :상수  :데이터 :상수  :초기화

    선언   타입   이름

 

*타입 변환

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

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

  ex) long m = 25;

      double d = 3.14 * 10;

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

 ex) long m = 25;

     double d = 3.14 * 10;

 2)강제 타입 변환 : 개발자가 강제로 타입 변환을 지시하는 경우. 강제 타입 변환을 캐스팅(casting)이라고도 부른다.

 ex) int n = 300;

 

예제 2-3

//자통 타입 변환과 강제 타입 변환이 들어있는 코드이다. 실행 결과는 무엇인가?

public class Test1 {
	public static void main(String[] args) {
		byte b =127;
		int i = 100;
		System.out.println(b+i); //b가 int 타입으로 자동 변환(자동 변환은 크기가 작은게 큰걸로 변환됨)
		System.out.println(10/4); 
		System.out.println(10.0/4); //4가 4.0으로 자동 변환 (실수 나누기이므로 결과는 25)
		System.out.println((char)0x12340041); 
		System.out.println((byte)(b+i)); 
		System.out.println((int)2.9 + 1.8); 
		System.out.println((int)(2.9 + 1.8)); 
		System.out.println((int)2.9 + (int)1.8); 		
	}
	
	/*정답
	 * byte = 1비트,   int = 4비트,   byte&int 둘 모두 정수형 테이터 타입의 변수
	 * b+i = 227
	 * 10/4 = 2 (둘 다 정수 int 타입)
	 * 2.5  //틀림
	 * A  //틀림
	 * -29  //틀림
	 * 3.8
	 * 4
	 * 3
	 */
}

정수 / 정수  -> 정수 출력

실수 / 정수  -> 실수 / 실수 -> 실수 출력

 

 

2-4

*자바에서 사용자로부터 키 입력 받는 방법

 1)System.in : 표준 입력 스트림 객체

 

예제 2-4

//Scanner 클래스로 이름, 도시, 나이, 체중, 독신 여부를 입력받고 다시 출력하는 프로그램을 작성하라.

import java.util.Scanner;

public class Test1 {
	public static void main(String[] args) {
		System.out.println("이름, 도시, 나이, 체중, 독신 여부를 빈칸으로 분리하여 입력하세요");
		Scanner scan = new Scanner(System.in);
		
		String name = scan.next();
		System.out.print("이름은 " + name + ", ");
		
		String city = scan.next();
		System.out.print("도시는 " + city + ", ");
		
		int age = scan.nextInt();
		System.out.print("나이는 " + age + ", ");
		
		double kg = scan.nextDouble();
		System.out.print("체중은 " + kg + ", ");
		
		boolean single = scan.nextBoolean();
		System.out.print("독신 여부는 " + single + ".");
		scan.close();
	}
}

 

2-5 연산

*연산 : 주어진 식을 계산하여 결과를 얻어내는 과정

-> 연산자(operator), 피연산자(operand), 식(expression)

 

<연산 종류와 연산자>

연산의 종류 연산자
증감 ++   --
산술 +   -   *   /   %
시프트 >>   <<   >>>
비교 >   <   >=   <=   ==   !=
비트 &   |   ^   ~
논리 &&   ||   !   ^
조건 ?   :
대입 =   *=   /=   +=   -=   &=   ^=   |=   <<=   >>=   >>>=

 

*연산자 우선순위

-여러 개의 연산자가 있는 경우 : 우선순위가 높은 연산자를 먼저 처리한다. & 우선순위가 동일하면 왼쪽에서 오른쪽으로(-->) 처리한다. 단, 대입 연산자, --, ++, +, -, !, 타입 변환 연산자 등은 오른쪽에서 왼쪽으로(<--) 처리한다.

-괄호는 항상 최우선적으로 처리한다. 식에 다수의 괄호가 포함된 경우 왼쪽에서 오른쪽으로(-->) 처리하며, 괄호가 다시 괄호를 포함한 경우는 안쪽부터 먼저 처리한다.

-복잡한 수식의 경우는 괄호로 묶어서 표시하는 것이 코드의 가독성을 높이며 예기치 못한 오류 발생을 줄인다.

 

<연산자 우선순위>

우선순위 높음 ++(postfix)   --(postfix)
   |
   |
   |
   |
   |
   |
   |
   |
   |
   |
   |
   |
  V
+(양수 부호)   -(음수 부호)   ++(prefix)   --(prefix)   ~   !
형 변환(type casting)
*   /   %
+(덧셈)   -(뺄셈)
<<   >>   >>>
<>   <=   >=   instanceof
==   !=
& (비트 AND)
^ (비트 XOR)
| (비트 OR)
&& (논리 AND)
|| (논리 OR)
? : (조건)
  낮음 =   +=   -=   *=   /=   %=   &=   ^=   |=   <<=   >>=   >>>=

 

1) 산술 연산자 : +(더하기), -(빼기), *, /(나누기), %(나머지) 

ex) 69/10 = 6,  69%10 = 9

- / (나누기) :

   (1) 정수 / 정수 = 실수 (소수점 이하는 결과에 반영되지 않음)

   (2) 실수 / 정수 = 실수 (나누기 연산은 둘 중 하나만 실수기만 해도 실수 연산으로 바뀌어서 결과는 실수가 나옴)

   (3) 정수 / 실수 = 실수

- % (나머지) :

   (1) 정수 % 정수 = 정수(만 가능, 실수는 불가능)

 

-%연산자는 나저미 연산자라 결과값이 나누는 수보다 무조건 작기 때문에, 나눠지는 정수가 홀수인지 짝수인지 구분할 때, n 값이 a의 배수인지 확인할 떄도 활용됨

ex 1) int r = n % 2;  // n이 홀수이면 r은 1, 짝수이면 r은 0

ex 2) int s = n % 3;  // n이 3의 배수이면 s는 0

 

<예제 2-5>

//예제 2-5 : /와 % 산술 연산
//초 단위의 정수를 입력받고, 몇 시간, 몇 분, 몇 초인지 출력하는 프로그램을 작성하라

import java.util.Scanner;

public class ScannerEx{
	public static void main(String args[]) {
		Scanner scan = new Scanner(System.in);
		System.out.print("정수를 입력하세요:");
		int time = scan.nextInt(); // 정수 입력
		System.out.print(time + "초는 ");
		
        // Ex 1
		int hour = time / 3600;
		System.out.print(hour + "시간, ");
		int minute = (time / 60) % 60;
		System.out.print(minute + "분, ");
		int second = time % 60;
		System.out.println(second + "초입니다." );
		
		// Ex 2
		System.out.print(time + "초는 " + hour + "시간, " + minute + "분, " + second + "초입니다." );
		
		scan.close();
	}
}

/* 실행결과
정수를 입력하세요:5000
5000초는 1시간, 23분, 20초입니다.
*/

 

2) 증감 연산 : ++, --

(1) 전위 연산자 : 연산자가 변수의 앞에 붙음. ++가 계산되어 연산 결과로 계산 후의 값을 반환함

ex) ++a, --a

(2) 후위 연산자 : 연산자가 변수의 뒤에 붙음. ++가 계산되어 변수의 값은 ++가 되지만, 증가되기 전의 변수 값을 반환함

ex) a++, a--

 

<증감 연산자>

후위 연산자 내용 전위 연산자 내용
a++ a를 1 증가하고, 증가 전의 값을 반환함 ++a a를 1 증가하고, 증가된 값을 반환함
a-- a를 1 감소하고, 감소 전의 값을 반환함 --a a를 1 감소하고, 감소된 값을 반환함

ex 1)

a = 1;

b = ++a;

-> a = 2, b = 2

ex2)

a = 1;

b = a++;

-> a = 2, b = 1

 

3) 대입 연산자 : 연산자의 오른쪽 식의 결과를 왼쪽에 있는 변수에 대입한다.

ex 1)

int a = 1, b = 3;

a = b;

a += b;

 

<대입 연산자>

대입 연산자 내용 대입 연산자 내용
a = b b의 값을 a에 대입 a &/ b a = a & b와 동일
a += b a = a + b와 동일 a ^= b a = a ^ b와 동일
a -= b a = a - b와 동일 a |= b a = a | b와 동일
a *= b a = a * b와 동일 a <<= b a = a << b와 동일
a /= b a = a / b와 동일 a >>= b a = a >> b와 동일
a %/ b a = a % b와 동일 a >>>= b a = a >>> b와 동일

 

<예제 2-6>

//예제 2-6 : 대입 연산자와 증감 연산자 사용
//다음은 대입 연산자와 증감 연산자를 활용하는 사례이다. 실행 결과는 무엇인가?


import java.util.Scanner;

public class ScannerEx {
	public static void main(String args[]) {
		// 대입 연산자 사례
		int a=3, b=3, c=3;
		a += 3;
		b *= 3;
		c %= 2;
		System.out.println("a="+ a +", b=" + b + ", c=" + c);
		
		// 증감 연산자 사례
		int d=3;
		a = d++; // a=3, d=4
		System.out.println("a=" + a + ", d=" + d);
		
		a = ++d; // a=5, d=5
		System.out.println("a=" + a + ", d=" + d);
		
		a = d--; // a=5, d=4
		System.out.println("a=" + a + ", d=" + d);
		
		a = --d; // a=3, d=3
		System.out.println("a=" + a + ", d=" + d);
	}
}

 

4) 비교 연산과 논리 연산

비교 연산자 : 두 개의 피연산자 비교해 논리값을(true, false) 내는 연산자

논리 연산자 : 논리값을(true, false) 대상으로 AND, OR, XOR, NOT의 논리 연산을 하여 논리값을 내는 연산자

 

<논리 연산자>

연산자 내용 예제 결과
!a a가 true이면 false, false이면 true !(3<5) false
a || b a와 b의 OR연산, a와 b 모두 false인 경우에만 false
-> a와 b 둘 다 false일 때만 false, 나머지 경우는 모두 true
(3>5) || (1==1) true
a && b a와 b의 AND연산, a와 b 모두 true인 경우에만 true
-> a와 b 둘 다 true일 때만 true, 나머지 경우는 모두 false
(3<5)&&(1==1) true
a^b a와 b의 XOR연산, a와 b가 서로 다를 때 true
-> a와 b가 서로 다를 때만 true, 같으면 false
(3>5)^(1==1) true

위의 예제처럼 비교 연산자와 논리 연산자를 복합하여 사용할 수 있다

 

Ex)

(age >= 20) && (age < 30) : age가 20 이상이고 30 미만인 경우에만 true값을 냄 -> 나이(int age)가 20대인 경우

(c >= 'A') && (c <= 'Z') : c가 'A' 이상이고 'Z' 이하인 경우에만 true값을 냄 -> 문자(char c)가 대문자인 경우

(x >= 0) && (y >= 0) && (x <= 50) && (y <= 50) : x가 0 이상이고 50이하이고, y도 0 이상이고 50 이하인 경우에만

                                                                           true값을 냄 -> (x,y)가 (0.0)과 (50,50)의 사각형 내에 있는 경우 

 

<예제 2-7>

//예제 2-7 : 비교 연산과 논리 연산
//다음은 비교 연산자와 논리 연산자의 사례이다. 실행 결과는 무엇인가?



public class ScannerEx {
	public static void main(String[] args) {
		//비교 연산
		System.out.println('a' > 'b'); //아스키코드 a:097, b:098
		System.out.println(3 >= 2);
		System.out.println(-1 < 0);
		System.out.println(3.45 <= 2);
		System.out.println(3 == 2);
		System.out.println(3 != 2);
		System.out.println(!(3 != 2));

		//비교 연산과 논리 연산 복합
		System.out.println((3 > 2) && (3 > 4));
		System.out.println((3 != 2) || (-1 > 0));
		System.out.println((3 != 2) ^ (-1 > 0));
	}
}

결과

false
true
true
false
false
true
false

//비교 & 논리 연산 복합
false
true
true

01

이 예제 문제를 풀면서 line 19인 System.out.println((3 != 2) || (-1 > 0)); 에서 "Dead code"라는 경고 표시가 떴다.

이게 무엇인가 하고 구글링을 해보니 Dead code란 전혀 실행되지 않는 코드를 의미하고, 이클립스 IDE가 성능이 너무 좋아서 나오는 경고라고 한다. 결과를 출력하는데 이상이 생기는 것은 아니지만 절대로 출력될 일이 없는 코드이기 때문에 작동하는 시간이 더 오래 걸리고 메모리만 잡아 먹는다고 한다.

논리 조건이 복잡하고 코드가 실행되지 않는다는 것을 직관적으로 확인하기 힘들 때 유용하다는데,,, Dead code 자체는 실행될 일이 절대 없는 코드를 말하니까 코드 변경할 일이 없으면 지우는 것이 효율성을 높이는데 도움이 될 것이라고 한다.

그런데 이 부분에서 도대체 왜 데드코드 경고가 뜨는지 모르겠다.. 아는 분 참견해주세효..

각설하고 넘어가면..

 

 

5) 조건 연산

조건 연산자 : 삼항(ternary) 연산자. 3개의 피연산자로 구성되어 있다.

조건 연산자의 형식 :    condition ? opr2 : opr3

-> condition(조건문)이 true이면 위 식의 결과값은 opr2의 값이 되고, false이면 opr3의 값이 된다. (opr2, opr3에는 식과 값이 올 수 있음)

 

Ex)

int x = 5;

int y = 3;

int s = (x>y)?1:-1

->실행 결과 : 1 (x가 y보다 크기 때문에 1이 s에 대입된다)

 

<예제 2-8>

//예제 2-8 : 조건 연산
//다음은 조건 연산자의 사례이다. 실행 결과는 무엇인가?


public class ScannerEx {
	public static void main(String[] args) {
		int a = 3, b = 5;
		System.out.println("두 수의 차는 " + ((a>b)?(a-b):(b-a)));
	}
}

 

 

6) 비트 연산

비트 연산 = 비트 논리 연산 + 비트 시프트 연산

-> 비트 논리 연산 : 비트끼리 AND, OR, XOR, NOT 연산을 함

-> 비트 시프트 연산 : 비트를 오른쪽이나 왼쪽으로 이동시킴

 

-비트 개념 :

컴퓨터의 모든 정보는 0과 1값만 가지는 2진수로 다루어지고 저장되며, 2진수의 한 자리를 비트(bit)라 부르고 비트 8개를 묶어서 바이트(byte)라고 한다.

ex) 십진수 10을 한 바이트로 표현하면 00001010이다. 

 

(1) 비트 논리 연산 : 피연산자의 각 비트들끼리 AND, OR, XOR, NOT의 논리 연산. 총 4 개의 연산자가 있음( &, |, ^, ~ )

<비트 논리 연산자>

연산자 별칭 내용
a & b AND 연산 두 비트 모두 1이면 1, 그렇지 않으면 0
-> 두 비트가 다 1일 때만 1
a | b OR 연산 두 비트 모두 0이면 0, 그렇지 않으면 1
-> 두 비트가 다 0일 때만 0
a ^ b XOR 연산 두 비트가 다르면 1, 같으면 0
-> 두 비트가 다를 때만 1
~ a NOT 연산 1은 0으로, 0은 1로 변환

Ex) 어떤 비트가 1인지를 검사할 때 &(AND) 연산자를 이용한다. 

//p89의 비트 논리 연산활용 사례
//냉장고의 온도가 0도 이상인지 판별하는 코드

import java.util.Scanner;

public class ScannerEx {
	public static void main(String args[]) {
		byte flag = 113; //3번째 비트값이 0임 // 8개의 각 비트는 8개의 센서 값을 각각 가리킴
		if((flag & 0b00001000) == 0) System.out.print("온도는 0도 미만"); 
		//3번째 비트가 0일 때 -> 냉장고의 온도가 0도 미만
		//3번째 비트가 1일 때 -> 냉장고의 온도가 0도 이상
		else System.out.print("온도는 0도 이상");
	}
}

 

(2) 비트 시프트 연산 : 비트 시프트 연산(shift operator)은 새로운 비트를 오른쪽이나 왼쪽 끝에 삽입하면서 비트의 자리를 이동시키는 연산이다. 저장 공간의 크기가 정해져 있으므로 시프트되는 방향에 따라 끝에 있는 비트는 사라지게 된다.

<비트 시프트 연산자>

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

*최상위 비트(MSB) : 수를 표현하는 이진수의 제일 높은 자리수

*최하위 비트(LSB) :  수를 표현하는 이진수의 제일 낮은 자리수

ex) 21을 8비트의 이진수로 표현하면 00010101이고, 최상위 비트는 0이고 최하위 비트는 1이다.

 

시프트 연산의 피연산자로 가능한 것 : byte, short, int, long, char 타입 (float, double, boolean타입은 사용불가함)

<< 연산자는 왼쪽 시프트 연산자로서 각 비트를 왼쪽으로 이동시키며, 오른쪽 끝에는 항상 비트 0이 삽입된다.

>>> 연산자는 비트를 오른쪽으로 이동시키며, 왼쪽 끝에는 항상 비트 0이 삽입된다.

>> 연산자는 오른쪽 시프트 연산자이지만, 왼쪽 끝의 최상위 비트에는 시프트 이전의 최상위 비트가 그대로 삽입된다.

(<<연산자는 최상위 비트가 1일 때인 음수를 시프트하여 최상위 비트가 0인 양수가 되는 오버플로가 발생할 수 있으므로 주의해야 함)

(byte, short, char 타입에 대해서는 시프트 시 int 타입으로 변환되어 연산이 일어나므로 원하지 않는 결과가 발생할 수 있음)

 

<예제 2-9>