Java 기초
Java의 특징
운영체제에 독립적
JVM을 사용하는 구조 덕분에 같은 코드로 모든 운영체제에서 실행이 가능하다.
JVM (Java Virtual Machine)
개발자가 작성한 코드를 컴파일러가 JVM이 실행할 수 있는 bytecode로 변환해주면 JVM은 bytecode를 각 플랫폼에 맞는 기계어로 변환해준다.
객체 지향 언어 (Object-oriented language)
모든 기능을 객체로 만들어 사용한다.
함수형 프로그래밍 지원
Java 8 버전부터 람다식, 스트림을 지원한다.
Garbage collection
메모리의 생성과 소멸을 개발자가 따로 설계하지 않고 garbage collector가 사용하지 않는 메모리를 수거한다.
변수와 타입 (Variable and type)
기본형과 참조형
기본형
boolean
- 정수형
byte
,short
,char
,int
,long
- 실수형
float
,double
참조형
String
, 배열, enum
, 인터페이스, 클래스 등 다른 모든 데이터 타입
기본형과 참조형의 차이
변수를 지정하고 대입했을 때 변수가 어떻게 값을 저장하는가에 따라 나뉜다.
기본형의 경우 변수에 담을 때 값 그 자체를 저장하게 되고 참조형의 경우 변수에 담을 때 값이 저장된 메모리의 힙 영역을 가리키는 주소를 저장하게 된다.
References
- Chapter 4. Types, Values, and Variables
- What's the difference between primitive and reference types?
Endianness
메모리에 값을 저장할 때 각 바이트를 배열하는 순서를 endianness라고 한다.
Big-endian은 더 큰 값을 표현하는 바이트가 더 앞에 오고 little-endian은 더 작은 값은 표현하는 바이트가 앞으로 온다.
Endianness가 다른 플랫폼들이 있기 때문에 변환이 필요한지 잘 확인해야 한다.
2's complement
정수형 타입에서 음수를 표현할 때 2's complement를 이용한다.
2's complement는 각 비트를 반전시키고 거기에 1을 더함으로써 구할 수 있다.
2's complement로 음수를 표현하는 경우 덧셈과 뺄셈이 자연스럽게 가능하다.
Further Reading
부동소수점 연산 (Floating-point arithmetic)
정수형의 범위를 넘어가는 숫자를 표현할 때 부동소수점을 사용한다.
Character
char
타입을 다루는 여러 static 메소드를 담은 클래스이다.
getNumericValue
public static int getNumericValue(char ch)
ch
매개변수가 담은 문자가 숫자일 때 그 숫자를 int
타입으로 반환해준다.
forDigit
public static char forDigit(int digit, int radix)
digit
매개변수가 담은 그 숫자에 해당하는 char
로 반환해준다.
radix
매개변수로 몇 진법으로 표현할지 결정한다.
Double.parseDouble
public static double parseDouble(String s) throws NumberFormatException
문자열 s
가 double
타입으로 표현 가능한 문자열이면 double
타입으로 반환해준다.
문자열 (String)
String
기본 문자열 클래스다.
인스턴스가 한 번 생성되면 그 값을 읽기만 가능하고 변경할 수 없다.
StringBuffer
String
클래스와 다르게 인스턴스가 생성된 이후 그 값을 변경, 추가할 수 있다.
Thread-safe하다.
StringBuilder
여러 개의 문자열을 더할 때 중간 결과에 해당하는 String
인스턴스를 만들지 않기 위해 사용한다.
간단한 문자열 연결의 경우 컴파일러에서 알아서 '+' 연산을 StringBuilder
로 최적화해준다.
반복문으로 '+' 연산을 하는 경우만 StringBuilder
를 사용해도 무방하다.
StringBuffer
와 호환되는 API를 지원하지만 동기화를 보장하지 않기 때문에 싱글스레드 환경에서 사용해야 한다.
StringBuffer
보다 빠르기때문에 멀티스레드 환경이 아니라면 StringBuilder
를 사용하는 것이 좋다.
References
StringTokenizer
문자열을 구분자로 나누어 토큰으로 만들어준다.
기본 구분자는 공백이다.
공식 문서에 따르면, 호환성을 위해 유지되는 legacy class이기 때문에 새로운 코드를 작성할 때는 String.split
이나 java.util.regex
패키지를 사용하는 것이 권장된다.
Further Reading
- Formatter (Java SE 11 & JDK 11 )
- Is it better practice to use String.format over string Concatenation in Java?
연산자 (Operator)
연산자 우선순위
다음 표에서 위에 있는 연산자부터 실행된다.
References
>>
vs. >>>
>>
는 오른쪽으로 shift하는데 제일 왼쪽에 추가되는 비트가 부호에 따라 달라지고 >>>
는 sign에 상관 없이 0이 추가된다.
References
콘솔 입출력 (I/O)
Scanner
System.in
또는 파일 등에 담긴 텍스트를 읽을 때 사용한다.
정규표현식을 활용하여 토큰화도 가능하다.
조건문
switch
expressions
JDK 14부터 switch
가 statement가 아닌 expression으로도 사용 가능하다.
추가로 :
가 아닌 ->
로 case
문을 구성할 수 있다
// ":" 사용
switch (num) {
case 1:
str = 1 + "st";
break;
...
}
// "->" 사용
switch (num) {
case 1 -> str = "one";
// ","로 여러 case를 묶어서 표현할 수 있다.
case 2, 3, 4, 5 -> str = "bigger than one";
...
}
// switch expression
str = switch (num) {
case 1 -> "one";
...
// expression이므로 값이 무조건 존재해야 해서 default가 필수다.
default -> "";
}
// switch expression에서 ":" 사용시 yield문으로 값을 생산해야한다.
str = switch (num) {
case 1:
yield "one";
...
default:
yield "";
}
->
를 사용하면 break
나 yield
를 쓰지 않아도 되고 여러 개의 case
문을 묶어서 표현할 수 있어서 편리하다.
물론 expression으로 사용할 때 ->
이후 여러 줄의 코드를 블록으로 나타내는 경우 블록 내에서 yield
문을 사용해야 한다.
References
- The if-then and if-then-else Statements
- The switch Statement
- 14.9. The
if
Statement - 14.11. The
switch
Statement
반복문
Enhanced for
배열이나 컬렉션을 iteration하기 위한 특수한 for
문의 형태이다.
가능한 경우라면 이 형태를 활용하는 것이 권장된다.
class EnhancedForDemo {
public static void main(String[] args){
int[] numbers =
{1,2,3,4,5,6,7,8,9,10};
for (int item : numbers) {
System.out.println("Count is: " + item);
}
}
}
References
배열 (Array)
Arrays.copyOf
public static <T> T[] copyOf(T[] original, int newLength)
배열을 시작부터 newLength
만큼 복사해준다.
newLength
가 original.length
보다 작으면 그만큼 잘라내고, original.length
보다 크면 그만큼 해당 타입의 초기값으로 채워준다.
Arrays.copyOfRange
public static <T> T[] copyOfRange(T[] original, int from, int to)
배열을 배열 내의 from
index와 to
index로 범위를 정하여 복사해준다.
to
index의 직전에 있는 원소까지 복사되는 것에 유의해야 한다.
배열의 끝까지 복사하려고 하면 to
값은 original.length
가 된다.
System.arraycopy
public static void arraycopy(
Object src, int srcPos, Object dest, int destPos, int length)
src
의 srcPos
index부터 length
만큼의 값을 복사하여 dest
에 destPos
index부터 넣어준다.