저를 포함한 초보자 분들에게 도움이 됐으면 좋겠습니다.
초보자 분들은 수박 겉핥기 식으로 알고 넘어가지 마시고, 조금이라도 왜 이렇게 프로그램이 돌아가는지알고 가시는 시간이 됐으면 좋겠습니다.

오늘은 java에 없어서는 안될 Class를 이야기해 보겠습니다.
일단 Class가 왜 자바에서 중요할까요?
Java는 OOP(객체지향 프로그래밍)을 지향합니다. C는 절차지향 프로그래밍이죠.
여기서 '객체'라는 것이 나오는데 이 '객체'를 중심으로 프로그래밍을 하는거죠.
그럼 객체는  뭘까요? Class를 이용하여 만들어진 것이라고 보시면 됩니다.
그럼 Class는? 객체를 생성하기 위한 틀 이라고 보시면 됩니다.
말이 어렵습니다.. 간단하게 가보죠.

게임을 시작하면 캐릭터를 만드는 창이 나옵니다.
캐릭터를 만드는 화면이 클래스 입니다. 이 화면을 통하여 캐릭터(객체)를 생성할 수 있죠.
우리는 이 클래스(캐릭터 생성화면)를 이용하여 캐릭터(객체)의 머리모양,눈모양,..... 등등 많은 것을 바꿀 수 있죠. 그리고 캐릭터를 생성을 하게됩니다. 이 생성된 캐릭터가 하나의 '객체'가 되는 것이죠.
다른 사람이 캐릭터를 만들게 된다면 어떨까요.
같은 캐릭터 생성화면(Class)을 사용하기 때문에 캐릭터(객체)는 전체적인 외형은 다를지라도, 머리모양,눈모양...등등 같은 속성을 가지게 되죠. 마찬가지로 '객체'가 생성되는 것이죠.

그럼 자바에선 어떻게 Class를 정의하고 객체를 만들까요? 이미 우리는 자바를 시작할 때 Class를 보았습니다.


(1)public class first{
	public static void main(String[] args) {
		System.out.println("Hello World!");
		
	}
}

처음 자바를 실행 해보면 'Hello World!'를 출력하는 코드가 나올 것입니다. 
이것도 하나의 class로 구성돼있습니다. (1)코드의 첫줄 public class first{ ~~ }에서 보듯 우리는 처음부터  Class를 사용하고 있는 것이죠.
Class는 간단하게 정의 할 수 있습니다.


 (2)public class second {  }

이런식으로 말이죠. 물론 second Class파일을 새로 만들어 주어야 합니다. 즉, first,second 2개의 자바 파일이 있는 것이죠. first는 class로 구성이 되어있지만 실질적으론 second의 객체를 만드는 역할을 할 것이고 second는 객체를 찍어내는 class(틀)역할을 할 것 입니다.

클래스는 만들었으니 이제 '객체'를 만들어 봅시다.
first에 second객체를 만들어 보겠습니다.


 
(3)public class first {	
        public static void main(String[] args) {
		    second create = new second();
	     }
}이와같이 < Class명 변수명 = new Class명(); > 이런식으로 객체를 생성 할 수 있습니다. 
객체를 생성할 때는 new키워드를 이용하여 만들어주고, new를 이용하게 되면 완전히 새로운 객체를 만들게 됩니다.
하지만, 이런 객체를 만들어도 (2)코드 second Class에서는 어떤 내용도 들어있지 않기에 깡통을 만드는 것과 같습니다. 그럼 일단 Class(틀)에 속성들을 넣어봅시다.



 (4)public class second {
	 String name = "Sims";
	 String head_Color = "black";
	
	 public void set_name(String change_name) {
	 	name = change_name;
	 }
	
	 public void set_headColor(String change_Color) {
	 	head_Color = change_Color;
	 }
	
	 public void walk() {
	 	System.out.println("걷는중");
	 }
	
	 public void attack() {
	 	System.out.println("공격");
	 }
}

(4)와같이 second에 머리색,아이디를 지정하는 변수를 만들고 이름,머리색을 바꿀 수 있는 메소드 또한 정의해 주면, 객체의 머리색을 바꿀수도 있고 아이디또한 바꿀 수 있습니다. 
그럼 어디서 머리색을 바꿀까요? 우리가 생성해준 first파일의 create객체를 이용하여 바꿀 수 있습니다.


