앞으로 자바의 정석을 공부하려고 한다. 점프투자바를 통해 전체적으로 기본적인 공부를 했지만 아직 이해가 되지 않는 부분이 있다. 자바의 정석을 공부하면서 이해가 안됐던 부분이나 중요하다고 생각하는 부분을 중점적으로 공부한 후 포스팅할 예정이다. 스케줄 상으로 자바의 정석을 한달 이내로 공부하는 것을 목표로 두고 있기 때문에 세세한 것을 하나하나 공부하기에는 시간이 부족하므로 빠르게 공부한 후에 스프링 강의를 들으려고 한다.
JVM를 직역하면 자바를 실행하기 위한 가상 머신(컴퓨터)이다. Virtal Machine이란 소프트웨어로 구현된 하드웨어를 뜻하는 넓은 의미의 용어이다. 넓은 의미로는 그렇지만 실제 컴퓨터가 아닌 소프트웨어로 구현된 컴퓨터라는 뜻으로 컴퓨터 속의 컴퓨터(소프트웨어)라고 이해하면 된다. 자바로 작성된 애플리케이션은 모두 JVM에서만 실행되기 때문에 자바 애플리케이션을 실행하기 위해서는 반드시 JVM이 필요하다.
일반 애플리케이션의 코드는 OS만 거치고 하드웨어에 전달되는데에 반해 자바 애플리케이션은 JVM -> OS -> 컴퓨터(하드웨어)로 한 과정을 더 거치기 때문에 실행 시에 코드를 해석(interprete)하는 속도가 상대적으로 느리다는 단점을 가지고 있다. 자바 소스코드, 즉 원시코드(.java)는 OS가 인식하지 못한다. OS가 인식할 수 있는 코드는 기계어이다. JVM이 원시코드(.java)를 Java bytecode(.class)로 바꾸어 OS가 코드를 이해할 수 있도록 해준다. 최근에는 향상된 기술로 인해 속도의 격차를 많이 줄였다.
JVM이라는 과정을 한번 더 거치는 특징이 단점이기도 하지만 장점으로 작용할 수도 있다. 일반 애플리케이션은 OS와 바로 맞붙어 있기 때문에 OS에 종속적이다. 다른 OS에서 실행시키기 위해서는 애플리케이션을 그 OS에 맞게 변경해야 한다. 반면 자바 애플리케이션은 JVM하고만 상호작용을 하기 때문에 OS에 독립적이다. 어떠한 OS에서도 실행이 가능하다. 단, JVM은 OS에 종속적이기 때문에 해당 OS에 맞는 JVM을 설치해야 한다. JVM의 특성 덕분에 자바의 장점 중의 하나인 "Write once, run everywhere" 이 가능해졌다.
변수는 기본형과 참조형 두가지로 나눌 수 있다. 기본형 변수는 실제 값(data)을 저장하는 반면, 참조형 변수는 어떤 값이 저장되어 잇는 주소(memory address)를 값으로 갖는다. 기본형에는 논리형(boolean), 문자형(char), 정수형(byte,short,int,long), 실수형(float,double)이 있다. 참조형은 기본형을 제외한 나머지 타입이다. 지금까지 새로운 객체를 생성할 때 참조형 변수를 사용한 것이다. 예를 들어
Scanner scanner = new Scanner(System.in);
이 코드를 해석하면 Scanner라는 클래스의 객체를 새로 생성해서 그 주소를 참조형 변수 scanner에 저장한 것이다.
final int MAX_SPEED; // 컴파일 에러!
final int MAX_SPEED = 10;
MAX_SPEED = 5; // 컴파일 에러!!
int tryangleArea = 5*5 /2
밑변 * 넓이 / 2라는 사실을 알긴 하지만 코드를 더욱 명확히 보이기 위해 상수를 이용한다.
final int width = 5;
final int height = 5;
int tryangleArea = width * height / 2;
이렇게 코드를 쓰면 확실히 이해하기 쉽고 코드를 변경할 때도 width의 값을 바꿔 쓰기만 하면 된다.
리터럴이란 우리가 평소에 알고 있는 상수를 의미한다. (1, 231, 0.124, 'A') 자바에서의 상수가 일반적인 상수의 의미와 다른 '저장공간'을 뜻하는 의미이기 때문에 차별화를 위해 리터럴이라는 문자를 상수 대신 사용하고 있다.
변수에 타입이 있는 것처럼 리터럴에도 타입이 있다. 지금까지 int를 많이 사용해왔기 때문에 리터럴에 타입이 있는지 몰랐다. 왜냐하면 default로 사용되는 int나 double같은 경우에는 타입을 작성하지 않아도 되기 때문이다. long같은 경우에는 리터럴 뒤에 l, L을 붙여주면 되고, float는 f,F를 붙여주면 된다.
long bigNumber = 10000000000000000L;
float pointNum = 3.14f;
char c = 'A';
char c = "A"; // 컴파일 에러!
String word = "java";
String word = 'java'; // 컴파일 에러!
문자(한 글자)를 사용할 때만 작은 따옴표를 사용하고 String을 이용해서 문자열을 저장하고 싶을 때는 큰 따옴표를 사용해야 한다.
점프투자바를 공부하면서 확실하지 않았던 것중에
int n = 7
String s = "" + n; // 7 출력
이 있었는데 자바의 정석을 공부하면서 확실히 알게 되었다.
다른 타입의 변수를 "" 혹은 " "등의 문자열과 같은 것을 더해서 저장하게 되면 String으로 저장이 된다.
printf를 사용하여 변수를 출력하고 싶을때 지시자(specifier)를 통해 변수의 값을 여러가지 형시으로 변환하여 출력할 수 있다.(%d-10진 정수, %f- 소수점)
float pi = 3.14f;
int n =10;
System.out.printf("%010d%n",n);
System.out.printf("%10d%n",n);
System.out.printf("%010f%n",pi);
System.out.printf("%10.10f%n",pi);
0000000010
10
003.140000
3.1400001049
char 타입의 변수에 문자를 저장하면 그 문자가 저장되는 것이 아닌 문자의 유니코드(정수)가 저장된다. char 타입 변수에 유니코드를 저장해도 그에 해당하는 문자가 출력된다.
char c1='A';
int code1=(int)c1;
char c2=65;
int code2=(int)c2;
System.out.printf("%c=%d\n",c1,code1); // A=65 출력
System.out.printf("%c=%d\n",c2,code2); // A=65 출력
타입이 표현할 수 있는 값의 범위를 넘어서는 것을 오버플로우라고 한다. 오버플로우가 발생했다고 해서 에러가 발생하는 것은 아니지만 원하는 값이 나오지 않는다.
byte n = 127;
n += 1;
System.out.println(n); // -128 출력
변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형변환이라고 한다. 형변환을 하는 방법은 형변환을 하고자하는 변수나 리터럴 앞에 괄호를 치고 그 안에 원하는 타입을 적어주면 된다.
double d = 8.1212123123123232313;
System.out.println(d); // 8.1212123123123232313 출력
int n = (int) d;
System.out.println(n); // 8 출력
float f = (float) d;
System.out.println(f); // 8.121212 출력