본문 바로가기

프로그래밍./Java

java에서 C와 다른 차이점 몇가지.




define이 없다. 매크로가 없다.
사실.. 어떻게 보면 C에서도 define 없어도 되긴하다.
매크로 함수가 아닌 이상 const와 큰 차이도 없으니까.

그래서 그런지 자바로는..
일단 동일한 기능을 구현해야 하니까 그 특징에 맞춰서.
1. 어디서든 사용이 가능해야 한다. - static 사용.
2. 처음 설정 된 값이 변경되선 안된다. - final 사용.

이 2가지를 해주면 되는데.
변수의 경우 static final int test; 만 해주면 안되고 초기 값도 잡아줘야 한다.
사실 당연한 소리다. 값을 변경하지 못할테니 처음에 생성할 때 잡아줘야지.
별 생각없이 만들면, 왜 안되지- -? 하고 멍때리게 된다.





자바는 변수를 제외한 나머지 모든 것들(배열, 객체변수) 을 C의 포인터 형식으로 잡는다.
int test[]; 이렇게 사용하면, c처럼 배열이 생성된게 아니다.

C에서의 동적할당과 같은 방식인듯 싶다.

test라는 포인터를 만들고, = new int[3]; 으로 동적할당해서 주소 값을 받는다.
즉, test는 int형 변수 3개의 공간의 주소를 담고 있는 껍데기에 불과한다.

다른 객체들도 마찬가지인데, 특히 String. C에서는 char 형으로 배열이나 포인터로 썼지만
여기서는 문자열을 객체로 만들어 놨다. 따라서 변수가 아닌 객체이기 때문에
이 역시도 String test; 하면 껍데기가 만들어지고, 나중에 new로 동적할당을 받아야 한다.

이 원리가 어디서 적용이 되냐하면, String의 값을 변경할 때 사용된다.

원래 문자열은 자체의 변경은 불가능하다.
그래서 우리는 "1번 문자열" , "2번 문자열" 이 있다고 가정했을 때

"1번 문자열" 은 주소가 100번지이고, "2번 문자열"은 주소가 500번지이다.

test에 100번지가 들어가 있다면 test를 출력하면 "1번 문자열" 이란 글자가 나온다.
이때, test의 문자를 바꾸려면 test에 500번지 주소를 넣어 주는 것이다.

그러면 "2번 문자열" 이란 글자가 나오는데, 이 상황을 모르고 쓴다면
tset에 "1번 문자열"이란 글자가 들어있는데, 이걸 지우고 "2번 문자열"로 고쳐쓴거라 착각하게 된다.





무튼, String 객체에서도 마찬가지이다.
String str = new String("test");  new로 동적할당 받아서 test의 넣고 그 주소를 넘겨주는 셈이다.


여기서 추가적으로. new String("test")도 가능하고 "test"도 가능하다.
차이점이 중요한데, 위에서 설명했듯 포인터를 이용한 동적할당 방식이라고 했다.

String str1 = "test";
String str2 = "test";

라고 쓴다면 당연히 출력은 둘다 test가 나온다.
음.. 뭐랄까 ROdata 영역에 test가 써지고 그 곳이 100번지라고 가정할 때
str1 과 str2는 모두 100번지를 가르키게 된다. 동일한 위치를 가르키는 것이다.

하지만 new String은 동적처럼. 공간을 직접 할당해서 그 안에 test라는 값을 담는다.
String str1 = new String("test");
String str2 = new String("test");

라고 사용하면 str1과 str2는 각각의 공간을 할당 받아서 test라는 값을 담은 것이다.
물론 가지고 있는 값이 동일하기 때문에 출력시 결과는 같게 된다.

하지만 자바에서 많이 시험해보던 string의 == 이 되는지의 차이가 발생한다.
여태 객체라서 무조건 equals를 써야 한다라고 알고 있었지만, 실제 원리는 그렇지 않다.
해당 변수가 어떤 존재인지. 그래서 무엇을 비교하는지가 중요했다.

계속 설명했지만, 객체의 변수는 포인터와 같은 방식이라고 했다.

따라서 str1, str2는 주고 값을 담게 되고, 따라서 if(str1 == str2) 을 비교한다면
str1의 주소와 str2의 주소를 비교하게 되는 것이다.

= "test"; 라고 작성한 경우. 당연히 동일한 주소를 가르키므로 같다고 성립된다.
당연히, if(str1 == "test") 도 성립된다. 이유는, 여기서 비교하는 "test"도 상수이므로
ROdata에 있는 test와 동일한 값이니 따로 공간을 할당하지 않고 같은 곳을 재사용할 것이다.
그러므로 str1과 똑같이 100번지를 가르키게 되는 것이다.