(5)public class first {	
	public static void main(String[] args) {
		second create = new second(); (객체생성 = 캐릭터생성)
		create.set_headColor("red");
		System.out.println(create.head_Color); //red
		create.walk(); //걷는중
	}
}
create는 second틀을 이용하여 만들었기에 second안에 있는 변수(name,head_Color),메소드(walk,run,set_name,set_headColor)를 따로 생성하여 가지고 있는 것입니다. 그럼 create안에 있는 것들에 접근해보죠.
create. 를 이용하여 접근 할 수 있습니다. < . >이 키워드가 바로 내부에 있는 속성들을 접근 하는 키워드 입니다. 예를 들어 create.set_headColor(~~);를 한다면 create안에 있는 set_headColor 메소드에 접근하여 일을 수행하는 것이죠.

우리가 출력을 하기위해 사용했던 System.out.println()도 System이라는 객체안에 있는 out에 접근하여 out안에 있는 println메소드를 접근하여 출력을 해주었던 것입니다!
(여기서 System이라는 객체를 만들지 않았는데 어떻게 접근하냐! 라는 질문이 나올 수 있습니다.
나중에 static 키워드를 배우게 되는데 이놈은 객체를 만들지 않고 어디서든 접근이 가능합니다. System안에 있는 out이 static변수로 선언되어있기에 객체를 생성을 하지 않아도 접근이 가능합니다.)

지금까지 Class에 대해서 설명을 해보았습니다. 자바는 Class와 객체의 개념만 어느정도 습득한다면 쉬운 언어이므로 Class,객체에 대해서 좀 더 자세히 알아 보시는 것도 좋을 것 같습니다. 코드적으론 뜯어볼게 없었네요. 

다음은 상속에 대해서 올리도록 하겠습니다.


저를 포함한 초보자 분들에게 도움이 됐으면 좋겠습니다.
초보자 분들은 수박 겉핥기 식으로 알고 넘어가지 마시고, 조금이라도 왜 이렇게 프로그램이 돌아가는지알고 가시는 시간이 됐으면 좋겠습니다.

자! 오늘은 프로그래밍에 없어서는 안 될 자료형편입니다.
그럼 자료형이란 무엇일까요??
int, char, float, double, boolean ... 등등 '자료'의 '형태'를 나타내는 겁니다.
int는 정수라는 자료를 저장하겠다. char는 문자라는 자료를 저장하겠다.... 를 나타내는 거죠.

그럼 자료형이 왜 필요할 까요??
어떠한 정보인지 알려주기 위함이라고 생각합니다.
자, 예를 들어 제가 필기체로 '0'를 써놨습니다. 그럼 이게 숫자0을 뜻하나요 문자o을 뜻하나요? 
질문을 받은 여러분들은 완벽하게 설명할 수 없습니다. 틀릴 수도 있고 맞을 수도 있죠.
또, 알맞은 저장공간을 할당 시키기 위해서 입니다.(char 와 int의 할당 저장공간이 다름)


(1)	public static void main(String[] args) throws IOException {
		Character k = new Character('0');
		Integer a = new Integer(0);
		System.out.println(k.BYTES);
		System.out.println(a.BYTES);
	}
제가 필기체'0'은 '문자 자료형이다'라고 알려주게 된다면, 숫자와 문자 사이의 애매함이 없어질 뿐더러, 할당해야하는 저장 공간을 줄 일 수 있습니다. 
(1)코드를 보시죠. 코드의 결과는 2,4 가 나옵니다. char는 2바이트 저장 공간, int는 4바이트 저장 공간을 가집니다.  자료형을 선언함으로써 2바이트 저장 크기를 아끼게 되는 셈이죠.
이러한 애매함을 없애고 적절한 저장 공간 확보하기 위해 여러가지 자료형이 존재한다고 필자는 생각합니다.

간단하게 말해, 자료형은 어떤 형태의 자료가 들어갈지 알려주는 지표 역할을 한다고 생각하시면 됩니다.

자, 기본적인 자료형에 대한 설명은 끝이 났습니다.
이제부턴 기본 자료형 vs 참조 자료형에 대해서 알아 보도록 하겠습니다.

기본 자료형부터 알아보도록 하겠습니다.
기본 자료형의 형태는 다음과 같습니다. < '자료형 변수명 = 값' > 이처럼 사용하게 되죠. 
대개 int, char, boolean, long, short... 가 있습니다. (String은 제외입니다.)
기본 자료형은 변수안에 '값'을 넣게 됩니다.
예를 들어 int k = 3;이라 하면, k는 3을 넣게됩니다. 당연한 소리죠.
하지만 참조 자료형은 그렇지 않습니다.
참조 자료형은 이름에서도 알 수 있듯이 '참조'를 하게 됩니다.
참조 자료형이란,  값을 가지고 있는 '위치'(객체의 위치)를 나타내는 해쉬코드를 가지고 있는겁니다.
즉 실제 값에 접근 할 수 있는 객체의 위치를 변수에  가지고 있는 겁니다.
< '자료형 변수명 = new 자료형(~~)' > 대게 이처럼 사용 되죠.

