자바의 정석

SUADI·2022년 6월 1일

앞으로 자바의 정석을 공부하려고 한다. 점프투자바를 통해 전체적으로 기본적인 공부를 했지만 아직 이해가 되지 않는 부분이 있다. 자바의 정석을 공부하면서 이해가 안됐던 부분이나 중요하다고 생각하는 부분을 중점적으로 공부한 후 포스팅할 예정이다. 스케줄 상으로 자바의 정석을 한달 이내로 공부하는 것을 목표로 두고 있기 때문에 세세한 것을 하나하나 공부하기에는 시간이 부족하므로 빠르게 공부한 후에 스프링 강의를 들으려고 한다.

1장 - 자바를 시작하기 전에

1.4 JVM(Java Virtual Machine)

  • 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" 이 가능해졌다.

2장 - 변수

2.0 변수의 타입

변수는 기본형과 참조형 두가지로 나눌 수 있다. 기본형 변수는 실제 값(data)을 저장하는 반면, 참조형 변수는 어떤 값이 저장되어 잇는 주소(memory address)를 값으로 갖는다. 기본형에는 논리형(boolean), 문자형(char), 정수형(byte,short,int,long), 실수형(float,double)이 있다. 참조형은 기본형을 제외한 나머지 타입이다. 지금까지 새로운 객체를 생성할 때 참조형 변수를 사용한 것이다. 예를 들어

Scanner scanner = new Scanner(System.in);

이 코드를 해석하면 Scanner라는 클래스의 객체를 새로 생성해서 그 주소를 참조형 변수 scanner에 저장한 것이다.

  • 자료형 타입(data type)과 타입(type)의 차이는 포함관계이다. 자료형 타입이 타입에 속해있다. 보통 자료형 타입은 기본형 변수의 타입을 이야기하고, 타입은 객체의 주소를 저장하는 참조형 변수의 타입을 뜻한다.

2.1 기본형(Primitive type)

  • 기본형 타입의 크기(byte 단위)
    boolean - 1
    char - 2
    byte - 1
    short -2
    int - 4(정수형 default)
    long - 8
    float - 4
    double - 8(실수형 default)

2.2 상수와 리터럴(constant, literal)

  • 상수의 특징 첫번짼는 변수와 마찬가지로 값을 저장할 수 있는 공간이지만 변수와 달리 값을 저장하면 다른 값으로 변경할 수 없다. 값을 변경할 수 없도록 하기 위해 상수 앞에 final이라는 키워드를 사용해서 고정시킨다.
  • 두번째 특징은 상수는 선언과 동시에 초기화해야 한다. 초기화는 선언된 변수에 데이터를 처음으로 저장하는 행위를 말한다.
  • 세번째 특징은 개발자들 사이의 암묵적인 관례인데 상수의 이름을 대문자로 사용하는 것이다.
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 타입을 사용해서 문자를 저장하고 싶을 때 작은 따옴표를 사용해서 저장한다.
char c = 'A';
char c = "A"; // 컴파일 에러!
String word = "java";
String word = 'java'; // 컴파일 에러!
  • 문자(한 글자)를 사용할 때만 작은 따옴표를 사용하고 String을 이용해서 문자열을 저장하고 싶을 때는 큰 따옴표를 사용해야 한다.

  • 점프투자바를 공부하면서 확실하지 않았던 것중에

int n = 7
String s = "" + n; // 7 출력

이 있었는데 자바의 정석을 공부하면서 확실히 알게 되었다.
다른 타입의 변수를 "" 혹은 " "등의 문자열과 같은 것을 더해서 저장하게 되면 String으로 저장이 된다.

2.3 printf

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
  • 지시자 앞에 10을 쓰면 숫자의 길이를 포함하여 오른쪽으로 총 10칸 미뤄진다. 010을 쓰면 숫자 앞에 숫자의 길이를 포함하여 0이 총 10칸만큼 생긴다. .10을 쓰면 소숫점 총 10자리까지 출력된다.

4.1 문자형(char)

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 출력
  • 문자를 코드로 변환하는 것을 인코딩, 반대를 디코딩이라고 한다.

4.3 정수형(byte,short,int,long)

타입이 표현할 수 있는 값의 범위를 넘어서는 것을 오버플로우라고 한다. 오버플로우가 발생했다고 해서 에러가 발생하는 것은 아니지만 원하는 값이 나오지 않는다.

byte n = 127;
n += 1;
System.out.println(n); // -128 출력
  • 예를 들어 값의 범위가 127까지인 byte 타입의 변수에 127을 저장한 후 1을 더하면 128이 되어야하지만 범위를 벗어나기 때문에 범위를 한바퀴를 돌아서 byte 타입의 최솟값인 -128이 출력된다.

5.1 형변환(casting)

변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형변환이라고 한다. 형변환을 하는 방법은 형변환을 하고자하는 변수나 리터럴 앞에 괄호를 치고 그 안에 원하는 타입을 적어주면 된다.

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 출력

0개의 댓글