하지만 new String("test")로 만들었다면 이야기가 달라진다.
if(str1 == "test") 에서 test는 ROdata에 있는 100번지 이다. 하지만 str1은 동적으로 메모리를 할당받아서
그 곳에 test라는 값을 넣었기 때문에 당연히 주소가 다른것이다.
당연히 str1 == str2 도 서로 다른 주소이기 때문에 다르다는 결과가 발생한다.


그렇다면 equals는 왜 되는 것일까? 그것은 주소가 아닌 그 주소에 담긴 값을 비교하는 것이기 때문이다.
주소가 어디든 서로간의 값을 비교 하기 때문에 둘이 같다는게 성립된다.

내가 알던 내용들이 결과는 맞지만, 이유가 틀렸던 것이다.
그냥 막연히 자바에서 문자열을 비교할 땐 == 가 안되고 equals를 사용해야 한다고만 알았던..




자바에서는 0,1 로 참, 거짓을 구별 할 수 없다.
자바에는 boolean이라는 true, false 로 판단을 한다.
따라서 C언어에서 while(1) 같은 문법은 자바에서 통하지 않는다. while(true)라고 써야 한다.
물론, while(1==1) 이런 식으로 써도 되고.. 변수 잡아줘서 값 넣고 1과 같은지
while(t ==1) 이런식으로 사용은 가능하다. 다만 while(1) 요놈을 그냥 막연히 바꾸자면 잠깐 멍하게 되니까- -;





자바에서 수행할 수 없는 기능들

getch(), getche()
키보드로 입력 시 바로 값을 읽어 들이는 기능이 없다. (콘솔기준)
GUI에 리스너나 이런 것들은 있지만, 콘솔로는 없다. 사실.. 자바에서 콘솔로 위와 같은 기능을 쓸일도 없긴하지만;
C의 게임 프로그램을 억지로 자바 콘솔로 바꾸려니 문제가 있어서..


System("cls")
콘솔 화면의 내용을 지우는 것인데, 없다고 한다 - -;
테트리스나 다른 게임들을 보면 화면이 변하는데,
사실은 이전 화면을 모두 지우고 아주 약간 변한 그림을 새로 그리는 것의 반복이다.
마치.. 어릴적 책의 모서리에 그림을 조금씩 다르게 그려서 빠르게 넘기면 움직이는 것 처럼.


gotoxy()[?]
물론, 움직인 부분만 살짝 수정도 가능하다. 움직인 부분을 그리고, 지나간 부분을 지우는 식으로.
워낙 빠르다 보니 움직이는 것 처럼 보이는 것이다.

이게 가능한 이유가 gotoxy() 함수 같은, 실제 함수는 아니고 일반적으로 이렇게 부르는데
콘솔에서 커서를 원하는 좌표로 이동시켜주는 기능이다. 하지만 자바에서 이것 또한 안된다.


자바에서 안되는게 왜 이렇게 많냐? 무지 쓸모 없어 보일 수도 있겠지만.
엄연히 "콘솔"이라는 범위 내에서의 이야기 이다. GUI. 즉 그래픽화면으로 만드는 것에는 전혀 문제가 없다.

오히려 더 쉽고 편할지도.. 마우스로 클릭으로도 인식되고, 여러가지 좋은 점이 많다.

단지. C의 게임 프로그램을 억지로 자바 콘솔로 바꿔 보자는 시도에서 발생한 몇가지 다른 점을 적은 것이다.



추가적으로 cls에 관해서 조금 이야기 하자면
화면을 지우는 것 없이 계속 새로운 화면을 계속 찍는 경우.
그 화면이 이전 화면과 동일한 위치에 찍힌다면. 콘솔화면에서 스크롤이 내려가고
그 자리에 그대로 새로운 화면이 찍히면 마치 변한 것처럼 보인다.
하지만 스크롤을 위로 올려보면 이전 그림들이 수두룩하게 남아있다..- 0-ㅋㅋ
움직일 때마다 스크롤이 조금씩 이동하지만 화면보느라 정신없어서 딱히 느껴질 정도는 아니다.

그리고 어떤 경우에 필요한지 모르겠지만, 화면을 꼭 전부 지워야 한다면.
" " 공백의 문자를 for으로 이용해서 화면의 크기만큼. 또는 원래 있던 텍스트들의 최대 길이 만큼
반복 시켜주면 모두 공백으로 채워져서 마치. 화면이 지워진 것 처럼 보일 수 있다.