대표적인 참조 자료형은 Array(배열)이 있습니다.
(2)public static void main(String[] args) throws IOException {
		int[] k = new int[]{0};
		System.out.println(k);
	}

(2) 코드를 봅시다.
int 정수형으로 한개의 값을 가지는 배열을 만들어 0 하나를 넣었습니다. 
그리고선 k를 출력해 보았습니다. 출력 결과는 어떻게 나올까요? 0이 나올까요? 아닙니다.
'[I@424c0bc4'이란 값이 나왔습니다. 424c0bc4를 값으로 가지고 있다는 것입니다.
424c0bc4가 뭘까요? k배열에 저장된 0에 접근하기 위해선 배열k라는 객체에 접근을 해야 합니다.
이 객체에 접근하기 위한 값이 해시코드값이라 생각하시면 됩니다.
이 해시코드값을 이용하여 객체에 접근한 후 0이 저장된 메모리로 접근할 수 있는것이죠.

기본 자료형과 참조 자료형을 판단하는 방법은 아주 쉽습니다.
변수명. 을 했을 경우 사용 할 수 있는 메소드가 있다? 라면 참조 자료형이라 생각하시면 됩니다.
아주 쉽게 구분 할 수 있죠. 하지만 가장 중요한 점은 아무래도 참조 자료형 변수는 실제 값을 가지는것이 아닌 hashcode(객체의 위치)라는 중간단계를 걸쳐야만 실제 값이 저장되있는 메모리에 접근 할 수 있다는 것을 아셨으면 합니다,

자료형은 코드적으론 뜯어볼 것은 많이 없었던 것 같습니다. 하지만 자료형에 대해서 알아가는 시간 되셨으면 좋겠습니다.

다음은 클래스에 대해서 올리도록 하겠습니다!

저를 포함한 초보자 분들에게 도움이 됐으면 좋겠습니다.
초보자 분들은 수박 겉핥기 식으로 알고 넘어가지 마시고, 조금이라도 왜 이렇게 프로그램이 돌아가는지알고 가시는 시간이 됐으면 좋겠습니다.

1. 자바 뜯어보기 - 입력편(Scanner) 보셨는지요? 안보고 오셨다면 한번 보고 오시는 것도 좋습니다.
http://sims-solve.tistory.com/2?category=747624


오늘은 Scanner에 이어서 BufferedReader에 대해서 낱낱히 살펴보겠습니다.

2. 입력 뜯어보기 - BufferedReader
가장 손쉽게 사용 할 수 있는 입력은 Scanner지만, 프로그래밍을 하다 보면 속도를 무시할 수 없습니다.
BufferedReader를 사용하면, Scanner보다 빠른 속도를 보장할 수 있기에 대개 Scanner보단 
BufferedReader를 선호합니다.  

BufferedReader를 설명하기 전에 System.in 표준입력으로 글자를 처리해 보겠습니다.  

(1)	public static void main(String[] args) throws IOException {
		System.out.println(System.in.read());
	}

Scanner편에서도 말했듯이  System.in은 표준출력인 키보드를 의미합니다. 
System.in은 InputStream으로 되어있습니다. InputStream은 8192퍼버 사이즈를 가질 수 있습니다.그래서  입력한 글자 다수를 모아 놓을 수 있죠. 입력된 글자들을 아스키코드 값으로 모아놓고 마지막에 13(LF,다음줄로), 10(CR,제일 처음칸으로)을 포함하여 (입력한 갯수 + 2)로 저장되있습니다.


 (2)  public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }


하지만! 여기선 .read()가 중요하게 작용합니다. 많은 글자를 넣어놨지만 .read()로 출력을 하게 되면
맨앞 글자의 아스키코값만 나오게 됩니다. 이유는 무엇일까요? 
사용자는 InputStream에 다수의 글자를 넣을 수 있지만, .read()의 결과값은 (2)소스에서 처럼 
getBufIfOpen()[pos++] & 0xff 입니다.즉, InputStream 내의 Buffer에 들어가있는 입력한 아스키코드중 맨앞 한개만 비트연산하여 뽑아주는 것입니다. 이렇게 보면 무슨 말인지 잘 이해가 가지 않습니다. 예를 보시죠!

만약 입력으로 123을 입력한다면, InputStream 내의 Buffer에 49 50 51 13 10 0 0 0 .... 이런식으로 저장이 됩니다. 그런데 .read()는 for문도 없고 단순하게 Buffer[pos++]를 실행하게되죠. 그럼 pos는 0인상태이므로 49 & 0xff 를 하게됩니다. &는 비트 연산이므로 지금은 모르셔도 상관없습니다. 
49 = 49 & 0xff라는것만 지금은 알아두시면 됩니다. 결국 49(=1)하나만 System.out.println으로 넘겨주게 되어 표준출력으로 아스키코드값 49가 출력이 됩니다. 디코더를 지정하지 않기도 하고 Byte버퍼를 사용하기에  아스키코드값을 원래 문자로 바꾸지 않고 그대로 출력을 하게 됩니다.

이렇게 되면 문제가 많아집니다. Scanner는 글자 수 상관없이 받을 수 있고, 입력한 그대로 형태를 출력할 수도 있는데 말이죠! 
그래서 Scanner는 사용하기 간단하다고 말을 했던 겁니다.

그럼 어떻게 문자열(다수의 문자)들을 처리, 아스키코드값이 아닌 입력 그대로의 문자로 처리할까요?
이번 주제의 주인공인 BufferedReader가 이러한 역할을 하게 됩니다.

InputStreamReader는 Byte 버퍼를 가지고 있습니다(아스키코드값). 이것을 Char 버퍼로 변경하여 입력한 문자 그대로 저장을 해줘야 하는데 그 역할을 하는 것이 바로 BufferedReader입니다.
간단하게 말해 Byte 버퍼 -> Char 버퍼로 변경하여 저장한다고 생각하시면 됩니다.

(3)	public static void main(String[] args) throws IOException {
		InputStreamReader k = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(k);
		System.out.println(br.readLine());
	}

자 그럼  한번 살펴보도록 하겠습니다.
(3) 코드에서 InputStreamReader는 버퍼의 크기, 어떤 디코더를 사용할지 등 입력에 필요한 데이터를 담고 있습니다. 이걸 BufferedReader의 매개변수로 넘겨주면, BufferedReader는 넘겨받은 InputStreamReader의 정보에 따라 같은 크기의 힙 버퍼,Char 버퍼를 생성합니다.(힙 버퍼와 캐릭터버퍼 총 2개)

가장 중요한 부분인 br.readLine()입니다. .readLine을 통하여 사용자가 입력을 하게 되는데,
실질적으로 입력을 받는 곳은 BufferedInputStream 의 getInfOpen().read() 부분입니다.
InputStream과 같이 native로 지정되어 실질적인 입력 처리는 다른언어로 처리됩니다.
입력을 받으면 heapbyBuffer에  아스키코드값을 저장을 합니다. (실질적으론 InputStreamReader의 ByteBuffer와 같습니다. 참조를 한다는 소리죠!)
그리고 나서, 저장해두었던 디코더를 형식으로 아스키코드를 캐릭터로 바꾸게 됩니다.


 (4)DoubleByte Class
 while (sp < sl && dp < dl) {
                    // inline the decodeSingle/Double() for better performance
                    int inSize = 1;
                    int b1 = sa[sp] & 0xff;
                    char c = b2cSB[b1];
                    if (c == UNMAPPABLE_DECODING) {
                        if (sl - sp < 2)
                            return crMalformedOrUnderFlow(b1);
                        int b2 = sa[sp + 1] & 0xff;
                        if (b2 < b2Min || b2 > b2Max ||
                            (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {
                            return crMalformedOrUnmappable(b1, b2);
                        }
                        inSize++;
                    }
                    da[dp++] = c;
                    sp += inSize;
                }

(4)코드를 걸쳐 캐릭터로 바꾸게 되는데, b2cSB가 디코더 역할을 한다고 볼 수 있습니다.
b2cSB은 아스키코드 값대로 모든 문자가 배열형태로 저장되어 있어, b2cSB[아스키코드값]으로 접근하여 해당 문자를 CharBuffer에 저장합니다. 
이 저장한 버퍼내용을 하나의 String형태로 만들어System.out.printlm()에게 넘겨주면 사용자가 볼 수 있게 처리하여 출력을 볼 수 있는 겁니다.

지금까지 입력하기 위해 BufferedReader가 어떤식으로 돌아가는지 자세히 뜯어보았습니다.
어떠신가요? 지금까지 단순한 암기로 입력을 사용하고 있으셨지 않았나요? 이 모든 과정을 안다는건 
무리가 있지만, 그래도 어떤 역할을 하는지는 알고 넘어가야 되지 않을까요? 
이번기회에 BufferedReader가 어떻게 돌아가는지 이해하고 넘어가시죠!

감사합니다.
다음은 자료형에 대해서 올리도록 하겠습니다!

+ Recent posts